[PATCH 3/4] mm: Add a NO_INHERIT flag to the PR_SET_MDWE prctl

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This extends the current PR_SET_MDWE prctl arg with a bit to indicate
that the process doesn't want MDWE protection to propagate to children.

To implement this no-inherit mode, the tag in current->mm->flags must be
absent from MMF_INIT_MASK. This means that the encoding for "MDWE but
without inherit" is different in the prctl than in the mm flags. This
leads to a bit of bit-mangling in the prctl implementation.

Signed-off-by: Florent Revest <revest@xxxxxxxxxxxx>
---
 include/linux/mman.h             |  8 +++++++-
 include/linux/sched/coredump.h   |  1 +
 include/uapi/linux/prctl.h       |  1 +
 kernel/sys.c                     | 29 +++++++++++++++++++++++------
 tools/include/uapi/linux/prctl.h |  1 +
 5 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/include/linux/mman.h b/include/linux/mman.h
index cee1e4b566d8..3d7a0b70ad2d 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -157,6 +157,12 @@ calc_vm_flag_bits(unsigned long flags)
 
 unsigned long vm_commit_limit(void);
 
+static inline bool has_mdwe_enabled(struct task_struct *task)
+{
+	return test_bit(MMF_HAS_MDWE, &task->mm->flags) ||
+	       test_bit(MMF_HAS_MDWE_NO_INHERIT, &task->mm->flags);
+}
+
 /*
  * Denies creating a writable executable mapping or gaining executable permissions.
  *
@@ -178,7 +184,7 @@ unsigned long vm_commit_limit(void);
  */
 static inline bool map_deny_write_exec(struct vm_area_struct *vma,  unsigned long vm_flags)
 {
-	if (!test_bit(MMF_HAS_MDWE, &current->mm->flags))
+	if (!has_mdwe_enabled(current))
 		return false;
 
 	if ((vm_flags & VM_EXEC) && (vm_flags & VM_WRITE))
diff --git a/include/linux/sched/coredump.h b/include/linux/sched/coredump.h
index 0ee96ea7a0e9..b2d9659ef863 100644
--- a/include/linux/sched/coredump.h
+++ b/include/linux/sched/coredump.h
@@ -91,4 +91,5 @@ static inline int get_dumpable(struct mm_struct *mm)
 				 MMF_DISABLE_THP_MASK | MMF_HAS_MDWE_MASK)
 
 #define MMF_VM_MERGE_ANY	29
+#define MMF_HAS_MDWE_NO_INHERIT	30
 #endif /* _LINUX_SCHED_COREDUMP_H */
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index f23d9a16507f..31ec44728412 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -284,6 +284,7 @@ struct prctl_mm_map {
 /* Memory deny write / execute */
 #define PR_SET_MDWE			65
 # define PR_MDWE_REFUSE_EXEC_GAIN	1
+# define PR_MDWE_NO_INHERIT		2
 
 #define PR_GET_MDWE			66
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 339fee3eff6a..c864fd42ece1 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2368,12 +2368,25 @@ static inline int prctl_set_mdwe(unsigned long bits, unsigned long arg3,
 	if (arg3 || arg4 || arg5)
 		return -EINVAL;
 
-	if (bits & ~(PR_MDWE_REFUSE_EXEC_GAIN))
+	if (bits & ~(PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT))
 		return -EINVAL;
 
-	if (bits & PR_MDWE_REFUSE_EXEC_GAIN)
-		set_bit(MMF_HAS_MDWE, &current->mm->flags);
-	else if (test_bit(MMF_HAS_MDWE, &current->mm->flags))
+	/* Cannot set NO_INHERIT without REFUSE_EXEC_GAIN */
+	if (bits & PR_MDWE_NO_INHERIT && !(bits & PR_MDWE_REFUSE_EXEC_GAIN))
+		return -EINVAL;
+
+	if (bits & PR_MDWE_REFUSE_EXEC_GAIN) {
+		if (bits & PR_MDWE_NO_INHERIT) {
+			/* Cannot go from inherit mode to no inherit */
+			if (test_bit(MMF_HAS_MDWE, &current->mm->flags))
+				return -EPERM;
+
+			set_bit(MMF_HAS_MDWE_NO_INHERIT, &current->mm->flags);
+		} else {
+			set_bit(MMF_HAS_MDWE, &current->mm->flags);
+			clear_bit(MMF_HAS_MDWE_NO_INHERIT, &current->mm->flags);
+		}
+	} else if (has_mdwe_enabled(current))
 		return -EPERM; /* Cannot unset the flag */
 
 	return 0;
@@ -2385,8 +2398,12 @@ static inline int prctl_get_mdwe(unsigned long arg2, unsigned long arg3,
 	if (arg2 || arg3 || arg4 || arg5)
 		return -EINVAL;
 
-	return test_bit(MMF_HAS_MDWE, &current->mm->flags) ?
-		PR_MDWE_REFUSE_EXEC_GAIN : 0;
+	if (test_bit(MMF_HAS_MDWE, &current->mm->flags))
+		return PR_MDWE_REFUSE_EXEC_GAIN;
+	else if (test_bit(MMF_HAS_MDWE_NO_INHERIT, &current->mm->flags))
+		return PR_MDWE_REFUSE_EXEC_GAIN | PR_MDWE_NO_INHERIT;
+
+	return 0;
 }
 
 static int prctl_get_auxv(void __user *addr, unsigned long len)
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
index 759b3f53e53f..a3424852d2d6 100644
--- a/tools/include/uapi/linux/prctl.h
+++ b/tools/include/uapi/linux/prctl.h
@@ -284,6 +284,7 @@ struct prctl_mm_map {
 /* Memory deny write / execute */
 #define PR_SET_MDWE			65
 # define PR_MDWE_REFUSE_EXEC_GAIN	1
+# define PR_MDWE_NO_INHERIT		2
 
 #define PR_GET_MDWE			66
 
-- 
2.40.1.495.gc816e09b53d-goog




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux