#638979 grub-mount shows symbolic links in mounted partitions as ordinary files

Package:
grub-common
Source:
grub2
Description:
GRand Unified Bootloader (common files)
Submitter:
Aki
Date:
2012-11-19 08:39:03 UTC
Severity:
normal
#638979#5
Date:
2011-08-23 13:16:52 UTC
From:
To:
Hello.

A first Debian GNU/Linux Wheezy amd64 (kernel 3.0.0-1-amd64) is
installed in /dev/sda1 as boot/root partition.

A second Debian GNU/Linux Wheezy (kernel 3.0.0-1-486) is installed in
/dev/sdb1 as root partition *skipping  grub installation* using the
expert menu install; the contents of / and /boot in /dev/sdb1 are:

# ls -la init* vmlinu* boot/*
-rw-r--r-- 1 root root  130995 24 lug 17.11 boot/config-3.0.0-1-486
-rw-r--r-- 1 root root 9084991 21 ago 14.34 boot/initrd.img-3.0.0-1-486
-rw-r--r-- 1 root root 1516241 24 lug 17.11 boot/System.map-3.0.0-1-486
-rw-r--r-- 1 root root 2419024 24 lug 17.10 boot/vmlinuz-3.0.0-1-486
lrwxrwxrwx 1 root root      28 21 ago 14.33 initrd.img ->
/boot/initrd.img-3.0.0-1-486
lrwxrwxrwx 1 root root      24 21 ago 14.33 vmlinuz ->
boot/vmlinuz-3.0.0-1-486

The user boots Debian GNU/Linux Wheezy amd64 from /dev/sda1 and then
runs the script /usr/sbin/update-grub2:

# update-grub2
Generating grub.cfg ...
Found background image: /usr/share/images/desktop-base/desktop-grub.png
Found linux image: /boot/vmlinuz-3.0.0-1-amd64
Found initrd image: /boot/initrd.img-3.0.0-1-amd64
Found Debian GNU/Linux (wheezy/sid) on /dev/sdb1
done

When the user boots GNU/Linux Wheezy amd64 from /dev/sda1, he/she finds
that four entries have been generated in /boot/grub/grub.cfg for the
single Debian GNU/Linux kernel installed in /dev/sdb1 (see attached
grub-dump.png and grub.cfg).

I suppose the cause is in /usr/bin/grub-mount.

All the following commands has been given given as root after booting
from /dev/sda1:

# mkdir -p /tmp/mnt
# grub-mount /dev/sdb1 /tmp/mnt/
# cd /tmp/mnt
# ls  -la vmlinu* initrd* boot/vmlinu* boot/initrd* -la
-r--r--r-- 0 root root 22279168 21 ago 14.34 boot/initrd.img-3.0.0-1-486
-r--r--r-- 0 root root  2419024 24 lug 17.10 boot/vmlinuz-3.0.0-1-486
-r--r--r-- 0 root root 22279168 21 ago 14.33 initrd.img
-r--r--r-- 0 root root  2419024 21 ago 14.33 vmlinuz
# cd ..
# umount /tmp/mnt
# mount /dev/sdb1 /tmp/mnt/
# cd /tmp/mnt
# ls  -la vmlinu* initrd* boot/vmlinu* boot/initrd* -la
-rw-r--r-- 1 root root 9084991 21 ago 14.34 boot/initrd.img-3.0.0-1-486
-rw-r--r-- 1 root root 2419024 24 lug 17.10 boot/vmlinuz-3.0.0-1-486
lrwxrwxrwx 1 root root      28 21 ago 14.33 initrd.img ->
/boot/initrd.img-3.0.0-1-486
lrwxrwxrwx 1 root root      24 21 ago 14.33 vmlinuz ->
boot/vmlinuz-3.0.0-1-486
# cd ..
# umount /tmp/mnt

As you can see, after mounting with grub-mount, symlinks are shown as
ordinary files in the mounted partition. This way the script
/usr/lib/linux-boot-probes/mounted/90fallback fails to recognize
symlinks (that it usually skips) at row 24 :

        1 #!/bin/sh
        2 # Fallback in case nothing else works. Look for vmlinu[xz]
file in root and
        3 # /boot, see if there is a matching initrd, and wing it.
        4 . /usr/share/os-prober/common.sh
        5 set -e
        6
        7 partition="$1"
        8 bootpart="$2"
        9 mpoint="$3"
       10 type="$4"
