[pacman-dev] dangerous symlink handling with --root option
Hi again, (and sorry again for any split lines) Okay, so I was fooling around with the --root option again, and after I realized from one of Xavier's posts that pre/post install scriptlets won't be run at all until /bin/sh (from bash) is installed, I figured I should install the packages twice. This led to two issues. I have a bash script (attached) that basically does: pkglist=( ... bunch o' base packages ... ) mkdir /tmp/pacman.test pacman -U --root /tmp/pacman.test ${pkglist[*]} pacman -U --root /tmp/pacman.test ${pkglist[*]} The second install of coreutils causes: error: cannot remove file '/tmp/pacman.test/usr/bin/sleep': Read-only file system error: failed to commit transaction (transaction aborted) error: failed to release transaction (could not commit transaction) First Issue: CPU usage then goes to 100%, so I assume that pacman has gone into an infinite loop somewhere. Second Issue: the real concern is the "Read-only file system" error, since /tmp is on a tmpfs and is definitely not read-only. My / partition is read-only though, and # ls -l /tmp/pacman.test/usr/bin/sleep lrwxrwxrwx 1 root root 10 2007-08-16 16:13 /tmp/pacman.test/usr/bin/sleep -> /bin/sleep So pacman was following the absolute symlink *out* of the --root and trying to remove /bin/sleep from my main arch install ?? Cheers, Jeremy Get news delivered with the All new Yahoo! Mail. Enjoy RSS feeds right on your Mail page. Start today at http://mrd.mail.yahoo.com/try_beta?.intl=ca
On Mon, Aug 20, 2007 at 10:38:26PM -0400, Mister Dobalina wrote:
Hi again,
(and sorry again for any split lines)
Okay, so I was fooling around with the --root option again, and after I realized from one of Xavier's posts that pre/post install scriptlets won't be run at all until /bin/sh (from bash) is installed, I figured I should install the packages twice. This led to two issues. I have a bash script (attached) that basically does:
I'm missing some basic *nix knowledge here :) When I saw this problem, I added /bin/sh and /bin/bash to my empty chroot, but it still didn't work. Now, I just made an installation of filesystem and all its dependencies, and it seemed to work. The filesystem scriptlet complained though because grep was missing, but at least it was run.
pkglist=( ... bunch o' base packages ... ) mkdir /tmp/pacman.test pacman -U --root /tmp/pacman.test ${pkglist[*]} pacman -U --root /tmp/pacman.test ${pkglist[*]}
The second install of coreutils causes:
error: cannot remove file '/tmp/pacman.test/usr/bin/sleep': Read-only file system error: failed to commit transaction (transaction aborted) error: failed to release transaction (could not commit transaction)
First Issue: CPU usage then goes to 100%, so I assume that pacman has gone into an infinite loop somewhere.
I think this is the same issue as described there (in the quoted mails) : http://www.archlinux.org/pipermail/pacman-dev/2007-August/009084.html ie, when a -U operation failed, pacman always looped when trying to unregister the databases. My fix has just recently been pushed to git.
Second Issue: the real concern is the "Read-only file system" error, since /tmp is on a tmpfs and is definitely not read-only. My / partition is read-only though, and
# ls -l /tmp/pacman.test/usr/bin/sleep
lrwxrwxrwx 1 root root 10 2007-08-16 16:13 /tmp/pacman.test/usr/bin/sleep -> /bin/sleep
So pacman was following the absolute symlink *out* of the --root and trying to remove /bin/sleep from my main arch install ??
Hmm, the question I would rather ask is wtf is that symlink in the first place ? sleep isn't a symlink here, it's a regular file. But even then, all other symlinks I've in the --root are correct, they don't point to somewhere outside it. $ ls -l foo/bin/sh lrwxrwxrwx 1 root root 4 mai 15 21:14 foo/bin/sh -> bash* $ ls -l foo/bin/sleep -rwxr-xr-x 1 root root 14380 aoû 16 22:13 foo/bin/sleep* But I'm also curious about your question.. Looks strange that pacman follows that symlink.
--- Xavier <shiningxc@gmail.com> wrote:
Hi again,
(and sorry again for any split lines)
Okay, so I was fooling around with the --root
again, and after I realized from one of Xavier's
On Mon, Aug 20, 2007 at 10:38:26PM -0400, Mister Dobalina wrote: option posts
that pre/post install scriptlets won't be run at all until /bin/sh (from bash) is installed, I figured I should install the packages twice. This led to two issues. I have a bash script (attached) that basically does:
I'm missing some basic *nix knowledge here :) When I saw this problem, I added /bin/sh and /bin/bash to my empty chroot, but it still didn't work.
Just bash in an empty chroot won't run because of missing shared libraries -- an ldd of /bin/bash shows it needs some libraries from readline, ncurses, and glibc.
Now, I just made an installation of filesystem and all its dependencies, and it seemed to work. The filesystem scriptlet complained though because grep was missing, but at least it was run.
pkglist=( ... bunch o' base packages ... ) mkdir /tmp/pacman.test pacman -U --root /tmp/pacman.test ${pkglist[*]} pacman -U --root /tmp/pacman.test ${pkglist[*]}
The second install of coreutils causes:
error: cannot remove file '/tmp/pacman.test/usr/bin/sleep': Read-only file system error: failed to commit transaction (transaction aborted) error: failed to release transaction (could not commit transaction)
First Issue: CPU usage then goes to 100%, so I assume that pacman has gone into an infinite loop somewhere.
I think this is the same issue as described there (in the quoted mails) :
http://www.archlinux.org/pipermail/pacman-dev/2007-August/009084.html
ie, when a -U operation failed, pacman always looped when trying to unregister the databases. My fix has just recently been pushed to git.
Ok great, glad you already knew about it.
Second Issue: the real concern is the "Read-only file system" error, since /tmp is on a tmpfs and is definitely not read-only. My / partition is read-only though, and
# ls -l /tmp/pacman.test/usr/bin/sleep
lrwxrwxrwx 1 root root 10 2007-08-16 16:13 /tmp/pacman.test/usr/bin/sleep -> /bin/sleep
So pacman was following the absolute symlink *out* of the --root and trying to remove /bin/sleep from my main arch install ??
Hmm, the question I would rather ask is wtf is that symlink in the first place ? sleep isn't a symlink here, it's a regular file.
/usr/bin/sleep should be a symlink to /bin/sleep on your system. This is actually due to a bug report I filed when I first started using archlinux a few years ago. sleep was originally being installed in /usr/bin, but this made it inaccessible during parts of rc.sysinit/rc.shutdown for people who have /usr on a separate partition. I always add a sync; sleep 5 at the end of rc.shutdown, because my hard drive has a large cache, and archlinux runs so quickly that it was powering down my computer before the hard drive cache was finished being written out to disk, causing an fsck run on every boot. Anyways, Judd agreed that sleep should go into /bin, but put a symlink in /usr/bin for anybody that wasn't expecting sleep to move.
But even then, all other symlinks I've in the --root are correct, they don't point to somewhere outside it.
I guess it depends on whether the package maintainer made it a relative or absolute symlink?
$ ls -l foo/bin/sh lrwxrwxrwx 1 root root 4 mai 15 21:14 foo/bin/sh -> bash* $ ls -l foo/bin/sleep -rwxr-xr-x 1 root root 14380 aoû 16 22:13 foo/bin/sleep*
foo/bin/sh -> bash is a relative symlink, points to the same directory that the link itself is in. And foo/bin/sleep is indeed the actually binary as it is supposed to be installed. But you should really be trying # ls -l foo/usr/bin/sleep to see where it points. cheers, Jeremy Be smarter than spam. See how smart SpamGuard is at giving junk email the boot with the All-new Yahoo! Mail at http://mrd.mail.yahoo.com/try_beta?.intl=ca
On Tue, Aug 21, 2007 at 10:16:19AM -0400, Mister Dobalina wrote:
$ ls -l foo/bin/sh lrwxrwxrwx 1 root root 4 mai 15 21:14 foo/bin/sh -> bash* $ ls -l foo/bin/sleep -rwxr-xr-x 1 root root 14380 aoû 16 22:13 foo/bin/sleep*
foo/bin/sh -> bash is a relative symlink, points to the same directory that the link itself is in. And foo/bin/sleep is indeed the actually binary as it is supposed to be installed. But you should really be trying
# ls -l foo/usr/bin/sleep
to see where it points.
oops, yes, I was looking at the wrong one ;)
But even then, all other symlinks I've in the --root are correct, they don't point to somewhere outside it.
I guess it depends on whether the package maintainer made it a relative or absolute symlink?
So isn't it a bug in the package rather than in pacman? Shouldn't there be only relative symlinks?
--- Xavier <shiningxc@gmail.com> wrote:
So isn't it a bug in the package rather than in pacman? Shouldn't there be only relative symlinks?
I don't know if any package maintainers have reasons for prefering an absolute symlink over a relative one. Either way, I think there is something wrong with the following test case. Note that it actually only uses a relative symlink, and does not involve the --root option. Make and install the package in the following PKGBUILD. Just install it with "-U". ################## pkgname=symlinktest pkgver=0.1 pkgrel=1 arch=(i686 x86_64) build() { mkdir -p ${startdir}/pkg/tmp cd ${startdir}/pkg/tmp ln -s tmpfs/file symlink } ################## Then issue the following commands (as root): # mkdir /tmp/tmpfs # mount -t tmpfs -o size=1k tmpfs /tmp/tmpfs # touch /tmp/tmpfs/file # mount -o remount,ro /tmp/tmpfs # pacman -R symlinktest On my system, pacman (v 3.0.5-3) goes into that infinite loop, after giving the following output: error: cannot remove file '/tmp/symlink': Read-only file system error: failed to commit transaction (cannot remove all files for package) error: failed to release transaction (could not commit transaction) Why should /tmp/tmpfs being read-only affect removing that symlink? Doing # mount -o remount,rw /tmp/tmpfs # pacman -R symlinktest works as expected though, and /tmp/tmpfs/file remains intact, so I guess there is not really any danger here. So it seems pacman can't remove symlinks which point to files which live on read-only filesystems, which I guess is not such a serious issue, since most people don't run with read-only root partitions. Curious though. I guess I'll stop wasting your time now :) Jeremy Be smarter than spam. See how smart SpamGuard is at giving junk email the boot with the All-new Yahoo! Mail at http://mrd.mail.yahoo.com/try_beta?.intl=ca
On Tue, Aug 21, 2007 at 11:20:33AM -0400, Mister Dobalina wrote:
Why should /tmp/tmpfs being read-only affect removing that symlink? Doing
# mount -o remount,rw /tmp/tmpfs # pacman -R symlinktest
works as expected though, and /tmp/tmpfs/file remains intact, so I guess there is not really any danger here. So it seems pacman can't remove symlinks which point to files which live on read-only filesystems, which I guess is not such a serious issue, since most people don't run with read-only root partitions. Curious though.
Yep, there is probably a problem here : 164 /* If we fail write permissions due to a read-only filesystem, abort. 165 * Assume all other possible failures are covered somewhere else */ 166 if(access(file, W_OK) == -1) { 167 if(errno != EACCES && access(file, F_OK) == 0) { 168 /* only return failure if the file ACTUALLY exists and we can't write to 169 * it - ignore "chmod -w" simple permission failures */ 170 _alpm_log(PM_LOG_ERROR, _("cannot remove file '%s': %s"), 171 file, strerror(errno)); 172 return(0); 173 } 174 } from man access : access() checks whether the calling process can access the file pathname. If pathname is a symbolic link, it is dereferenced.
--- Xavier <shiningxc@gmail.com> wrote:
Now, I just made an installation of filesystem and all its dependencies, and it seemed to work. The filesystem scriptlet complained though because grep was missing, but at least it was run.
Try installing bash and all its dependencies, in the proper order (so, without using "-Ud"). Then install glibc a second time. You'll notice that the first time glibc is installed it has no complaints, but the second time the scriptlet complains about missing grep and awk and other things. I infer from this that the scriptlet is not running at all before bash is installed, since it should complain about missing grep and awk both times. This has implications for this method of installing archlinux: http://wiki.archlinux.org/index.php/Install_Arch_from_within_another_distro which I've added to the "discussion" section of that wiki page. My original problem of incorrect permissions on /tmp was because I was installing neither bash nor coreutils into my chroot (using zsh instead), and using "-Ud" to install filesystem. Jeremy Make free worldwide PC-to-PC calls. Try the new Yahoo! Canada Messenger at http://ca.messenger.yahoo.com/
participants (2)
-
Mister Dobalina
-
Xavier