#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <linux/capability.h>
#include <linux/limits.h>
#include <linux/sched.h>
#include <sched.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/epoll.h>
#include <sys/personality.h>
+#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
return default_logging_callback(pakfire, NULL, priority, line, length);
}
+static int pakfire_drop_capabilities(struct pakfire* pakfire) {
+ 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,
+ };
+
+ 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(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(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(pakfire, "cap_set_flag() failed: %m\n");
+ goto ERROR;
+ }
+
+ // Restore capabilities
+ r = cap_set_proc(caps);
+ if (r) {
+ ERROR(pakfire, "Could not restore capabilities: %m\n");
+ goto ERROR;
+ }
+
+ERROR:
+ if (caps)
+ cap_free(caps);
+
+ return r;
+}
+
static int find_environ(struct pakfire_execute* env, const char* key) {
if (!key) {
errno = EINVAL;
if (r)
return r;
+ // Drop capabilities
+ r = pakfire_drop_capabilities(pakfire);
+ if (r)
+ return r;
+
// exec() command
r = execvpe(env->argv[0], (char**)env->argv, env->envp);
if (r < 0) {