From: Stephen Smalley This patch for 2.5.73 replaces the CAP_SYS_ADMIN test in vm_enough_memory with a security_vm_allocate hook call so that security modules such as SELinux can distinguish this test from other CAP_SYS_ADMIN checks. This change is necessary since the vm_enough_memory capability check is applied to all processes that allocate mappings and we don't want to spuriously audit CAP_SYS_ADMIN denials generated by this test. include/linux/security.h | 22 ++++++++++++++++++++++ mm/mmap.c | 2 +- security/capability.c | 2 ++ security/dummy.c | 8 ++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff -puN include/linux/security.h~security-vm_enough_memory include/linux/security.h --- 25/include/linux/security.h~security-vm_enough_memory 2003-06-23 09:46:28.000000000 -0700 +++ 25-akpm/include/linux/security.h 2003-06-23 09:46:28.000000000 -0700 @@ -63,6 +63,13 @@ static inline int cap_netlink_recv (stru return 0; } +static inline int cap_vm_allocate (void) +{ + if (capable(CAP_SYS_ADMIN)) + return 0; + return -EPERM; +} + /* * Values used in the task_security_ops calls */ @@ -958,6 +965,10 @@ struct swap_info_struct; * See the syslog(2) manual page for an explanation of the @type values. * @type contains the type of action. * Return 0 if permission is granted. + * @vm_allocate: + * Check permissions for allocating memory reserved for privileged + * processes. Called by vm_enough_memory. + * Return 0 if permission is granted. * * @register_security: * allow module stacking. @@ -989,6 +1000,7 @@ struct security_operations { int (*quotactl) (int cmds, int type, int id, struct super_block * sb); int (*quota_on) (struct file * f); int (*syslog) (int type); + int (*vm_allocate) (void); int (*bprm_alloc_security) (struct linux_binprm * bprm); void (*bprm_free_security) (struct linux_binprm * bprm); @@ -1238,6 +1250,11 @@ static inline int security_syslog(int ty return security_ops->syslog(type); } +static inline int security_vm_allocate(void) +{ + return security_ops->vm_allocate(); +} + static inline int security_bprm_alloc (struct linux_binprm *bprm) { return security_ops->bprm_alloc_security (bprm); @@ -1898,6 +1915,11 @@ static inline int security_syslog(int ty return cap_syslog(type); } +static inline int security_vm_allocate(void) +{ + return cap_vm_allocate(); +} + static inline int security_bprm_alloc (struct linux_binprm *bprm) { return 0; diff -puN mm/mmap.c~security-vm_enough_memory mm/mmap.c --- 25/mm/mmap.c~security-vm_enough_memory 2003-06-23 09:46:28.000000000 -0700 +++ 25-akpm/mm/mmap.c 2003-06-23 09:46:28.000000000 -0700 @@ -93,7 +93,7 @@ int vm_enough_memory(long pages) /* * Leave the last 3% for root */ - if (!capable(CAP_SYS_ADMIN)) + if (security_vm_allocate()) free -= free / 32; if (free > pages) diff -puN security/capability.c~security-vm_enough_memory security/capability.c --- 25/security/capability.c~security-vm_enough_memory 2003-06-23 09:46:28.000000000 -0700 +++ 25-akpm/security/capability.c 2003-06-23 09:46:28.000000000 -0700 @@ -307,6 +307,8 @@ static struct security_operations capabi .task_reparent_to_init = cap_task_reparent_to_init, .syslog = cap_syslog, + + .vm_allocate = cap_vm_allocate, }; #if defined(CONFIG_SECURITY_CAPABILITIES_MODULE) diff -puN security/dummy.c~security-vm_enough_memory security/dummy.c --- 25/security/dummy.c~security-vm_enough_memory 2003-06-23 09:46:28.000000000 -0700 +++ 25-akpm/security/dummy.c 2003-06-23 09:46:28.000000000 -0700 @@ -97,6 +97,13 @@ static int dummy_syslog (int type) return 0; } +static int dummy_vm_allocate (void) +{ + if (current->euid) + return -EPERM; + return 0; +} + static int dummy_bprm_alloc_security (struct linux_binprm *bprm) { return 0; @@ -793,6 +800,7 @@ void security_fixup_ops (struct security set_to_dummy_if_null(ops, quota_on); set_to_dummy_if_null(ops, sysctl); set_to_dummy_if_null(ops, syslog); + set_to_dummy_if_null(ops, vm_allocate); set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security); set_to_dummy_if_null(ops, bprm_compute_creds); _