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.