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

Stappers <[email protected]>
Newsgroups gmane.linux.debian.devel.embedded
Message-ID <[email protected]>
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 <[email protected]>, 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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.