]> git.ipfire.org Git - people/stevee/pakfire.git/commitdiff
jail: Drop capabilities
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 2 Aug 2022 14:40:09 +0000 (14:40 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 2 Aug 2022 14:40:09 +0000 (14:40 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/jail.c

index 57efb93abbc74cfb05fa751bc6634f865b70b742..16539d1216739967d9301e0b8d27d2c5db011454 100644 (file)
 #############################################################################*/
 
 #include <errno.h>
+#include <linux/capability.h>
 #include <linux/sched.h>
 #include <sched.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <syscall.h>
+#include <sys/capability.h>
 #include <sys/eventfd.h>
 #include <sys/personality.h>
+#include <sys/prctl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -222,6 +225,122 @@ int pakfire_jail_set_env(struct pakfire_jail* jail, const char* key, const char*
        return 0;
 }
 
+// Capabilities
+
+static int pakfire_jail_drop_capabilities(struct pakfire_jail* jail) {
+       const int capabilities[] = {
+               // Deny access to the kernel's audit system
+               CAP_AUDIT_CONTROL,
+               CAP_AUDIT_READ,
+               CAP_AUDIT_WRITE,
+
+               // Deny suspending block devices
+               CAP_BLOCK_SUSPEND,
+
+               // Deny any stuff with BPF
+               CAP_BPF,
+
+               // Deny checkpoint restore
+               CAP_CHECKPOINT_RESTORE,
+
+               // Deny opening files by inode number (open_by_handle_at)
+               CAP_DAC_READ_SEARCH,
+
+               // Deny setting SUID bits
+               CAP_FSETID,
+
+               // Deny locking more memory
+               CAP_IPC_LOCK,
+
+               // Deny modifying any Apparmor/SELinux/SMACK configuration
+               CAP_MAC_ADMIN,
+               CAP_MAC_OVERRIDE,
+
+               // Deny creating any special devices
+               CAP_MKNOD,
+
+               // Deny setting any capabilities
+               CAP_SETFCAP,
+
+               // Deny reading from syslog
+               CAP_SYSLOG,
+
+               // Deny any admin actions (mount, sethostname, ...)
+               CAP_SYS_ADMIN,
+
+               // Deny rebooting the system
+               CAP_SYS_BOOT,
+
+               // Deny loading kernel modules
+               CAP_SYS_MODULE,
+
+               // Deny setting nice level
+               CAP_SYS_NICE,
+
+               // Deny access to /proc/kcore, /dev/mem, /dev/kmem
+               CAP_SYS_RAWIO,
+
+               // Deny circumventing any resource limits
+               CAP_SYS_RESOURCE,
+
+               // Deny setting the system time
+               CAP_SYS_TIME,
+
+               // Deny playing with suspend
+               CAP_WAKE_ALARM,
+
+               0,
+       };
+
+       DEBUG(jail->pakfire, "Dropping capabilities...\n");
+
+       size_t num_caps = 0;
+       int r;
+
+       // Drop any capabilities
+       for (const int* cap = capabilities; *cap; cap++) {
+               r = prctl(PR_CAPBSET_DROP, *cap, 0, 0, 0);
+               if (r) {
+                       ERROR(jail->pakfire, "Could not drop capability %d: %m\n", *cap);
+                       return r;
+               }
+
+               num_caps++;
+       }
+
+       // Fetch any capabilities
+       cap_t caps = cap_get_proc();
+       if (!caps) {
+               ERROR(jail->pakfire, "Could not read capabilities: %m\n");
+               return 1;
+       }
+
+       /*
+               Set inheritable capabilities
+
+               This ensures that no processes will be able to gain any of the listed
+               capabilities again.
+       */
+       r = cap_set_flag(caps, CAP_INHERITABLE, num_caps, capabilities, CAP_CLEAR);
+       if (r) {
+               ERROR(jail->pakfire, "cap_set_flag() failed: %m\n");
+               goto ERROR;
+       }
+
+       // Restore capabilities
+       r = cap_set_proc(caps);
+       if (r) {
+               ERROR(jail->pakfire, "Could not restore capabilities: %m\n");
+               goto ERROR;
+       }
+
+ERROR:
+       if (caps)
+               cap_free(caps);
+
+       return r;
+}
+
 // UID/GID Mapping
 
 static int pakfire_jail_write_uidgid_mapping(struct pakfire_jail* jail,
@@ -462,6 +581,11 @@ static int pakfire_jail_child(struct pakfire_jail* jail, const char* argv[], int
        if (r)
                return r;
 
+       // Drop capabilities
+       r = pakfire_jail_drop_capabilities(jail);
+       if (r)
+               return r;
+
        return 0;
 }