]> rtime.felk.cvut.cz Git - pisa/qemu-utils.git/blob - qemu-run-trick/qemu-setup-and-run
qemu-run-trick: do not deep_copy if only target permissions cannot be set.
[pisa/qemu-utils.git] / qemu-run-trick / qemu-setup-and-run
1 #!/bin/bash
2 #
3 # QEMU trick to dive user in his own hoe environment
4 # as root in a virualized shadow of his own system
5 #
6 # (C) 2013 Pavel Pisa <pisa@cmp.felk.cvut.cz>
7 #
8 # THE TSCRIPT IS PROVIDED “AS IS” WITHOUT WARRANTY
9 # OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
10 #
11 # There is no limitation of scrip use, modification
12 # and distribution or relicensing.
13 #
14 # Some used ideas are documented at CTU FEE A4M35OSP
15 # excercises pages
16 #   http://support.dce.felk.cvut.cz/osp/cviceni/2/
17 #   http://support.dce.felk.cvut.cz/osp/cviceni/2-en/
18 #
19 # and Departemnt Of Control Engineering IT Wiki
20 #   https://support.dce.felk.cvut.cz/
21 #
22
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"
32 QEMU_MEMORY="-m 1024"
33 QEMU_KVM_ENABLE="-enable-kvm"
34 #QEMU_OUTPUT="-vga cirrus -serial null"
35 QEMU_OUTPUT="-nographic -append console=ttyS0"
36
37 INITRD_DIR_ABS=$(readlink -f ${INITRD_DIR})
38
39 function libraries_for_binary()
40 {
41   ldd $1 | sed -n -e 's#^\t\(/[^ ]*\) .*$#\1#p' -e 's#^\t\([^ ]*\) => \([^ ]\+\) .*$#\2#p'
42 }
43
44 function deep_copy()
45 {
46   src=$1
47   tgt_dir=$2
48
49   while true ; do
50     mkdir -p ${tgt_dir}/$(dirname ${src}) || return 1
51     cp -av ${src} ${tgt_dir}/${src#/} || \
52     cp -v ${src} ${tgt_dir}/${src#/} || return 1
53
54
55     l=$(readlink ${src})
56     if [ -z "$l" ] ; then
57       return 0
58     fi
59     if [ ${l:0:1} != '/' ] ; then
60       l=$(dirname ${src})/${l}
61     fi
62     src=${l}
63   done
64 }
65
66 function setup_initrd_content()
67 {
68   mkdir -p ${INITRD_DIR_ABS}
69   mkdir -p ${INITRD_DIR_ABS}/bin
70   mkdir -p ${INITRD_DIR_ABS}/etc/init.d
71
72   LIBS=$(libraries_for_binary ${BUSYBOX})
73   if [ -n "${RESIZE}" ] ; then
74     LIBS+=" "$(libraries_for_binary ${RESIZE})
75   fi
76
77   LIBS="$(for i in ${LIBS} ; do echo $i ; done | sort -u)"
78
79   for i in ${LIBS}; do
80     deep_copy ${i} ${INITRD_DIR_ABS}
81   done
82
83   cp -a ${BUSYBOX} ${INITRD_DIR_ABS}/bin
84   ( cd ${INITRD_DIR_ABS}/bin && ln -s busybox sh )
85
86   if [ -n "${RESIZE}" ] ; then
87     cp -a ${RESIZE} ${INITRD_DIR_ABS}/bin
88   fi
89
90
91   for m in ${MODULES_LIST} ; do
92     mf=$(find /lib/modules/${KERNEL_VERSION} -name ${m}.ko )
93     if [ -n "${mf}" ] ; then
94       mkdir -p "${INITRD_DIR_ABS}/$(dirname ${mf})"
95       cp -a "${mf}" "${INITRD_DIR_ABS}/${mf#/}"
96     else
97       echo "Module ${m} not found"
98     fi
99   done
100
101   rootmnt=/mnt/root
102   init=/sbin/init
103   root_dir_list="/proc /sys /dev /mnt /mnt/root /mnt/rootbase /mnt/overlay /tmp"
104
105   (
106     echo '#!/bin/sh'
107     for d in $root_dir_list ; do
108        echo "mkdir -p $d"
109     done
110
111     cat <<EOF
112 echo "Starting QEMU trick"
113 mount -t proc none /proc
114 mount -t sysfs none /sys
115 mount -t tmpfs none /dev
116 depmod
117 EOF
118     for m in ${MODULES_LIST} ; do
119       echo modprobe $m
120     done
121     cat <<EOF
122 mdev -s
123 if [ -e /bin/resize ] ; then
124   mv /dev/tty /dev/tty-backup
125   ln -s /dev/console /dev/tty
126   /bin/resize >/tmp/term-size
127   . /tmp/term-size
128   stty cols \$COLUMNS rows \$LINES
129   rm -f /dev/tty
130   mv /dev/tty-backup /dev/tty
131 fi
132 mount -t 9p -o ro,trans=virtio,version=9p2000.u root /mnt/rootbase
133 mount -t tmpfs overlay /mnt/overlay
134 mkdir -p /mnt/overlay/data
135
136 echo "Ready to setup overlay"
137 #sleep 5
138 #/bin/sh
139
140 if grep -q aufs /proc/filesystems ; then
141   echo "Using aufs to remap root"
142   mount -n -t aufs -o noxino,noatime,dirs=/mnt/overlay/data=rw:/mnt/rootbase=ro aufs-root ${rootmnt}
143 else
144   echo "Using overlay to remap root"
145   mkdir -p /mnt/overlay/work
146   mount -n -t overlay -o upperdir=/mnt/overlay/data,workdir=/mnt/overlay/work,lowerdir=/mnt/rootbase overlay-root ${rootmnt}
147 fi
148
149 mount -n -o move /dev ${rootmnt}/dev
150 mount -n -o move /sys ${rootmnt}/sys
151 mount -n -o move /proc ${rootmnt}/proc
152 mount -t 9p -o trans=virtio,version=9p2000.u home ${rootmnt}/home
153 mount -t tmpfs none ${rootmnt}/root
154 mount -t tmpfs none ${rootmnt}/tmp
155 mount -t tmpfs none ${rootmnt}/run
156 mount -t tmpfs none ${rootmnt}/var/log
157 mount -t tmpfs none ${rootmnt}/var/tmp
158
159 rm ${rootmnt}/var/lib/urandom/random-seed 
160 rm -rf ${rootmnt}/etc/shadow
161 echo >${rootmnt}/etc/shadow
162 rm -rf ${rootmnt}/etc/ssh
163 mkdir ${rootmnt}/etc/ssh
164
165 rm -f ${rootmnt}/etc/rc2.d/* ${rootmnt}/etc/rc3.d/* ${rootmnt}/etc/rc4.d/* ${rootmnt}/etc/rc5.d/*
166
167 rm -rf ${rootmnt}/etc/fstab.d ${rootmnt}/etc/fstab
168 echo >${rootmnt}/etc/fstab
169
170 rm -rf ${rootmnt}/var/lib/dpkg/lock ${rootmnt}/var/lib/apt/lists/lock ${rootmnt}/var/cache/apt/archives/lock
171 rm -rf ${rootmnt}/etc/apt/apt.conf.d/*etckeeper ${rootmnt}/var/lib/dpkg/triggers/Lock
172
173 rm -rf ${rootmnt}/etc/network/interfaces.d ${rootmnt}/etc/network/interfaces
174 echo "auto lo eth0" >${rootmnt}/etc/network/interfaces
175 echo "iface lo inet loopback" >>${rootmnt}/etc/network/interfaces
176 echo "iface eth0 inet dhcp" >>${rootmnt}/etc/network/interfaces
177
178 if  [ -e ${rootmnt}/bin/bash ] ; then
179   shell=/bin/bash
180 else
181   shell=/bin/sh
182 fi
183
184 mv ${rootmnt}/etc/inittab ${rootmnt}/etc/inittab.orig
185 cp ${rootmnt}/etc/inittab.orig ${rootmnt}/etc/inittab
186 sed -i -e '/\/sbin\/.*getty/d' ${rootmnt}/etc/inittab
187 #echo "1:2345:respawn:/bin/sh" >>${rootmnt}/etc/inittab
188 #echo "T0:1234:respawn:/bin/sh" >>${rootmnt}/etc/inittab
189
190 echo "1:2345:respawn:/sbin/agetty -n -l \${shell} -o '-l' tty1 38400 linux" >>${rootmnt}/etc/inittab
191 echo "2:23:respawn:/sbin/agetty -n -l \${shell} -o '-l' tty2 38400 linux" >>${rootmnt}/etc/inittab
192 echo "T0:23:respawn:/sbin/agetty -n -l \${shell} -o '-l' -L ttyS0 9600 xterm" >>${rootmnt}/etc/inittab
193
194 cd ${rootmnt}
195 echo "Ready to proceed by pivot_root"
196 #sleep 5
197 #/bin/sh
198
199 #mkdir -p ${rootmnt}/overlay/pivot
200 #pivot_root . overlay/pivot
201 #exec chroot . sbin/init
202 exec switch_root ${rootmnt} /sbin/init
203 EOF
204
205   ) >${INITRD_DIR_ABS}/init
206
207   chmod 755 ${INITRD_DIR_ABS}/init
208
209   return 0
210 }
211
212 function build_initrd_gen_init_cpio()
213 {
214
215   (
216     cat <<EOF
217 dir /dev 755 0 0
218 nod /dev/tty0 644 0 0 c 4 0
219 nod /dev/tty1 644 0 0 c 4 1
220 nod /dev/tty2 644 0 0 c 4 2
221 nod /dev/tty3 644 0 0 c 4 3
222 nod /dev/tty4 644 0 0 c 4 4
223 #slink /init bin/busybox 700 0 0
224 dir /proc 755 0 0
225 dir /sys 755 0 0
226 dir /mnt 755 0 0
227 dir /mnt/root 755 0 0
228 dir /mnt/rootbase 755 0 0
229 dir /mnt/overlay 755 0 0
230 EOF
231     find ${INITRD_DIR} -mindepth 1 -type d -printf "dir /%P %m 0 0\n"
232     find ${INITRD_DIR} -type f -printf "file /%P %p %m 0 0\n"
233     find ${INITRD_DIR} -type l -printf "slink /%P %l %m 0 0\n"
234   ) > filelist
235
236   $GEN_INIT_CPIO filelist | gzip > ${RAMDISK_ARCHIVE}
237
238   return 0
239 }
240
241 function build_initrd_cpio()
242 {
243   ( cd ${INITRD_DIR_ABS} && find . | cpio --quiet -H newc -o  ) | gzip -9 > ${RAMDISK_ARCHIVE}
244 }
245
246 function run_virt_system()
247 {
248   $QEMU ${QEMU_KVM_ENABLE} \
249         -kernel ${KERNEL_IMAGE} \
250         -initrd ${RAMDISK_ARCHIVE} ${QEMU_MEMORY} \
251         -virtfs local,path=/,security_model=none,mount_tag=root \
252         -virtfs local,path=/home,security_model=none,mount_tag=home \
253         -net nic,macaddr=be:be:be:10:00:01,model=virtio,vlan=0 \
254         -net user,vlan=0 \
255         ${QEMU_OUTPUT}
256
257 #     -chardev can,id=canbus0,port=can0
258 #     -device pci-can,chardev=canbus0,model=SJA1000
259 #     -device apohw -vga cirrus
260 #     -device mf624,port=55555
261
262   return $?
263 }
264
265 function clean_setup()
266 {
267   rm -rf ${RAMDISK_ARCHIVE} filelist ${INITRD_DIR_ABS}
268 }
269
270 if [ "$(whoami)" == "root" ] ; then
271   echo "$0: !!! TOO DANGEROUS TO RUN AS ROOT !!!"
272   exit 1;
273 fi
274
275 clean_setup || exit 1
276 echo "=== setup_initrd_content ==="
277 setup_initrd_content || exit 1
278 echo "=== build_initrd ==="
279 if [ -n "${GEN_INIT_CPIO}" ] ; then
280   build_initrd_gen_init_cpio || exit 1
281 else
282   build_initrd_cpio || exit 1
283 fi
284 echo "=== run_virt_system ==="
285 run_virt_system || exit 1