[..cut..]
       22         for kernfile in $(eval ls "$mpoint$kernpat"
2>/dev/null); do
       23                 kernbasefile=$(echo "$kernfile" | sed
"s!^$mpoint!!")
===> 24                 if [ -f "$kernfile" ] && [ ! -L "$kernfile" ]; then
       25                         initrdname=$(echo "$kernfile" | sed
"s/vmlinu[zx]/initrd\*/")
       26                         # Yellow Dog Linux appends .img to it.
       27                         initrdname1="${initrdname}.img"

A possible temporary work-around could be to rename the
/usr/bin/grub-mount to /bin/mount and then run /usr/sbin/update-grub2 again:

# cd /usr/bin/
# mv grub-mount grub-mount.old
# ln -s /bin/mount grub-mount
# ls grub-mount* -la
lrwxrwxrwx 1 root root     10 22 ago 11.04 grub-mount -> /bin/mount
-rwxr-xr-x 1 root root 281744  9 ago 02.46 grub-mount.old
# /usr/sbin/update-grub2

I suppose grub-mount should be fixed to let it recognize symlinks.

Let me know if you need further informations.

Thanks,
Aki.

#638979#10
Date:
2012-01-14 09:35:25 UTC
From:
To:
tag 638979 wont-fix
thanks
grub-mount uses GRUB internal FS modules and it's API doesn't expose
symlinks

#638979#15
Date:
2012-11-16 19:04:19 UTC
From:
To:
affects 638979 +os-prober
thanks

There is already a patch?
http://lists.gnu.org/archive/html/grub-devel/2012-10/msg00021.html
Cheers

#638979#22
Date:
2012-11-18 10:18:13 UTC
From:
To:
No, that fixes a regression in 2.00 which caused any
symlink-to-directory encountered in a directory's contents to cause the
directory to appear as though it were empty.  That bug was not present
in 1.99, where this bug was originally reported in Debian, so please
don't conflate them.

