-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathcreate-gce-image.sh
executable file
·209 lines (190 loc) · 7.83 KB
/
create-gce-image.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#!/usr/bin/env bash
# Copyright 2016 syzkaller project authors. All rights reserved.
# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
# create-gce-image.sh creates a minimal bootable image suitable for syzkaller/GCE in ./disk.raw file.
# The script can also create/delete temp files in the current dir.
#
# Prerequisites:
# - you need a user-space system, a basic Debian system can be created with:
# sudo debootstrap --include=openssh-server,curl,tar,gcc,libc6-dev,time,strace,sudo,less,psmisc,selinux-utils,policycoreutils,checkpolicy,selinux-policy-default,firmware-atheros --components=main,contrib,non-free stable debian
# - you need kernel to use with image (e.g. arch/x86/boot/bzImage)
# note: kernel modules are not supported
# - you need grub:
# sudo apt-get install grub-efi
#
# Usage:
# ./create-gce-image.sh /dir/with/user/space/system /path/to/{zImage,bzImage} [arch]
#
# If SYZ_SYSCTL_FILE env var is set and points to a file,
# then its contents will be appended to the image /etc/sysctl.conf.
# If SYZ_CMDLINE_FILE env var is set and points to a file,
# then its contents will be appended to the kernel command line.
# If MKE2FS_CONFIG env var is set, it will affect invoked mkfs.ext4.
#
# The image then needs to be compressed with:
# tar -Sczf disk.tar.gz disk.raw
# and uploaded to GCS with:
# gsutil cp disk.tar.gz gs://my-images/image.tar.gz
# finally, my-images/image.tar.gz can be used to create a new GCE image.
#
# The image can be tested locally with e.g.:
# qemu-system-x86_64 -hda disk.raw -net user,host=10.0.2.10,hostfwd=tcp::10022-:22 \
# -net nic -enable-kvm -m 2G -display none -serial stdio
# once the kernel boots, you can ssh into it with:
# ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -p 10022 root@localhost
set -eux
CLEANUP=""
trap 'eval " $CLEANUP"' EXIT
IMG_ARCH="${3:-amd64}"
if [ ! -e $1/sbin/init ]; then
echo "usage: create-gce-image.sh /dir/with/user/space/system /path/to/bzImage [arch]"
exit 1
fi
case "$IMG_ARCH" in
386|amd64|s390x)
KERNEL_IMAGE_BASENAME=bzImage
;;
ppc64le)
KERNEL_IMAGE_BASENAME=zImage.pseries
;;
esac
if [ "$(basename $2)" != "$KERNEL_IMAGE_BASENAME" ]; then
echo "usage: create-gce-image.sh /dir/with/user/space/system /path/to/bzImage [arch]"
exit 1
fi
# qemu-nbd is broken on Debian with:
# Calling ioctl() to re-read partition table.
# Re-reading the partition table failed.: Invalid argument
# The kernel still uses the old table. The new table will be used at the
# next reboot or after you run partprobe(8) or kpartx(8).
# losetup is broken on Ubuntu with some other error.
# Try to figure out what will work.
BLOCK_DEVICE="loop"
if [ "$(uname -a | grep Ubuntu)" != "" ]; then
BLOCK_DEVICE="nbd"
fi
# Clean up after previous unsuccessful run.
sudo umount disk.mnt || true
if [ "$BLOCK_DEVICE" == "loop" ]; then
:
elif [ "$BLOCK_DEVICE" == "nbd" ]; then
sudo modprobe nbd
sudo qemu-nbd -d /dev/nbd0 || true
fi
rm -rf disk.mnt disk.raw || true
fallocate -l 2G disk.raw
if [ "$BLOCK_DEVICE" == "loop" ]; then
DISKDEV="$(sudo losetup -f --show -P disk.raw)"
CLEANUP="sudo losetup -d $DISKDEV; $CLEANUP"
elif [ "$BLOCK_DEVICE" == "nbd" ]; then
DISKDEV="/dev/nbd0"
sudo qemu-nbd -c $DISKDEV --format=raw disk.raw
CLEANUP="sudo qemu-nbd -d $DISKDEV; $CLEANUP"
fi
case "$IMG_ARCH" in
386|amd64|s390x)
echo -en "o\nn\np\n1\n\n\na\nw\n" | sudo fdisk $DISKDEV
PARTDEV=$DISKDEV"p1"
;;
ppc64le)
# Create a small PowerPC PReP boot partition, and a Linux partition for the rest
echo -en "o\nn\np\n1\n2048\n16383\na\nt\n41\nn\np\n2\n\n\nw\n" | sudo fdisk $DISKDEV
PARTDEV=$DISKDEV"p2"
;;
esac
until [ -e $PARTDEV ]; do sleep 1; done
sudo -E mkfs.ext4 -O ^resize_inode,^has_journal,ext_attr,extents,huge_file,flex_bg,dir_nlink,sparse_super $PARTDEV
mkdir -p disk.mnt
CLEANUP="rm -rf disk.mnt; $CLEANUP"
sudo mount $PARTDEV disk.mnt
CLEANUP="sudo umount disk.mnt; $CLEANUP"
sudo cp -a $1/. disk.mnt/.
sudo cp $2 disk.mnt/vmlinuz
sudo sed -i "/^root/ { s/:x:/::/ }" disk.mnt/etc/passwd
echo "T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100" | sudo tee -a disk.mnt/etc/inittab
echo -en "auto lo\niface lo inet loopback\nauto eth0\niface eth0 inet dhcp\n" | sudo tee disk.mnt/etc/network/interfaces
echo '/dev/root / ext4 defaults 0 0' | sudo tee -a disk.mnt/etc/fstab
echo "debugfs /sys/kernel/debug debugfs defaults 0 0" | sudo tee -a disk.mnt/etc/fstab
echo "securityfs /sys/kernel/security securityfs defaults 0 0" | sudo tee -a disk.mnt/etc/fstab
echo "configfs /sys/kernel/config/ configfs defaults 0 0" | sudo tee -a disk.mnt/etc/fstab
echo 'binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0' | sudo tee -a disk.mnt/etc/fstab
for i in {0..31}; do
echo "KERNEL==\"binder$i\", NAME=\"binder$i\", MODE=\"0666\"" | \
sudo tee -a disk.mnt/etc/udev/50-binder.rules
done
# Add udev rules for custom drivers.
# Create a /dev/vim2m symlink for the device managed by the vim2m driver
echo 'ATTR{name}=="vim2m", SYMLINK+="vim2m"' | sudo tee -a disk.mnt/etc/udev/rules.d/50-udev-default.rules
# Create a /dev/i915 symlink to /dev/dri/card# if i915 driver is in use.
echo 'SUBSYSTEMS=="pci", DRIVERS=="i915", SYMLINK+="i915"' | sudo tee -a disk.mnt/etc/udev/rules.d/60-drm.rules
# sysctls
SYZ_SYSCTL_FILE="${SYZ_SYSCTL_FILE:-}"
if [ "$SYZ_SYSCTL_FILE" != "" ]; then
cat $SYZ_SYSCTL_FILE | sudo tee -a disk.mnt/etc/sysctl.conf
fi
echo -en "127.0.0.1\tlocalhost\n" | sudo tee disk.mnt/etc/hosts
echo "nameserver 8.8.8.8" | sudo tee -a disk.mnt/etc/resolv.conf
echo "syzkaller" | sudo tee disk.mnt/etc/hostname
sudo mkdir -p disk.mnt/boot/grub
# Setup ssh without key/password.
cat << EOF | sudo tee disk.mnt/etc/ssh/sshd_config
PermitRootLogin yes
PasswordAuthentication yes
PermitEmptyPasswords yes
ClientAliveInterval 420
Subsystem sftp /usr/lib/openssh/sftp-server
EOF
# Reset root password.
sudo sed -i "s#^root:\*:#root::#g" disk.mnt/etc/shadow
CMDLINE=""
SYZ_CMDLINE_FILE="${SYZ_CMDLINE_FILE:-}"
if [ "$SYZ_CMDLINE_FILE" != "" ]; then
CMDLINE=$(awk '{printf("%s ", $0)}' $SYZ_CMDLINE_FILE)
fi
case "$IMG_ARCH" in
386|amd64)
cat << EOF | sudo tee disk.mnt/boot/grub/grub.cfg
terminal_input console
terminal_output console
set timeout=0
# vsyscall=native: required to run x86_64 executables on android kernels
# (for some reason they disable VDSO by default)
# panic=86400: prevents kernel from rebooting so that we don't get reboot output in all crash reports
# debug is not set as it produces too much output
menuentry 'linux' --class gnu-linux --class gnu --class os {
insmod vbe
insmod vga
insmod video_bochs
insmod video_cirrus
insmod gzio
insmod part_msdos
insmod ext2
set root='(hd0,1)'
linux /vmlinuz root=/dev/sda1 console=ttyS0 earlyprintk=serial vsyscall=native net.ifnames=0 sysctl.kernel.hung_task_all_cpu_backtrace=1 $CMDLINE
}
EOF
sudo grub-install --target=i386-pc --boot-directory=disk.mnt/boot --no-floppy $DISKDEV
;;
ppc64le)
cat << EOF | sudo tee disk.mnt/boot/grub/grub.cfg
terminal_input console
terminal_output console
set timeout=0
# panic=86400: prevents kernel from rebooting so that we don't get reboot output in all crash reports
# debug is not set as it produces too much output
menuentry 'linux' --class gnu-linux --class gnu --class os {
insmod gzio
insmod part_msdos
insmod ext2
search -f --set /vmlinuz
linux /vmlinuz root=/dev/sda2 rootwait console=ttyS0 earlyprintk=serial oops=panic panic_on_warn=1 nmi_watchdog=panic panic=60 net.ifnames=0 $CMDLINE
}
EOF
sudo grub-install --target=powerpc-ieee1275 --boot-directory=disk.mnt/boot $DISKDEV"p1"
;;
s390x)
sudo zipl -V -t disk.mnt/boot -i disk.mnt/vmlinuz \
-P "root=/dev/vda1 console=ttyS0 earlyprintk=serial oops=panic panic_on_warn=1 nmi_watchdog=panic panic=86400 net.ifnames=0 sysctl.kernel.hung_task_all_cpu_backtrace=1 net.ifnames=0 biosdevname=0 $CMDLINE" \
--targetbase=$DISKDEV --targettype=SCSI --targetblocksize=512 --targetoffset=2048
;;
esac