add caps module, to drop capabilities
authorHarald Hoyer <harald@redhat.com>
Wed, 9 Mar 2011 17:10:54 +0000 (18:10 +0100)
committerHarald Hoyer <harald@redhat.com>
Thu, 10 Mar 2011 16:22:56 +0000 (17:22 +0100)
This adds the following parameters:
rd.caps=1
turn the caps module on/off
rd.caps.initdrop=cap_sys_module,cap_sys_rawio
drop the specified comma seperated capabilities
rd.caps.disablemodules=1
turn off module loading
rd.caps.disablekexec=1
turn off the kexec functionality

If module loading is turned off, all modules have to be loaded in the
initramfs, which are used later on. This can be done with
"rd.driver.pre="
rd.driver.pre=autofs4,sunrpc,ipt_REJECT,nf_conntrack_ipv4,....

Because the kernel command line would get huge with all those drivers, I
recommend to make use of $initramfs/etc/cmdline.

So, all rd.caps.* and rd.driver.pre arguments are in caps.conf can be
copied to $initramfs/etc/cmdline with "-i caps.conf /etc/cmdline".

Also all modules have to be loaded in the initramfs via "--add-drivers".

The resulting initramfs creation would look like this:

  --add-drivers "autofs4 sunrpc ipt_REJECT nf_conntrack_ipv4 \
  nf_defrag_ipv4 iptable_filter ip_tables
  ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack
  ip6table_filter ip6_tables dm_mirror dm_region_hash dm_log uinput ppdev
  parport_pc parport ipv6 sg 8139too 8139cp mii i2c_piix4 i2c_core ext3
  jbd mbcache sd_mod crc_t10dif sr_mod cdrom ata_generic pata_acpi ata_piix
  dm_mod" \
  /boot/initramfs-caps.img

modules.d/02caps/README [new file with mode: 0644]
modules.d/02caps/caps.sh [new file with mode: 0755]
modules.d/02caps/module-setup.sh [new file with mode: 0755]
modules.d/99base/init

