summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c23
-rw-r--r--security/selinux/include/av_perm_to_string.h2
-rw-r--r--security/selinux/include/av_permissions.h2
3 files changed, 27 insertions, 0 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index bba852326a0b..a480aa47a9d3 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2437,6 +2437,17 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
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;
@@ -2474,6 +2485,18 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
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 --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index ead4f172f9b8..924832abbe68 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -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")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 592cdf19f669..2df3f166c491 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -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