#638979#27
Date:
2012-11-19 08:35:56 UTC
From:
To:
Sorry for my laziness and the low effort to understand a thread I gave
a link :(.

To prove I can give a more effort to this thing I sit down to change
os-prober code to comply with grub-mount feature (symlink behaviour).

A first level of problem is duplicating output of the same kernel/initrd
filename pairs. Duplicates appears because the patterns tried are not
disjunctive at the line 15 of /usr/lib/linux-boot-probes/mounted/90fallback.

for kernpat in /vmlinuz /vmlinux /boot/vmlinuz /boot/vmlinux "/boot/vmlinuz*" \
                "/boot/vmlinux*" "/vmlinuz*" "/vmlinux*" "/kernel-*" "/boot/kernel-*"; do

I don't know why there are pattern pairs /vmlinuz and "/vmlinuz*" and so
on. Shell wild-card "/vmlinuz*" is expanded in the alphabetical order,
so potential /vmlinuz alone is expanded always first if exists. I'm not
certain the reasoning... aha in between is /boot/vmlinuz, so if both
exists /vmlinuz and /boot/vmlinuz, they appear in that order
(/boot/vmlinuz appears before /vmlinuz<something>).


...initrd patterns at the line 27...:
                        initrdname=$(echo "$kernfile" | sed "s/vmlinu[zx]/initrd\*/")
                        # Yellow Dog Linux appends .img to it.
                        initrdname1="${initrdname}.img"

The following patch removes duplicates from expanded patterns of kernels and
initrd images:
--- /usr/lib/linux-boot-probes/mounted/90fallback~ 2012-11-18 20:40:05.050334822 +0100 +++ /usr/lib/linux-boot-probes/mounted/90fallback 2012-11-18 21:16:50.846268406 +0100 @@ -21,6 +21,8 @@ fi for kernfile in $(eval ls "$mpoint$kernpat" 2>/dev/null); do kernbasefile=$(echo "$kernfile" | sed "s!^$mpoint!!") + echo "$kernfile_seen" | fgrep -q " $kernbasefile " && continue + kernfile_seen="$kernfile_seen $kernbasefile " if [ -f "$kernfile" ] && [ ! -L "$kernfile" ]; then initrdname=$(echo "$kernfile" | sed "s/vmlinu[zx]/initrd\*/") # Yellow Dog Linux appends .img to it. @@ -35,7 +37,7 @@ # And Gentoo's also initrdname4=$(echo "$kernfile" | sed "s/kernel/initramfs\*/") foundinitrd=0 - for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null); do + for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null | sort | uniq); do if [ "$initrd" != "$kernfile" ] && [ -f "$initrd" ] && [ ! -L "$initrd" ]; then initrd=$(echo "$initrd" | sed "s!^$mpoint!!") result "$partition:$kernbootpart::$kernbasefile:$initrd:root=$mappedpartition" Before the patch: bobek:~# /usr/lib/linux-boot-probes/50mounted-tests /dev/mapper/vg-deboot /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/boot/vmlinuz-3.2.0-4-amd64:/boot/initrd.img-3.2.0-4-amd64:root=/dev/dm-23 /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 After the patch: bobek:~# /usr/lib/linux-boot-probes/50mounted-tests /dev/mapper/vg-deboot /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/boot/vmlinuz-3.2.0-4-amd64:/boot/initrd.img-3.2.0-4-amd64:root=/dev/dm-23 I hope the above change is worth doing anyway. We can go further and try to identify the identical file's with different filenames. (This problem is introduced by grub-mount behaviour on symlinks.)
--- /usr/lib/linux-boot-probes/mounted/90fallback~zito1 2012-11-19 01:04:58.817863969 +0100 +++ /usr/lib/linux-boot-probes/mounted/90fallback 2012-11-19 01:49:23.941785223 +0100 @@ -9,6 +9,11 @@ mpoint="$3" type="$4" +getmd5() +{ + md5sum "$1" | cut -f1 -d ' ' +} + mappedpartition=$(mapdevfs "$partition" 2>/dev/null) || mappedpartition="$partition" exitcode=1 @@ -24,6 +29,7 @@ echo "$kernfile_seen" | fgrep -q " $kernbasefile " && continue kernfile_seen="$kernfile_seen $kernbasefile " if [ -f "$kernfile" ] && [ ! -L "$kernfile" ]; then + kernmd5=$(getmd5 "$kernfile") initrdname=$(echo "$kernfile" | sed "s/vmlinu[zx]/initrd\*/") # Yellow Dog Linux appends .img to it. initrdname1="${initrdname}.img" @@ -39,6 +45,13 @@ foundinitrd=0 for initrd in $(eval ls "$initrdname" "$initrdname1" "$initrdname2" "$initrdname3" "$initrdname4" 2>/dev/null | sort | uniq); do if [ "$initrd" != "$kernfile" ] && [ -f "$initrd" ] && [ ! -L "$initrd" ]; then + initrdmd5=$(getmd5 "$initrd") + pairmd5="$kernmd5:$initrdmd5" + if echo "$pairmd5_seen" | fgrep -q " $pairmd5 "; then + foundinitrd=1 + continue + fi + pairmd5_seen="$pairmd5_seen $pairmd5 " initrd=$(echo "$initrd" | sed "s!^$mpoint!!") result "$partition:$kernbootpart::$kernbasefile:$initrd:root=$mappedpartition" exitcode=0 Adding above change causes: bobek:~# /usr/lib/linux-boot-probes/50mounted-tests /dev/mapper/vg-deboot /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/vmlinuz:/initrd.img:root=/dev/dm-23 Maybe better is to get the result with files under /boot directory using reordered items:
--- 90fallback~zito2 2012-11-19 01:54:11.357776732 +0100 +++ 90fallback 2012-11-19 01:57:53.389770171 +0100 @@ -17,8 +17,8 @@ mappedpartition=$(mapdevfs "$partition" 2>/dev/null) || mappedpartition="$partition" exitcode=1 -for kernpat in /vmlinuz /vmlinux /boot/vmlinuz /boot/vmlinux "/boot/vmlinuz*" \ - "/boot/vmlinux*" "/vmlinuz*" "/vmlinux*" "/kernel-*" "/boot/kernel-*"; do +for kernpat in /boot/vmlinuz /boot/vmlinux "/boot/vmlinuz*" "/boot/vmlinux*" "/boot/kernel-*" \ + /vmlinuz /vmlinux "/vmlinuz*" "/vmlinux*" "/kernel-*"; do if echo "$kernpat" | grep -q boot/; then kernbootpart="$bootpart" else Now the result is: bobek:~# /usr/lib/linux-boot-probes/50mounted-tests /dev/mapper/vg-deboot /dev/mapper/vg-deboot:/dev/mapper/vg-deboot::/boot/vmlinuz-3.2.0-4-amd64:/boot/initrd.img-3.2.0-4-amd64:root=/dev/dm-23 This change seems to me better for Debian. I'm not certain about intent of original writer about ordering items (other probed systems), so maybe this is not acceptable. The root file-system root=/dev/dm-23 is resolved inappropriately. I must change kernel argument root=/dev/dm-23 to root=/dev/mapper/vg-deboot in the grub by hand to boot. This is another issue, witch should have different bug number so I'm not solving it there. Hope the attached complete diff is helpful a bit. Sorry for my English :(. Kindly regards -- Zito