
From: Stephen Smalley <sds@epoch.ncsc.mil>

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);

_
