3 # QEMU trick to dive user in his own home environment
4 # as root in a virualized shadow of his own system
6 # (C) 2013 Pavel Pisa <pisa@cmp.felk.cvut.cz>
8 # THE TSCRIPT IS PROVIDED “AS IS” WITHOUT WARRANTY
9 # OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
11 # There is no limitation of scrip use, modification
12 # and distribution or relicensing.
14 # Some used ideas are documented at CTU FEE A4M35OSP
16 # http://support.dce.felk.cvut.cz/osp/cviceni/2/
17 # http://support.dce.felk.cvut.cz/osp/cviceni/2-en/
19 # and Departemnt Of Control Engineering IT Wiki
20 # https://support.dce.felk.cvut.cz/
23 QEMU=qemu-system-x86_64
24 BUSYBOX=$(which busybox)
25 RESIZE=$(which resize)
26 KERNEL_VERSION=$(uname -r)
27 KERNEL_IMAGE=/boot/vmlinuz-${KERNEL_VERSION}
28 RAMDISK_ARCHIVE=ramdisk.cpio
29 #GEN_INIT_CPIO=$(dirname $0)/gen_init_cpio
30 INITRD_DIR=initrd_content
31 MODULES_LIST="virtio virtio_ring virtio_pci virtio_net virtio_net fscache 9pnet 9pnet_virtio 9p aufs overlay"
33 QEMU_KVM_ENABLE="-enable-kvm"
34 #QEMU_OUTPUT="-vga cirrus -serial null"
35 QEMU_OUTPUT="-nographic -append console=ttyS0"
37 INITRD_DIR_ABS=$(readlink -f ${INITRD_DIR})
39 function libraries_for_binary()
41 ldd $1 | sed -n -e 's#^\t\(/[^ ]*\) .*$#\1#p' -e 's#^\t\([^ ]*\) => \([^ ]\+\) .*$#\2#p'
50 mkdir -p ${tgt_dir}/$(dirname ${src}) || return 1
51 cp -v ${src} ${tgt_dir}/${src#/} || return 1
52 cp -auv ${src} ${tgt_dir}/${src#/}
58 if [ ${l:0:1} != '/' ] ; then
59 l=$(dirname ${src})/${l}
65 function setup_initrd_content()
67 mkdir -p ${INITRD_DIR_ABS}
68 mkdir -p ${INITRD_DIR_ABS}/bin
69 mkdir -p ${INITRD_DIR_ABS}/etc/init.d
71 LIBS=$(libraries_for_binary ${BUSYBOX})
72 if [ -n "${RESIZE}" ] ; then
73 LIBS+=" "$(libraries_for_binary ${RESIZE})
76 LIBS="$(for i in ${LIBS} ; do echo $i ; done | sort -u)"
79 deep_copy ${i} ${INITRD_DIR_ABS}
82 cp -a ${BUSYBOX} ${INITRD_DIR_ABS}/bin
83 ( cd ${INITRD_DIR_ABS}/bin && ln -s busybox sh )
85 if [ -n "${RESIZE}" ] ; then
86 cp -a ${RESIZE} ${INITRD_DIR_ABS}/bin
90 for m in ${MODULES_LIST} ; do
91 mf=$(find /lib/modules/${KERNEL_VERSION} -name ${m}.ko )
92 if [ -n "${mf}" ] ; then
93 mkdir -p "${INITRD_DIR_ABS}/$(dirname ${mf})"
94 cp -a "${mf}" "${INITRD_DIR_ABS}/${mf#/}"
96 echo "Module ${m} not found"
102 root_dir_list="/proc /sys /dev /mnt /mnt/root /mnt/rootbase /mnt/overlay /tmp"
106 for d in $root_dir_list ; do
111 echo "Starting QEMU trick"
112 if mount -t proc none /proc ; then
113 echo "mount works directly"
116 echo "trying busybox mount"
117 BINPR="/bin/busybox "
118 if ! \${BINPR}mount -t proc none /proc ; then
119 echo "mounting proc failed, cannot continue"
124 \${BINPR}mount -t sysfs none /sys
125 \${BINPR}mount -t tmpfs none /dev
128 for m in ${MODULES_LIST} ; do
133 if [ -e /bin/resize ] ; then
134 \${BINPR}mv /dev/tty /dev/tty-backup
135 \${BINPR}ln -s /dev/console /dev/tty
136 /bin/resize >/tmp/term-size
138 \${BINPR}stty cols \$COLUMNS rows \$LINES
139 \${BINPR}rm -f /dev/tty
140 \${BINPR}mv /dev/tty-backup /dev/tty
142 \${BINPR}mount -t 9p -o ro,trans=virtio,version=9p2000.u root /mnt/rootbase
143 \${BINPR}mount -t tmpfs overlay /mnt/overlay
144 \${BINPR}mkdir -p /mnt/overlay/data
146 echo "Ready to setup overlay"
150 if grep -q aufs /proc/filesystems ; then
151 echo "Using aufs to remap root"
152 \${BINPR}mount -n -t aufs -o noxino,noatime,dirs=/mnt/overlay/data=rw:/mnt/rootbase=ro aufs-root ${rootmnt}
154 echo "Using overlay to remap root"
155 \${BINPR}mkdir -p /mnt/overlay/work
156 \${BINPR}mount -n -t overlay -o upperdir=/mnt/overlay/data,workdir=/mnt/overlay/work,lowerdir=/mnt/rootbase overlay-root ${rootmnt}
159 \${BINPR}mount -n -o move /dev ${rootmnt}/dev
160 \${BINPR}mount -n -o move /sys ${rootmnt}/sys
161 \${BINPR}mount -n -o move /proc ${rootmnt}/proc
162 \${BINPR}mount -t 9p -o trans=virtio,version=9p2000.u home ${rootmnt}/home
163 \${BINPR}mount -t tmpfs none ${rootmnt}/root
164 \${BINPR}mount -t tmpfs none ${rootmnt}/tmp
165 \${BINPR}mount -t tmpfs none ${rootmnt}/run
166 \${BINPR}mount -t tmpfs none ${rootmnt}/var/log
167 \${BINPR}mount -t tmpfs none ${rootmnt}/var/tmp
169 \${BINPR}rm -f ${rootmnt}/var/lib/urandom/random-seed
170 \${BINPR}rm -rf ${rootmnt}/etc/shadow
171 echo >${rootmnt}/etc/shadow
172 \${BINPR}rm -rf ${rootmnt}/etc/ssh
173 \${BINPR}mkdir ${rootmnt}/etc/ssh
175 \${BINPR}rm -f ${rootmnt}/etc/rc2.d/* ${rootmnt}/etc/rc3.d/* ${rootmnt}/etc/rc4.d/* ${rootmnt}/etc/rc5.d/*
177 \${BINPR}rm -rf ${rootmnt}/etc/fstab.d ${rootmnt}/etc/fstab
178 echo >${rootmnt}/etc/fstab
180 \${BINPR}rm -rf ${rootmnt}/var/lib/dpkg/lock ${rootmnt}/var/lib/apt/lists/lock ${rootmnt}/var/cache/apt/archives/lock
181 \${BINPR}rm -rf ${rootmnt}/etc/apt/apt.conf.d/*etckeeper ${rootmnt}/var/lib/dpkg/triggers/Lock
183 \${BINPR}rm -rf ${rootmnt}/etc/network/interfaces.d ${rootmnt}/etc/network/interfaces
184 echo "auto lo eth0" >${rootmnt}/etc/network/interfaces
185 echo "iface lo inet loopback" >>${rootmnt}/etc/network/interfaces
186 echo "iface eth0 inet dhcp" >>${rootmnt}/etc/network/interfaces
188 if [ -e ${rootmnt}/bin/bash ] ; then
194 \${BINPR}mv ${rootmnt}/etc/inittab ${rootmnt}/etc/inittab.orig
195 \${BINPR}cp ${rootmnt}/etc/inittab.orig ${rootmnt}/etc/inittab
196 \${BINPR}sed -i -e '/\/sbin\/.*getty/d' ${rootmnt}/etc/inittab
197 #echo "1:2345:respawn:/bin/sh" >>${rootmnt}/etc/inittab
198 #echo "T0:1234:respawn:/bin/sh" >>${rootmnt}/etc/inittab
200 echo "1:2345:respawn:/sbin/agetty -n -l \${shell} -o '-l' tty1 38400 linux" >>${rootmnt}/etc/inittab
201 echo "2:23:respawn:/sbin/agetty -n -l \${shell} -o '-l' tty2 38400 linux" >>${rootmnt}/etc/inittab
202 echo "T0:23:respawn:/sbin/agetty -n -l \${shell} -o '-l' -L ttyS0 9600 xterm" >>${rootmnt}/etc/inittab
205 echo "Ready to proceed by pivot_root"
209 #mkdir -p ${rootmnt}/overlay/pivot
210 #pivot_root . overlay/pivot
211 #exec chroot . sbin/init
212 exec \${BINPR}switch_root ${rootmnt} /sbin/init
215 ) >${INITRD_DIR_ABS}/init
217 chmod 755 ${INITRD_DIR_ABS}/init
222 function build_initrd_gen_init_cpio()
228 nod /dev/tty0 644 0 0 c 4 0
229 nod /dev/tty1 644 0 0 c 4 1
230 nod /dev/tty2 644 0 0 c 4 2
231 nod /dev/tty3 644 0 0 c 4 3
232 nod /dev/tty4 644 0 0 c 4 4
233 #slink /init bin/busybox 700 0 0
237 dir /mnt/root 755 0 0
238 dir /mnt/rootbase 755 0 0
239 dir /mnt/overlay 755 0 0
241 find ${INITRD_DIR} -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
242 find ${INITRD_DIR} -type f -printf "file /%P %p %m 0 0\n"
243 find ${INITRD_DIR} -type l -printf "slink /%P %l %m 0 0\n"
246 $GEN_INIT_CPIO filelist | gzip > ${RAMDISK_ARCHIVE}
251 function build_initrd_cpio()
253 ( cd ${INITRD_DIR_ABS} && find . | cpio --quiet -H newc -o ) | gzip -9 > ${RAMDISK_ARCHIVE}
256 function run_virt_system()
258 $QEMU ${QEMU_KVM_ENABLE} \
259 -kernel ${KERNEL_IMAGE} \
260 -initrd ${RAMDISK_ARCHIVE} ${QEMU_MEMORY} \
261 -virtfs local,path=/,security_model=none,mount_tag=root \
262 -virtfs local,path=/home,security_model=none,mount_tag=home \
263 -net nic,macaddr=be:be:be:10:00:01,model=virtio,vlan=0 \
267 # -chardev can,id=canbus0,port=can0
268 # -device pci-can,chardev=canbus0,model=SJA1000
269 # -device apohw -vga cirrus
270 # -device mf624,port=55555
275 function clean_setup()
277 rm -rf ${RAMDISK_ARCHIVE} filelist ${INITRD_DIR_ABS}
280 if [ "$(whoami)" == "root" ] ; then
281 echo "$0: !!! TOO DANGEROUS TO RUN AS ROOT !!!"
285 clean_setup || exit 1
286 echo "=== setup_initrd_content ==="
287 setup_initrd_content || exit 1
288 echo "=== build_initrd ==="
289 if [ -n "${GEN_INIT_CPIO}" ] ; then
290 build_initrd_gen_init_cpio || exit 1
292 build_initrd_cpio || exit 1
294 echo "=== run_virt_system ==="
295 run_virt_system || exit 1