From: James Morris This patch adds controls to the SELinux module over the setting and inheritance of resource limits. With these controls, the ability to set hard limits can be limited to specific processes such as login, and when an untrusted process invokes a more trusted program, soft limits can be reset, thereby avoiding failures in the trusted program due to malicious setting of the soft limit by the untrusted process. Roland McGrath provided input and feedback on the patch, which was implemented by Stephen Smalley . --- 25-akpm/security/selinux/hooks.c | 34 ++++++++++++++++--- 25-akpm/security/selinux/include/av_perm_to_string.h | 2 + 25-akpm/security/selinux/include/av_permissions.h | 2 + 3 files changed, 34 insertions(+), 4 deletions(-) diff -puN security/selinux/hooks.c~selinux-01-resource-limit-control security/selinux/hooks.c --- 25/security/selinux/hooks.c~selinux-01-resource-limit-control Fri Jan 9 12:49:27 2004 +++ 25-akpm/security/selinux/hooks.c Fri Jan 9 12:49:27 2004 @@ -1516,6 +1516,7 @@ static void selinux_bprm_compute_creds(s u32 sid; struct av_decision avd; struct itimerval itimer; + struct rlimit *rlim, *initrlim; int rc, i; secondary_ops->bprm_compute_creds(bprm); @@ -1586,6 +1587,26 @@ static void selinux_bprm_compute_creds(s spin_unlock_irq(¤t->sighand->siglock); } + /* Check whether the new SID can inherit resource limits + from the old SID. If not, reset all soft limits to + the lower of the current task's hard limit and the init + task's soft limit. Note that the setting of hard limits + (even to lower them) can be controlled by the setrlimit + check. The inclusion of the init task's soft limit into + the computation is to avoid resetting soft limits higher + than the default soft limit for cases where the default + is lower than the hard limit, e.g. RLIMIT_CORE or + RLIMIT_STACK.*/ + rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, + PROCESS__RLIMITINH, NULL, NULL); + if (rc) { + for (i = 0; i < RLIM_NLIMITS; i++) { + rlim = current->rlim + i; + initrlim = init_task.rlim+i; + rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); + } + } + /* Wake up the parent if it is waiting so that it can recheck wait permission to the new task SID. */ wake_up_interruptible(¤t->parent->wait_chldexit); @@ -2222,10 +2243,15 @@ static int selinux_task_setnice(struct t static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { - /* SELinux does not currently provide a process - resource limit policy based on security contexts. - It does control the use of the CAP_SYS_RESOURCE capability - using the capable hook. */ + struct rlimit *old_rlim = current->rlim + resource; + + /* Control the ability to change the hard limit (whether + lowering or raising it), so that the hard limit can + later be used as a safe reset point for the soft limit + upon context transitions. See selinux_bprm_compute_creds. */ + if (old_rlim->rlim_max != new_rlim->rlim_max) + return task_has_perm(current, current, PROCESS__SETRLIMIT); + return 0; } diff -puN security/selinux/include/av_permissions.h~selinux-01-resource-limit-control security/selinux/include/av_permissions.h --- 25/security/selinux/include/av_permissions.h~selinux-01-resource-limit-control Fri Jan 9 12:49:27 2004 +++ 25-akpm/security/selinux/include/av_permissions.h Fri Jan 9 12:49:27 2004 @@ -451,6 +451,8 @@ #define PROCESS__SETFSCREATE 0x00040000UL #define PROCESS__NOATSECURE 0x00080000UL #define PROCESS__SIGINH 0x00100000UL +#define PROCESS__SETRLIMIT 0x00200000UL +#define PROCESS__RLIMITINH 0x00400000UL #define IPC__SETATTR 0x00000008UL #define IPC__READ 0x00000010UL diff -puN security/selinux/include/av_perm_to_string.h~selinux-01-resource-limit-control security/selinux/include/av_perm_to_string.h --- 25/security/selinux/include/av_perm_to_string.h~selinux-01-resource-limit-control Fri Jan 9 12:49:27 2004 +++ 25-akpm/security/selinux/include/av_perm_to_string.h Fri Jan 9 12:49:27 2004 @@ -67,6 +67,8 @@ static struct av_perm_to_string av_perm_ { SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate" }, { SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure" }, { SECCLASS_PROCESS, PROCESS__SIGINH, "siginh" }, + { SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit" }, + { SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh" }, { SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue" }, { SECCLASS_MSG, MSG__SEND, "send" }, { SECCLASS_MSG, MSG__RECEIVE, "receive" }, _