#!/bin/sh . common.sh mountvirt() { # TODO: simply put these dirs on the initrd itself mkdir -m 0755 -p /dev /sys /proc /tmp /var /run mkdir -m 0700 -p /root mount -t sysfs -o nodev,noexec,nosuid none /sys mount -t proc -o nodev,noexec,nosuid none /proc tmpfs_size="10M" # [ -f /etc/udev/udev.conf ] && . /etc/udev/udev.conf mount -t tmpfs -o size=$tmpfs_size,mode=0755 udev /dev mount -t tmpfs -o size=64M,mode=0755 run /run mkdir -m 0755 /dev/pts /run/lock mount -t devpts devpts /dev/pts ln -s /run /run/lock /var/ } makedev() { # TODO: simply put these nodes on the initrd itself mkdir -m 0755 -p /dev mknod /dev/null c 1 3 mknod /dev/zero c 1 5 mknod /dev/tty c 5 0 if [ "$FUCK_devconsole" ]; then # FUCK /dev/console mknod /dev/console c 4 1 # tty1 is console; a saner alternative (TODO: fix shutdown to chvt) else mknod /dev/console c 5 1 fi for i in 0 1 2 3 4 5 6 7 8; do mknod /dev/tty${i} c 4 ${i} done # TODO: wait for udev? pft. for i in 0 1 2 3 4 5 6 7; do mknod /dev/loop${i} b 7 ${i} done } loadenv() { # TODO: filter the wheat from the chaff here; most of this is unused. # TODO: implement the various boot args # Load config files # export DPKG_ARCH= # . /conf/arch.conf # export ROOT= # . /conf/initramfs.conf # for conf in conf/conf.d/*; do # [ -f ${conf} ] && . ${conf} # done # Make modprobe quiet export MODPROBE_OPTIONS="-qb" # Export constants export rootmnt=/root # Export bootparam variables export init=/sbin/init export readonly=y export blacklist= # Parse command line options for x in $(cat /proc/cmdline); do case $x in init=*) init=${x#init=} ;; root=*) ROOT=${x#root=} case $ROOT in LABEL=*) ROOT="/dev/disk/by-label/${ROOT#LABEL=}" ;; UUID=*) ROOT="/dev/disk/by-uuid/${ROOT#UUID=}" ;; /dev/nfs) [ -z "${BOOT}" ] && BOOT=nfs ;; esac ;; rootflags=*) ROOTFLAGS="-o ${x#rootflags=}" ;; rootfstype=*) ROOTFSTYPE="${x#rootfstype=}" ;; ro) readonly=y ;; rw) readonly=n ;; nfsroot=*) NFSROOT="${x#nfsroot=}" ;; ip=*) IPOPTS="${x#ip=}" ;; boot=*) BOOT=${x#boot=} ;; resume=*) RESUME="${x#resume=}" ;; noresume) noresume=y ;; blacklist=*) blacklist=${x#blacklist=} ;; hostname=*) hostname=${x#hostname=} hostname "$hostname" ;; bootcd_device=*) bootcd_device=${x#bootcd_device=} mkdir -p /cdrom && mount -r -t hostfs -o "${bootcd_device#hostfs=}" hostfs /cdrom && bootdone samizdat-cdrom ;; overlay_device=*) overlay_device=${x#overlay_device=} mkdir -p /overlay && mount -t hostfs -o "${overlay_device#hostfs=}" hostfs /overlay && bootdone rw-overlay ;; uml_modules=*) uml_modules=${x#uml_modules=} mount -t hostfs -o "${uml_modules#hostfs=}" hostfs /lib/modules ;; esac done if [ -z "${noresume}" ]; then export resume=${RESUME} else export noresume fi } mountunionroot() { bootwait samizdat-cdrom squashfs-root ufs= if grep -q aufs /proc/filesystems || modprobe aufs; then ufs=aufs elif grep -q unionfs /proc/filesystems || modprobe unionfs; then ufs=unionfs fi case $ufs in unionfs) ro=ro;; aufs) ro=rr;; *) panic "mountunionroot: unionfs module not found";; esac dirs=; if [ -f /squashes/filesystem.module ]; then while read img; do d=/squashes/"${img%.squashfs}" mountpoint -q /squashes/"${img%.squashfs}" || continue; dirs="$d=$ro${dirs:+:$dirs}" done < /squashes/filesystem.module else for d in /squashes/*; do mountpoint -q "$d" || continue dirs="$d=$ro${dirs:+:$dirs}" done fi [ -n "$dirs" ] || panic "no squashes. missing/broken images on cdrom?" if true; then # overlay_tmp=$(mktemp -d /overlay.XXXXXX) && overlay_tmp=/overlay.$$ && mkdir -p $overlay_tmp && mount -t tmpfs tmpfs $overlay_tmp && touch $overlay_tmp/samizdat-filesystem-is-new dirs="$overlay_tmp:$dirs" || { rmdir $overlay_tmp; panic "mountunionroot: failure creating tmpfs overlay"; } fi mount -t $ufs -o rw,dirs="$dirs" $ufs "$rootmnt" || panic "mountunionroot: $ufs: mount (dirs=$dirs): error: $?" } insertoverlay() # TODO: copy-up and umount tmpfs. MASSIVELY IMPORTANT! { if ! mountpoint -q /overlay; then # rw-overlay was signalled without a mount on /overlay # thus, boot with the current tmpfs overlay mkdir -p /overlay mount -o move $overlay_tmp /overlay return 0 fi ufs=$(sed -ne 's?^[^ ]* '"$rootmnt"' \(unionfs\|aufs\) .*?\1?p' /proc/mounts) case $ufs in unionfs) panic 'insertoverlay: TODO: implement unionfs support' mount -o remount,rw,add=/overlay "$rootmnt" || panic "insertoverlay: remount unionfs (add=/overlay): error: $?" #mount -o remount,del=$overlay_tmp && # NO, WRONG, COPY-UP FIRST #umount $overlay_tmp && rmdir $overlay_tmp ;; aufs) mount -o remount,rw,prepend:/overlay=rw "$rootmnt" || panic "insertoverlay: remount aufs (prepend:/overlay=rw): error: $?" mount -o remount,mod:"$overlay_tmp"=ro+wh "$rootmnt" || panic "insertoverlay: couldn't set aufs branch read-only: $overlay_tmp" # copy everything the user reads (not just writes) to the overlay # (this is appropriate for CD-ROM but not testing. TODO: enable) #mount -o remount,coo=all "$rootmnt" mkdir -p "$rootmnt"/xino && mount -o move "$overlay_tmp" "$rootmnt"/xino || panic "insertoverlay: couldn't move mount $overlay_tmp to $rootmnt/xino" ;; *) panic "insertoverlay: unrecognized filesystem ($ufs)";; esac bootdone root-mounted } AppendIfNoSuchLine() { local filename="$1" shift if grep -vqF "$1" < "$filename"; then printf '%s\n' "$@" >> "$filename" fi } gpg_agent_chroot() { chroot "$rootmnt" sh -c \ 'export PATH=/usr/local/sbin:/usr/local/bin:$PATH; killall gpg-agent; samizdat-gpg-agent; killall -USR2 samizdat-pinentry;' } remove_squashfs_mistakes() { # Workaround for bad samizdat-generated upstream squashfs: rm -f "$rootmnt"/etc/ipsec.conf rm -rf "$rootmnt"/etc/samizdat/samizdat-receive-hooks rm -f "$rootmnt"/etc/adjtime } patchroot_UNUSED() { test -e "$rootmnt"/samizdat-filesystem-is-new || return echo Patching livecd root -- $(date) >> /dev/tty7 rm -f /dev/console; mknod /dev/console c 4 1 remove_squashfs_mistakes if [ -e /etc/adjtime -a ! -e "$rootmnt"/etc/adjtime ]; then cp /etc/adjtime "$rootmnt"/etc/adjtime fi if [ -f "$rootmnt"/cdrom/samizdat/skel.tgz ]; then chroot "$rootmnt" bin/tar -C / --no-same-owner -zxf /cdrom/samizdat/skel.tgz fi chroot "$rootmnt" hostname -F /etc/hostname chroot "$rootmnt" update-rc.d samizdat-pids start 15 S # We need debian-tor user so that hidden service directory can have the right owner chroot "$rootmnt" adduser --quiet --system --disabled-password --home /var/lib/tor \ --no-create-home --shell /bin/bash --group debian-tor # TODO: check errors here chroot "$rootmnt" sh -c \ 'export PATH=/usr/local/sbin:/usr/local/bin:"$PATH" GNUPGHOME=/gpg/gnupghome verbose=1; samizdat-receive -v < /cdrom/samizdat/secrets.mime && samizdat-receive -v < /cdrom/samizdat/public.mime' for diversion in /etc/kernel/postinst.d/initramfs-tools /etc/init.d/live-boot /sbin/halt; do chroot "$rootmnt" dpkg-divert --rename --package samizdat --add "$diversion" done cp /bin/halt.montecarlo "$rootmnt"/sbin/halt if ! [ -f "$rootmnt"/var/lib/dpkg/info/linux-image-"$(uname -r)".list ]; then chroot "$rootmnt" sh -c \ 'dpkg --fsys-tarfile /cdrom/samizdat/debs/linux-image-$(uname -r)_*.deb | tar -C / -x; depmod -a' fi # disable some of GRML's many consoles. # sed -i -e 's/^\([3456789]\|1[012]\):/#\1:/' "$rootmnt"/etc/inittab # sed -i -e 's/^NUM_CONSOLES=12/NUM_CONSOLES=0/' "$rootmnt"/usr/bin/zsh-login # these GRML scripts implement a "sendsigs" which does not respect omit.d sed -i -e 's/^\(l0:.*\)grml-halt$/\1rc 0/' "$rootmnt"/etc/inittab sed -i -e 's/^\(l6:.*\)grml-reboot$/\1rc 6/' "$rootmnt"/etc/inittab chroot "$rootmnt" update-rc.d sendsigs stop 20 0 6 echo Done patching livecd root -- $(date) >>/dev/tty7 rm "$rootmnt"/samizdat-filesystem-is-new } movemounts() { # Move mounted filesystems to the root filesystem while read dev mp rest; do case "$mp" in "$rootmnt"|"$rootmnt"/*|/|/proc|/dev|/dev/pts|/sys) continue ;; /mnt.samizdat.*) #umount -l "$mp" target="$rootmnt/media/${dev##*/}" ;; /overlay.*) umount -l $mp; continue ;; *) target="$rootmnt$mp" ;; esac mkdir -p "$target" mount -n -o move "$mp" "$target" done "$rootmnt$CONSOLE" 2>&1 panic "exec init failed (init=$init)" # exec run-init -c "$CONSOLE" "$rootmnt" "$init" "$@" # panic "exec run-init failed (init=$init)" } start_udev() { echo > /proc/sys/kernel/hotplug mkdir -p /dev/.udev/db/ /dev/.udev/queue/ # mkdir -p "$LOGBASE"; sh -c "udevd --resolve-names=never --debug >$LOGBASE/udevd."'$$'".log 2>&1" & udevd --resolve-names=never --daemon udevadm trigger --action=add # udevadm settle } stop_udev() { for proc in /proc/[0-9]*; do [ -x $proc/exe ] || continue [ "$(readlink $proc/exe)" = /sbin/udevd ] && kill ${proc#/proc/} done # ignore any failed event because the init script will trigger again all events nuke /dev/.udev/queue/ } killeverything() { # TODO: exempt: interactive shell(s) (AND CHILDREN) (or: anything with # a tty?), samizdat-agent, fsck(!!), ...? # exempt_cmdline="$(printf "sh\0-i\0")" force= while true; do killme= for proc in /proc/[0-9]*; do [ $proc != /proc/1 -a $proc != /proc/$$ -a -x $proc/exe ] || continue # [ "$(cat $proc/cmdline)" != "$exempt_cmdline" ] || continue read pid tcomm state ppid pgrp sid tty_nr tty_pgrp rest < $proc/stat [ $tty_nr = 0 ] || continue killme="$killme ${proc#/proc/}" done if [ -n "$killme" ]; then kill $force $killme else break fi force=-KILL done }