Name: Linux kernel trusted path execution restriction patch Purpose: Restrict users to execute files from a single directory only Author: Robert Annessi Date: 10.09.2007 License: GPLv2 Credits: Brad Spengler (based on grsecurity-2.1.10-2.6.19.2-200701222307.patch) diff -urN linux-2.6.18.orig/fs/compat.c linux-2.6.18-tpe/fs/compat.c --- linux-2.6.18.orig/fs/compat.c 2007-09-10 13:49:23.000000000 +0200 +++ linux-2.6.18-tpe/fs/compat.c 2007-09-10 17:15:27.000000000 +0200 @@ -1567,6 +1567,13 @@ if (retval < 0) goto out; +#ifdef CONFIG_SECURITY_TPE + if (!tpe_check(file)) { + retval = -EACCES; + goto out; + } +#endif + retval = search_binary_handler(bprm, regs); if (retval >= 0) { free_arg_pages(bprm); diff -urN linux-2.6.18.orig/fs/exec.c linux-2.6.18-tpe/fs/exec.c --- linux-2.6.18.orig/fs/exec.c 2007-02-24 00:52:30.000000000 +0100 +++ linux-2.6.18-tpe/fs/exec.c 2007-09-10 17:15:27.000000000 +0200 @@ -57,6 +57,10 @@ #include #endif +#ifdef CONFIG_SECURITY_TPE +extern int tpe_check(const struct file *file); +#endif + int core_uses_pid; char core_pattern[65] = "core"; int suid_dumpable = 0; @@ -1188,6 +1192,13 @@ if (retval < 0) goto out; +#ifdef CONFIG_SECURITY_TPE + if (!tpe_check(file)) { + retval = -EACCES; + goto out; + } +#endif + retval = search_binary_handler(bprm,regs); if (retval >= 0) { free_arg_pages(bprm); diff -urN linux-2.6.18.orig/security/Kconfig linux-2.6.18-tpe/security/Kconfig --- linux-2.6.18.orig/security/Kconfig 2007-02-24 00:52:30.000000000 +0100 +++ linux-2.6.18-tpe/security/Kconfig 2007-09-10 17:55:47.000000000 +0200 @@ -4,6 +4,44 @@ menu "Security options" +config SECURITY_TPE + bool "Trusted Path Execution (TPE)" + help + If you say Y here, you will be able to choose a gid + you want to mark as "untrusted." + Users in this group will only be able to execute files that are in + the trusted directory (specified below). + +config SECURITY_TPE_INVERT + bool "Invert GID option" + depends on SECURITY_TPE + help + If you say Y here, the group you specify in the TPE configuration + will be trusted (not untrusted). This option is useful if you want + the TPE restriction to be applied to most users on the system. + +config SECURITY_TPE_GID + int "GID for untrusted users" + depends on SECURITY_TPE && !SECURITY_TPE_INVERT + default 1000 + +config SECURITY_TPE_GID + int "GID for trusted users" + depends on SECURITY_TPE && SECURITY_TPE_INVERT + default 1000 + help + If you have not selected the "Invert GID option" above, setting this + GID determines what group the TPE restriction will be *enabled* for. + If you have selected the "Invert GID option" above, setting this GID + determines what group the TPE restriction will be *disabled* for. + +config SECURITY_TPE_DIR + string "Trusted directory" + depends on SECURITY_TPE + default "/bin" + help + The "trusted" directory (appending a trailing slash will not work!). + config KEYS bool "Enable access key retention support" help diff -urN linux-2.6.18.orig/security/Makefile linux-2.6.18-tpe/security/Makefile --- linux-2.6.18.orig/security/Makefile 2007-02-24 00:52:30.000000000 +0100 +++ linux-2.6.18-tpe/security/Makefile 2007-09-10 17:15:27.000000000 +0200 @@ -5,6 +5,8 @@ obj-$(CONFIG_KEYS) += keys/ subdir-$(CONFIG_SECURITY_SELINUX) += selinux +obj-$(CONFIG_SECURITY_TPE) += tpe.o + # if we don't select a security model, use the default capabilities ifneq ($(CONFIG_SECURITY),y) obj-y += commoncap.o diff -urN linux-2.6.18.orig/security/tpe.c linux-2.6.18-tpe/security/tpe.c --- linux-2.6.18.orig/security/tpe.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.18-tpe/security/tpe.c 2007-09-10 17:15:27.000000000 +0200 @@ -0,0 +1,25 @@ +#include + +int tpe_check(const struct file *file) +{ + char *buf = (char *)__get_free_page(GFP_KERNEL); + int tpe_gid = CONFIG_SECURITY_TPE_GID; + int pathlen = strlen(CONFIG_SECURITY_TPE_DIR); + + buf = d_path(file->f_dentry, file->f_vfsmnt, buf, PAGE_SIZE); + + if (current->uid && +#ifdef CONFIG_SECURITY_TPE_INVERT + (!in_group_p(tpe_gid)) +#else + (in_group_p(tpe_gid)) +#endif + && (strncmp(buf, CONFIG_SECURITY_TPE_DIR, pathlen) != 0 + || strlen(buf) != pathlen + strlen(file->f_dentry->d_name.name) + + 1)) { + printk(KERN_ALERT "TPE: denied exec of \"%s\" by uid/gid \ + \"%d/%d\"\n", buf, file->f_uid, file->f_gid); + return 0; + } + return 1; +}