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

This patch adds new permission checks to the SELinux mmap and mprotect hooks
to enable control over the ability to make executable a mapping that can
contain data not covered by the existing file-based permission checks.

The task->self execmem permission controls the ability to create an executable
anonymous mapping or a writable executable private file mapping.  The
task->file execmod permission controls the ability to make executable a
previously written private file mapping, e.g.  for text relocations.  Thanks
to Roland McGrath for input and feedback on earlier versions of this patch.  

Signed-off-by:  Stephen Smalley <sds@epoch.ncsc.mil>
Signed-off-by:  James Morris <jmorris@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/security/selinux/hooks.c                     |   23 +++++++++++++++++++
 25-akpm/security/selinux/include/av_perm_to_string.h |    2 +
 25-akpm/security/selinux/include/av_permissions.h    |    2 +
 3 files changed, 27 insertions(+)

diff -puN security/selinux/hooks.c~selinux-enhance-selinux-control-of-executable-mappings security/selinux/hooks.c
--- 25/security/selinux/hooks.c~selinux-enhance-selinux-control-of-executable-mappings	Thu Dec  2 12:56:50 2004
+++ 25-akpm/security/selinux/hooks.c	Thu Dec  2 12:56:50 2004
@@ -2443,6 +2443,17 @@ static int selinux_file_ioctl(struct fil
 
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
+	if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
+		/*
+		 * We are making executable an anonymous mapping or a
+		 * private file mapping that will also be writable.
+		 * This has an additional check.
+		 */
+		int rc = task_has_perm(current, current, PROCESS__EXECMEM);
+		if (rc)
+			return rc;
+	}
+
 	if (file) {
 		/* read access is always possible with a mapping */
 		u32 av = FILE__READ;
@@ -2480,6 +2491,18 @@ static int selinux_file_mprotect(struct 
 	if (rc)
 		return rc;
 
+	if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
+		/*
+		 * We are making executable a file mapping that has
+		 * had some COW done. Since pages might have been written,
+		 * check ability to execute the possibly modified content.
+		 * This typically should only occur for text relocations.
+		 */
+		int rc = file_has_perm(current, vma->vm_file, FILE__EXECMOD);
+		if (rc)
+			return rc;
+	}
+
 	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
 }
 
diff -puN security/selinux/include/av_permissions.h~selinux-enhance-selinux-control-of-executable-mappings security/selinux/include/av_permissions.h
--- 25/security/selinux/include/av_permissions.h~selinux-enhance-selinux-control-of-executable-mappings	Thu Dec  2 12:56:50 2004
+++ 25-akpm/security/selinux/include/av_permissions.h	Thu Dec  2 12:56:50 2004
@@ -105,6 +105,7 @@
 
 #define FILE__EXECUTE_NO_TRANS                    0x00020000UL
 #define FILE__ENTRYPOINT                          0x00040000UL
+#define FILE__EXECMOD                             0x00080000UL
 
 #define LNK_FILE__IOCTL                           0x00000001UL
 #define LNK_FILE__READ                            0x00000002UL
@@ -458,6 +459,7 @@
 #define PROCESS__RLIMITINH                        0x00400000UL
 #define PROCESS__DYNTRANSITION                    0x00800000UL
 #define PROCESS__SETCURRENT                       0x01000000UL
+#define PROCESS__EXECMEM                          0x02000000UL
 
 #define IPC__CREATE                               0x00000001UL
 #define IPC__DESTROY                              0x00000002UL
diff -puN security/selinux/include/av_perm_to_string.h~selinux-enhance-selinux-control-of-executable-mappings security/selinux/include/av_perm_to_string.h
--- 25/security/selinux/include/av_perm_to_string.h~selinux-enhance-selinux-control-of-executable-mappings	Thu Dec  2 12:56:50 2004
+++ 25-akpm/security/selinux/include/av_perm_to_string.h	Thu Dec  2 12:56:50 2004
@@ -16,6 +16,7 @@
    S_(SECCLASS_DIR, DIR__RMDIR, "rmdir")
    S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans")
    S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint")
+   S_(SECCLASS_FILE, FILE__EXECMOD, "execmod")
    S_(SECCLASS_FD, FD__USE, "use")
    S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto")
    S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn")
@@ -64,6 +65,7 @@
    S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh")
    S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition")
    S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent")
+   S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
    S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
    S_(SECCLASS_MSG, MSG__SEND, "send")
    S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
_