[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: foreign rootfs without root priviliges with multistrap, fakeroot, fakechroot and qemu user emulation



On Thu, Jun 16, 2011 at 07:15:35PM +0200, Stappers wrote:
> On Thu, Jun 16, 2011 at 10:40:01AM +0200, Johannes Schauer wrote:
> > hi,
> > 
> > as a follow up for "fakechroot + qemu user emulation" in january 2011 and my
> > solution explained in "fakechroot + qemu user emulation (it works now)" in
> > april 2011 and by the request of wookey who suggested I should post it here,
> > let me just paste the links to four scripts of mine.
> > 
> > notioninkadam: http://mister-muffin.de/p/_8K5
> > touchbook: http://mister-muffin.de/p/9nQ4
> > openmoko: http://mister-muffin.de/p/wFep
> > kirkwood: http://mister-muffin.de/p/l0U_
> 
> The openmoko one for further (in-line) discussion
> fetched with `wget -O - openmoko: http://mister-muffin.de/p/wFep`
  fetched with `wget -O -           http://mister-muffin.de/p/wFep`
> 
> --2011-06-16 19:09:47--  http://mister-muffin.de/p/wFep
> Herleiden van mister-muffin.de... 62.75.187.73
> Verbinding maken met mister-muffin.de|62.75.187.73|:80... verbonden.
> HTTP-verzoek is verzonden; wachten op antwoord... 200 OK
> Lengte: 5838 (5,7K) [text/plain]
> Wordt geschreven naar: `STDOUT'
> #!/bin/sh -ex
> 
> if [ "$LOGNAME" = "root" ] \
> || [ "$USER" = "root" ] \
> || [ "$USERNAME" = "root" ] \
> || [ "$SUDO_COMMAND" != "" ] \
> || [ "$SUDO_USER" != "" ] \
> || [ "$SUDO_UID" != "" ] \
> || [ "$SUDO_GID" != "" ]; then
> 	echo "don't run this script as root - there is no need to"
> 	exit
> fi
> 
> if [ "$FAKEROOTKEY" = "" ]; then
>         echo "re-executing script inside fakeroot"
>         fakeroot $0;
>         exit
> fi
> 
> DIST="sid"
> ROOTDIR="debian-$DIST-multistrap"
> MIRROR="http://127.0.0.1:3142/ftp.de.debian.org/debian";
> MIRROR_REAL="http://ftp.de.debian.org/debian";
> #MIRROR="http://127.0.0.1:3142/ftp.debian-ports.org/debian";
> #MIRROR_REAL="http://ftp.debian-ports.org/debian";
> 
> export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C
> 
> rm -rf $ROOTDIR $ROOTDIR.tar
> 
> PACKAGES="locales udev module-init-tools procps mtd-utils curl wget ntpdate"
> PACKAGES=$PACKAGES" screen less vim-tiny console-tools vpnc rsync conspy"
> PACKAGES=$PACKAGES" man-db fbset input-utils openssh-server wpasupplicant"
> PACKAGES=$PACKAGES" bluez bluez-utils bluez-alsa bluez-gstreamer iputils-ping"
> PACKAGES=$PACKAGES" iproute dnsutils nodm xserver-xorg-input-evdev xterm"
> PACKAGES=$PACKAGES" xserver
>      0K .-xorg xserver-xorg-video-fbdev"
> 
> cat > multistrap.conf << __END__
> [General]
> #arch=armhf
> arch=armel
> directory=$ROOTDIR
> cleanup=true
> unpack=true
> noauth=true
> #bootstrap=Debian_bootstrap Debian_unreleased
> bootstrap=Debian_bootstrap
> aptsources=Debian
> allowrecommends=false
> addimportant=false
> 
> [Debian_bootstrap]
> packages=$PACKAGES
> source=$MIRROR
> suite=$DIST
> omitdebsrc=true
> 
> #[Debian_unreleased]
> #packages=$PACKAGES
> #source=$MIRROR
> #suite=unreleased
> #omitdebsrc=true
> 
> [Debian]
> source=$MIRROR_REAL
> keyring=debian-archive-keyring
> suite=$DIST
> omitdebsrc=true
> __END__
> 
> multistrap -f multistrap.conf
> 
> cp /usr/bin/qemu-arm-static $ROOTDIR/usr/bin
> 
> # stop invoke-rc.d from starting services
> cat > $ROOTDIR/usr/sbin/policy-rc.d << __END__
> #!/bin/sh
> echo "sysvinit: All runlevel operations denied by policy" >&2
> exit 101
> __END__
> chmod +x $ROOTDIR/usr/sbin/policy-rc.d
> 
> # fix for ldconfig inside fakechroot
> mv $ROOTDIR/sbin/ldconfig $ROOTDIR/sbin/ldconfig.REAL
> mv $ROOTDIR/usr/bin/ldd $ROOTDIR/usr/bin/ldd.REAL
> ln -s ../bin/true $ROOTDIR/sbin/ldconfig
> 
> # get fake ldd (needs objdump from binutils) for mkinitramfs
> # https://github.com/fakechroot/fakechroot/raw/master/scripts/ldd.pl
> curl http://mister-muffin.de/p/a3Dt > $ROOTDIR/usr/bin/ldd

fetched with `wget -O - http://mister-muffin.de/p/a3Dt`

--2011-06-16 20:01:51--  http://mister-muffin.de/p/a3Dt
Herleiden van mister-muffin.de... 62.75.187.73
Verbinding maken met mister-muffin.de|62.75.187.73|:80... verbonden.
HTTP-verzoek is verzonden; wachten op antwoord... 200 OK
Lengte: 4464 (4,4K) [text/plain]
Wordt geschreven naar: `STDOUT'
#!/usr/bin/perl

# fakeldd
#
# Replacement for ldd with usage of objdump
#
# (c) 2003-2010 Piotr Roszatycki <dexter@debian.org>, LGPL

use strict;

my @Libs = ();
my %Libs = ();

my $Status = 0;
my $Dynamic = 0;
my $Format = '';

my $Ldsodir = "/lib";
my @Ld_Library_Path = qw(/usr/lib /lib /usr/lib32 /lib32 /usr/lib64 /lib64);


sub ldso {
    my ($lib) = @_;

    return if $Libs{$lib};

    my $path;

    if ($lib =~ /^\//) {
        $path = $lib;
    }
    else {
        foreach my $dir (@Ld_Library_Path) {
            next unless -f "$dir/$lib";

            my $badformat = 0;
            local *PIPE;
            open PIPE, "objdump -p '$dir/$lib' 2>/dev/null |";
            while (my $line = <PIPE>) {
                if ($line =~ /file format (\S*)$/) {
                    $badformat = 1 unless $1 eq $Format;
                    last;
                }
            }
            close PIPE;

            next if $badformat;

            $path = "$dir/$lib";
            last;
        }
    }

    push @Libs, $lib;
    if (-f $path) {
        $Libs{$lib} = $path;
        objdump($path);
    }
}


sub objdump {
    my (@files) = @_;

    foreach my $file (@files) {
        local *PIPE
     0K .;
        open PIPE, "objdump -p '$file' 2>/dev/null |";
        while (my $line = <PIPE>) {
            $line =~ s/^\s+//;

            if ($line =~ /file format (\S*)$/) {
                if (not $Format) {
                    $Format = $1;

                    if ($^O eq 'linux') {
                        if ($Format =~ /^elf64-/) {
                            push @Libs, 'linux-vdso.so.1';
                            $Libs{'linux-vdso.so.1'} = '';
                        }
                        else {
                            push @Libs, 'linux-gate.so.1';
                            $Libs{'linux-gate.so.1'} = '';
                        }
                    }

                    foreach my $lib (split /:/, $ENV{LD_PRELOAD}||'') {
                        ldso($lib);
                    }
                }
                else {
                    next unless $Format eq $1;
                }
            }
            if (not $Dynamic and $line =~ /^Dynamic Section:/) {
                $Dynamic = 1;
            }

            next unless $line =~ /^ \s* NEEDED \s+ (.*) \s* $/x;

            my $needed = $1;
            if ($needed =~ /^ld(-linux)?(\.|-)/) {
                $needed = "$Ldsodir/$needed";
            }

            ldso($needed);
        }
        close PIPE;
    }
}


sub load_ldsoconf {
    my ($file) = @_;

    local *FH;
    open FH, $file;
    while (my $line = <FH>) {
        chomp $line.;
        $line =~ s/#.*//;
        next if $line =~ /^\s*$/;

        if ($line =~ /^include\s+(.*)\s*/) {
            my $include = $1;
            foreach my $incfile (glob $include) {
                load_ldsoconf($incfile);
            }
            next;
        }

        unshift @Ld_Library_Path, $line;
    }
    close FH;
}


MAIN: {
    my @args = @ARGV;

    if (not @args) {
        print STDERR "fakeldd: missing file arguments\n";
        exit 1;
    }

    if (not `which objdump`) {
        print STDERR "fakeldd: objdump: command not found: install binutils package\n";
        exit 1;
    }

    load_ldsoconf('/etc/ld.so.conf');
    unshift @Ld_Library_Path, split(/:/, $ENV{LD_LIBRARY_PATH}||'');

    while ($args[0] =~ /^-/) {
        my $arg = $args[0];
        shift @ARGV;
        last if $arg eq "--";
    }

    foreach my $file (@args) {
        %Libs = ();
        $Dynamic = 0;

        if (@args > 1) {
            print "$file:\n";
        }

        if (not -f $file) {
            print STDERR "ldd: $file: No such file or directory\n";
            $Status = 1;
            next;
        }

        objdump($file);

        if ($Dynamic == 0) {
            print "\tnot a dynamic executable\n";
            $Status = 1;
        }
        elsif (scalar %Libs eq "0") {
            print "\tstatically linked\n";
        }

        my $address = '0x' . '0' x ($Format =~ /^elf64-/ ? 16 : 8);

        forea.ch my $lib (@Libs) {
            if ($lib =~ /^\//) {
                printf "\t%s (%s)\n", $lib, $address;
            }
            elsif (defined $Libs{$lib}) {
                printf "\t%s => %s (%s)\n", $lib, $Libs{$lib}, $address;
            }
            else {
                printf "\t%s => not found\n", $lib;
            }
        }

    }
}

END {
    $? = $Status;
}
.                                                  100%  140K=0,03s

2011-06-16 20:01:51 (140 KB/s) - geschreven naar stdout [4464/4464]

> chmod +x $ROOTDIR/usr/bin/ldd
> 
> # supply ld.so.conf for fake ldd (running libc6 postinst script will fail)
> echo "include /etc/ld.so.conf.d/*.conf" > $ROOTDIR/etc/ld.so.conf
> 
> # do not generate ssh host keys
> mkdir -p. $ROOTDIR/etc/ssh/
> touch "$ROOTDIR/etc/ssh/ssh_host_rsa_key"
> touch "$ROOTDIR/etc/ssh/ssh_host_dsa_key"
> touch "$ROOTDIR/etc/ssh/ssh_host_ecdsa_key"
> 
> cat > $ROOTDIR/tmp/debconfseed.txt << __END__
> # put debconf options here
> __END__
> fakechroot chroot $ROOTDIR debconf-set-selections /tmp/debconfseed.txt
> rm $ROOTDIR/tmp/debconfseed.txt
> 
> # run preinst scripts
> for script in $ROOTDIR/var/lib/dpkg/info/*.preinst; do
> 	[ "$script" = "$ROOTDIR/var/lib/dpkg/info/bash.preinst" ] && continue
> 	fakechroot chroot $ROOTDIR ${script##$ROOTDIR} install
> done
> 
> # run dpkg --configure -a twice because of errors during the first run
> fakechroot chroot $ROOTDIR /usr/bin/dpkg --configure -a || fakechroot chroot $ROOTDIR /usr/bin/dpkg --configure -a
> 
> fakechroot chroot $ROOTDIR update-locale LANG=en_US.UTF-8 LANGUAGE=en_US:en
> echo en_US.UTF-8 UTF-8 > $ROOTDIR/etc/locale.gen
> fakechroot chroot $ROOTDIR locale-gen
> 
> cat > $ROOTDIR/etc/fstab << __END__
> # <file system> <mount point>    <type> <options>                          <dump> <pass>
> rootfs          /                auto   defaults,errors=remount-ro,noatime 0      1
> /dev/mmcblk0p2  /home           auto    defaults,errors=remount-ro,noatime 0      2
> proc            /proc            proc   defaults                           0      0
> tmpfs           /tmp             tmpfs  defaults,noatime                   0      0
> tmpfs           /var/lock        tmpfs  defaults,noatime                   0      0
> t.mpfs           /var/run         tmpfs  defaults,noatime                   0      0
> tmpfs           /var/log         tmpfs  defaults,noatime                   0      0
> tmpfs           /etc/network/run tmpfs  defaults,noatime                   0      0
> __END__
> 
> echo openmoko > $ROOTDIR/etc/hostname
> 
> cat > $ROOTDIR/etc/hosts << __END__
> 127.0.0.1 localhost
> 127.0.0.1 openmoko
> __END__
> 
> cat > $ROOTDIR/etc/default/nodm << __END__
> NODM_ENABLED=true
> NODM_USER=user
> NODM_XINIT=/usr/bin/xinit
> NODM_FIRST_VT=7
> NODM_XSESSION=/etc/X11/Xsession
> NODM_X_OPTIONS='-nolisten tcp'
> NODM_MIN_SESSION_TIME=60
> __END__
> 
> # activate a tty on serial
> echo "T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100" >> $ROOTDIR/etc/inittab
> 
> fakechroot chroot $ROOTDIR useradd user -p `openssl passwd -crypt -salt // ""` -s /bin/bash --create-home
> fakechroot chroot $ROOTDIR usermod -a -G audio,dialout user
> 
> sed -i 's/\(root:\)[^:]*\(:\)/\1'`openssl passwd -crypt -salt // "" | sed 's/\(\/\|\\\|&\)/\\&/g'`'\2/' $ROOTDIR/etc/shadow
> sed -i 's/\(PermitEmptyPasswords\) no/\1 yes/' $ROOTDIR/etc/ssh/sshd_config
> echo 'APT::Install-Recommends "0";' > $ROOTDIR/etc/apt/apt.conf.d/99no-install-recommends
> echo 'Acquire::PDiffs "0";' > $ROOTDIR/etc/apt/apt.conf.d/99no-pdiffs
> 
> #cleanup
> rm $ROOTDIR/sbin/ldconfig $ROOTDIR/usr/bin/ldd
> mv $ROOTDIR/sbin/ldconfig.REAL $ROOTDIR/sbin/ldconfig
> mv $ROOTDIR/usr/bin/ldd.REAL $ROOTDIR/usr/bin/ldd
> rm $ROOTDIR/usr/sbin/policy-rc.d
> rm $ROOTDIR/etc/ssh/ssh_host_*
> cp /etc/resolv.conf $ROOTDIR/etc/resolv.conf
> 
> # need to generate tar inside fakechroot so that absolute symlinks are correct
> fakechroot chroot $ROOTDIR tar -cf $ROOTDIR.tar -C / .
> mv $ROOTDIR/$ROOTDIR.tar .
> 
> tar --delete -f $ROOTDIR.tar ./usr/bin/qemu-arm-static
> rm $ROOTDIR/usr/bin/qemu-arm-static
> ..                                                 100%  144K=0,04s
> 
> 2011-06-16 19:09:47 (144 KB/s) - geschreven naar stdout [5838/5838]


Reply to: