Linux Kernel Features…
… mit dessen Hilfe Container-Runtimes gebaut werden. Keine Garantie für die Vollständigkeit dieser Liste.
chroot
Um den gestarteten Prozessen ein anderes / vorzugeben. Noch nicht mal ein Linux-Feature und wurde bereits 1979 in Unix implementiert.
# Ich habe da mal was vorbereitet. export mirror=http://dl-3.alpinelinux.org/alpine/ export chroot_dir=/root/alpine export version=2.6.7-r0 wget ${mirror}/latest-stable/main/x86_64/apk-tools-static-${version}.apk tar -xzf apk-tools-static-*.apk ./sbin/apk.static -X ${mirror}/latest-stable/main -U --allow-untrusted --root ${chroot_dir} --initdb add alpine-base mknod -m 666 ${chroot_dir}/dev/full c 1 7 mknod -m 666 ${chroot_dir}/dev/ptmx c 5 2 mknod -m 644 ${chroot_dir}/dev/random c 1 8 mknod -m 644 ${chroot_dir}/dev/urandom c 1 9 mknod -m 666 ${chroot_dir}/dev/zero c 1 5 mknod -m 666 ${chroot_dir}/dev/tty c 5 0 cp /etc/resolv.conf ${chroot_dir}/etc/ mkdir -p ${chroot_dir}/root mkdir -p ${chroot_dir}/etc/apk echo "${mirror}/${branch}/main" > ${chroot_dir}/etc/apk/repositories mount -t proc none ${chroot_dir}/proc mount -o bind /sys ${chroot_dir}/sys chroot ${chroot_dir} /bin/sh -l
Namespaces
Definiert was Prozesse sehen und machen können.
Mount
unshare -m /bin/bash mount -t tmpfs tmpfs /tmp touch /tmp/blah ls -l /tmp ### nur blah Anderes Terminal ls -l /tmp ### orig-stuff aber kein blah
PID
unshare --pid /bin/bash ps -ef ## segmentation fault, da fehlt wohl noch was unshare --pid --mount-proc -f /bin/bash ps -ef UID PID PPID C STIME TTY TIME CMD root 1 0 0 08:26 pts/1 00:00:00 /bin/bash root 4 1 0 08:26 pts/1 00:00:00 ps -ef
User
Wichtig, als != root starten
id -u ## 500 unshare --user --map-root-user /bin/bash id -u ## 0
Trotzdem hat man keine root-Berechtigung!
mount -o tmpfs tmpfs /tmp ## permission denied
Network
man ip-netns ip netns list ip netns add testing ip netns exec testing ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1 ip link add veth0 type veth peer name veth1 ip link set veth1 netns testing ip a ## kein veth1 ip addr add 192.168.0.1/32 dev veth0 ip route add 192.168.0.0/24 dev veth0 ip netns exec testing ip link set veth1 up ip netns exec testing ip addr add 192.168.0.2/32 dev veth1 ip netns exec testing ip route add 192.168.0.0/24 dev veth1 ping 192.168.0.2 ## works ip netns exec testing ip a 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1 7: veth1@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 inet 192.168.0.2/32 scope global veth1
Capabilities
Gezielt Fähigkeiten von Prozessen beschränken. Auch wenn der Prozess als effective user 0 (root) läuft.
man capabilities mount -t tmpfs tmpfs /mnt umount /mnt capsh --drop=CAP_SYS_ADMIN -- id -u ## 0 mount -t tmpfs tmpfs /mnt ## permission denied
cgroups
Resourcen von Prozessen einschränken. Beispiel Memory.
cd /sys/fs/cgroup/memory mkdir testing cd testing ls -l # zeigt u.a. tasks # 2. Console auf und dort die PID ermitteln ls -l # funktioniert echo $$ # Zurück in Console 1 und bash der Console 2 in die cgroup testing aufnehmen echo PID > tasks cat tasks PID echo 1 > memory.limit_in_bytes # Console 2 ls -l Killed
Wie man sieht hängen alle Child Prozesse auch in dieser cgroup!
Weitere Resourenlimits:
- CPU
- blkio
- devices
- pids (Process numbers)
Siehe die Kernel Dokumentation zu cgroups.
seccomp
secure computing mode. Gezieltes filtern von system calls. Leider habe ich hier kein einfaches Beispiel.
AppArmor / SELinux / SMACK
Mandatory Access Control im Linux Kernel. Es gibt verschiedene Implementierungen. Ubuntu verwendet z.B. AppArmor.
Auf Ubuntu
vi /etc/apparmor.d/usr.sbin.rsyslogd ... /usr/sbin/rsyslogd { # rsyslog configuration /etc/rsyslog.conf r, /etc/rsyslog.d/ r, /etc/rsyslog.d/** r, /{,var/}run/rsyslogd.pid rwk, /var/spool/rsyslog/ r, /var/spool/rsyslog/** rwk ... }
AppArmor wird unter Ubuntu auch dazu verwendet den Zugriff von VMs-Prozessen einzuschränken. Damit wird der Schaden potentielle Schaden bei einem Ausbruch aus der VM verringert.
Zum Schluss
Alle der genannten Features existieren schon einige Jahre im Linux-Kernel. Vorläufer davon existieren in Form von OpenVZ / Parallels Virtuozzo bereits seit ca. 2000. Allerdings außerhalb des Mainline Kernels gepflegt. Die Features können nicht nur dafür benutzt werden um Container Runtimes wie Docker oder CoreOS rkt zu erstellen, man kann auch "regulär im System" laufende Anwendungen damit einpferchen. Auch systemd bietet Flags, die einige der angesprochenen Techniken verweden um Prozesse besser voneinander zu trennen. Siehe dazu Security Features in systemd.