-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,

Attached is a quick RFC patch for modifying the way the LSM's handle
prctl() checks. Currently, the only thing LSMs can do with prctl() calls
is add more restrictions to their use than the default kernel.

What this patch does is make it possible for an LSM to fake a successful
prctl() call, and also support LSM-specific prctl()s; ones that are only
supported when the particular LSM is loaded.

Please comment

Thanks

Andrew
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHhPjP+bHCR3gb8jsRAsYQAJ9hA/SvYNDi1F4ARGH/HGcXEamJEwCglJX6
KjTVxS0qlTd5LGWY2yt9ulY=
=/bv4
-----END PGP SIGNATURE-----
>From 145ec28befdea7f4ff5444985d3f255eaf644e8b Mon Sep 17 00:00:00 2001
From: Andrew G. Morgan <[EMAIL PROTECTED]>
Date: Tue, 8 Jan 2008 22:51:27 -0800
Subject: [PATCH] Add support for the security modules to override/substitute prctl() syscalls

Signed-off-by: Andrew G. Morgan <[EMAIL PROTECTED]>
---
 include/linux/security.h |   11 +++++++----
 kernel/sys.c             |    3 +--
 security/dummy.c         |    3 ++-
 security/security.c      |    4 ++--
 security/selinux/hooks.c |    5 +++--
 5 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 9d199a5..f3ac840 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -687,7 +687,9 @@ struct request_sock;
  *	@arg3 contains a argument.
  *	@arg4 contains a argument.
  *	@arg5 contains a argument.
- *	Return 0 if permission is granted.
+ *      @rc_p contains a pointer to communicate back the forced return code
+ *	Return 0 if permission is granted, and non-zero if the security module
+ *      has taken responsibility (setting *rc_p) for the prctl call.
  * @task_reparent_to_init:
  * 	Set the security attributes in @p->security for a kernel thread that
  * 	is being reparented to the init task.
@@ -1354,7 +1356,7 @@ struct security_operations {
 	int (*task_wait) (struct task_struct * p);
 	int (*task_prctl) (int option, unsigned long arg2,
 			   unsigned long arg3, unsigned long arg4,
-			   unsigned long arg5);
+			   unsigned long arg5, int *rc_p);
 	void (*task_reparent_to_init) (struct task_struct * p);
 	void (*task_to_inode)(struct task_struct *p, struct inode *inode);
 
@@ -1610,7 +1612,7 @@ int security_task_kill(struct task_struct *p, struct siginfo *info,
 			int sig, u32 secid);
 int security_task_wait(struct task_struct *p);
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
-			 unsigned long arg4, unsigned long arg5);
+			 unsigned long arg4, unsigned long arg5, int *rc_p);
 void security_task_reparent_to_init(struct task_struct *p);
 void security_task_to_inode(struct task_struct *p, struct inode *inode);
 int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
@@ -2162,8 +2164,9 @@ static inline int security_task_wait (struct task_struct *p)
 static inline int security_task_prctl (int option, unsigned long arg2,
 				       unsigned long arg3,
 				       unsigned long arg4,
-				       unsigned long arg5)
+				       unsigned long arg5, int *rc_p)
 {
+	*rc_p = 0;
 	return 0;
 }
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 5a61f80..56ff7a2 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1631,8 +1631,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 {
 	long error;
 
-	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
-	if (error)
+	if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error))
 		return error;
 
 	switch (option) {
diff --git a/security/dummy.c b/security/dummy.c
index cdb4352..0c1934f 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -600,8 +600,9 @@ static int dummy_task_kill (struct task_struct *p, struct siginfo *info,
 }
 
 static int dummy_task_prctl (int option, unsigned long arg2, unsigned long arg3,
-			     unsigned long arg4, unsigned long arg5)
+			     unsigned long arg4, unsigned long arg5, int *rc_p)
 {
+	*rc_p = 0;
 	return 0;
 }
 
diff --git a/security/security.c b/security/security.c
index ba45473..2ea0a13 100644
--- a/security/security.c
+++ b/security/security.c
@@ -688,9 +688,9 @@ int security_task_wait(struct task_struct *p)
 }
 
 int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
-			 unsigned long arg4, unsigned long arg5)
+			 unsigned long arg4, unsigned long arg5, int *rc_p)
 {
-	return security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+	return security_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
 }
 
 void security_task_reparent_to_init(struct task_struct *p)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 5d25ec2..8df230d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3209,12 +3209,13 @@ static int selinux_task_prctl(int option,
 			      unsigned long arg2,
 			      unsigned long arg3,
 			      unsigned long arg4,
-			      unsigned long arg5)
+			      unsigned long arg5,
+			      int *rc_p)
 {
 	/* The current prctl operations do not appear to require
 	   any SELinux controls since they merely observe or modify
 	   the state of the current process. */
-	return 0;
+	return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
 }
 
 static int selinux_task_wait(struct task_struct *p)
-- 
1.5.3.7

Reply via email to