diff --git a/modules.d/02caps/README b/modules.d/02caps/README
new file mode 100644 (file)
index 0000000..57d2538
--- /dev/null
@@ -0,0 +1,33 @@
+This adds the following parameters:
+rd.caps=1
+        turn the caps module on/off
+rd.caps.initdrop=cap_sys_module,cap_sys_rawio
+        drop the specified comma seperated capabilities
+rd.caps.disablemodules=1
+        turn off module loading
+rd.caps.disablekexec=1
+        turn off the kexec functionality
+
+If module loading is turned off, all modules have to be loaded in the
+initramfs, which are used later on. This can be done with
+"rd.driver.pre="
+rd.driver.pre=autofs4,sunrpc,ipt_REJECT,nf_conntrack_ipv4,....
+
+Because the kernel command line would get huge with all those drivers, I
+recommend to make use of $initramfs/etc/cmdline.
+
+So, all rd.caps.* and rd.driver.pre arguments are in caps.conf can be
+copied to $initramfs/etc/cmdline with "-i caps.conf /etc/cmdline".
+
+Also all modules have to be loaded in the initramfs via "--add-drivers".
+
+The resulting initramfs creation would look like this:
+
+  --add-drivers "autofs4 sunrpc ipt_REJECT nf_conntrack_ipv4 \
+  nf_defrag_ipv4 iptable_filter ip_tables
+  ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack
+  ip6table_filter ip6_tables dm_mirror dm_region_hash dm_log uinput ppdev
+  parport_pc parport ipv6 sg 8139too 8139cp mii i2c_piix4 i2c_core ext3
+  jbd mbcache sd_mod crc_t10dif sr_mod cdrom ata_generic pata_acpi ata_piix
+  dm_mod" \
+  /boot/initramfs-caps.img
diff --git a/modules.d/02caps/caps.sh b/modules.d/02caps/caps.sh
new file mode 100755 (executable)
index 0000000..1732b70
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+capsmode=$(getarg rd.caps)
+
+if [ "$capsmode" = "1" ]; then
+    CAPS_INIT_DROP=$(getarg rd.caps.initdrop=)
+    CAPS_USERMODEHELPER_BSET=$(capsh --drop="$CAPS_INIT_DROP" -- -c 'while read a b ; do [ "$a" = "CapBnd:" ] && echo $((0x${b:$((${#b}-8)):8})) $((0x${b:$((${#b}-16)):8})) && break; done < /proc/self/status')
+    CAPS_MODULES_DISABLED=$(getarg rd.caps.disablemodules=)
+    CAPS_KEXEC_DISABLED=$(getarg rd.caps.disablekexec=)
+
+    info "Loading CAPS_MODULES $CAPS_MODULES"
+    for i in $CAPS_MODULES;do modprobe $i 2>&1 >/dev/null | vinfo; done
+    
+    if [ "$CAPS_MODULES_DISABLED" = "1" -a -e /proc/sys/kernel/modules_disabled ]; then
+        info "Disabling module loading."
+        echo $CAPS_MODULES_DISABLED > /proc/sys/kernel/modules_disabled
+    fi
+
+    if [ "$CAPS_KEXEC_DISABLED" = "1" -a -e /proc/sys/kernel/kexec_disabled ]; then
+        info "Disabling kexec."
+        echo $CAPS_KEXEC_DISABLED > /proc/sys/kernel/kexec_disabled
+    fi
+
+    info "CAPS_USERMODEHELPER_BSET=$CAPS_USERMODEHELPER_BSET"
+    if [ -e /proc/sys/kernel/usermodehelper/bset ]; then
+        info "Setting usermode helper bounding set."
+        echo $CAPS_USERMODEHELPER_BSET > /proc/sys/kernel/usermodehelper/bset
+        echo $CAPS_USERMODEHELPER_BSET > /proc/sys/kernel/usermodehelper/inheritable
+    fi
+    
+    echo "CAPS_INIT_DROP=\"$CAPS_INIT_DROP\"" > /etc/capsdrop
+    info "Will drop capabilities $CAPS_INIT_DROP from init."
+fi
+
diff --git a/modules.d/02caps/module-setup.sh b/modules.d/02caps/module-setup.sh
new file mode 100755 (executable)
index 0000000..7ad2f25
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+check() {
+    type -P capsh >/dev/null 2>&1
+}
+
+depends() {
+    return 0
+}
+
+install() {
+    inst_hook pre-pivot 99 "$moddir/caps.sh"
+    inst $(type -P capsh 2>/dev/null) /usr/sbin/capsh
+    # capsh wants bash and we need bash also
+    inst /bin/bash && ln -sf bash "${initdir}/bin/sh"
+}
+
index f4da4cc..becc8d4 100755 (executable)
@@ -359,8 +359,19 @@ wait_for_loginit
 
 export PATH="$OLD_PATH"
 
-exec /sbin/switch_root "$NEWROOT" "$INIT" $initargs || {
-    echo "Something went very badly wrong in the initramfs.  Please "
-    echo "file a bug against dracut."
-    emergency_shell
-}
+if [ -f /etc/capsdrop ]; then
+    . /etc/capsdrop
+    info "Calling $INIT with capabilities $CAPS_INIT_DROP dropped."
+    exec /usr/sbin/capsh --drop="$CAPS_INIT_DROP" -- -c "exec /sbin/switch_root \"$NEWROOT\" \"$INIT\" $initargs" || {
+       warn "Command:"
+       warn capsh --drop=$CAPS_INIT_DROP -- -c exec switch_root "$NEWROOT" "$INIT" $initargs
+       warn "failed."
+       emergency_shell
+    }
+else
+    exec /sbin/switch_root "$NEWROOT" "$INIT" $initargs || {
+       warn "Something went very badly wrong in the initramfs.  Please "
+       warn "file a bug against dracut."
+       emergency_shell
+    }
+fi