public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [ linus-git ] prctl(PR_SET_KEEPCAPS, ...) is broken for some configs, e.g. CONFIG_SECURITY_SELINUX
@ 2008-06-08 13:38 Dmitry Adamushko
  2008-06-08 15:10 ` Andrew Morgan
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry Adamushko @ 2008-06-08 13:38 UTC (permalink / raw)
  To: Andrew G. Morgan
  Cc: Serge E. Hallyn, Andrew Morton, Linus Torvalds, linux-kernel



The following move-it-back-to-generic-place patch fixes the problem.


---
From: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Subject: fix prctl()'s handling of PR_{SET,GET}_KEEPCAPS
    
with the commit 3898b1b4ebff8dcfbcf1807e0661585e06c9a91c

prctl(PR_SET_KEEPCAPS, {1 | 0}, 0, 0, 0);

always returns -EINVAL for the following configs:

1) CONFIG_SECURITY but without any of CONFIG_SECURITY_* modules;

2) CONFIG_SECURITY + CONFIG_SECURITY_SELINUX + CONFIG_SECURITY_SELINUX_DISABLE

both fall back to 'dummy' implementation.

3) CONFIG_SECURITY + CONFIG_SECURITY_SELINUX

for this config it will work when there is a secondary security module.

Here is what happens:

Processing of PR_SET_KEEPCAPS (and a couple of other options) has been
moved from kernel/sys.c::sys_prctl() to security/commoncap.c::cap_task_prctl().

For the aforementioned configs cap_task_prctl() is not called
(moreover, security/commoncap.c is not compiled).

SELinux's implementation of .task_prctl callback resorts to
secondary_ops->task_prctl() which is dummy_task_prctl() (in the
absence of CONFIG_SECURITY_CAPABILITIES (or any other) as a secondary
module).

So the relevant code should be either moved back to sys_prctl() or
placed in some generic function (not in security/commoncap.c) which is
accessible for all configs.

Move it back to sys_prctl().
    
Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>

----

diff --git a/kernel/sys.c b/kernel/sys.c
index 14e9728..5b8e583 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -24,6 +24,7 @@
 #include <linux/times.h>
 #include <linux/posix-timers.h>
 #include <linux/security.h>
+#include <linux/securebits.h>
 #include <linux/dcookies.h>
 #include <linux/suspend.h>
 #include <linux/tty.h>
@@ -1658,6 +1659,21 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 		return error;
 
 	switch (option) {
+		case PR_GET_KEEPCAPS:
+			if (issecure(SECURE_KEEP_CAPS))
+				error = 1;
+			break;
+		case PR_SET_KEEPCAPS:
+			if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
+				error = -EINVAL;
+			else if (issecure(SECURE_KEEP_CAPS_LOCKED))
+				error = -EPERM;
+			else if (arg2)
+				current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
+			else
+				current->securebits &=
+					~issecure_mask(SECURE_KEEP_CAPS);
+			break;
 		case PR_SET_PDEATHSIG:
 			if (!valid_signal(arg2)) {
 				error = -EINVAL;
@@ -1744,6 +1760,12 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
 		case PR_SET_TSC:
 			error = SET_TSC_CTL(arg2);
 			break;
+		case PR_CAPBSET_READ:
+			if (!cap_valid(arg2))
+				error = -EINVAL;
+			else
+				error = !!cap_raised(current->cap_bset, arg2);
+			break;
 		default:
 			error = -EINVAL;
 			break;
diff --git a/security/commoncap.c b/security/commoncap.c
index 5edabc7..76f3a76 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -576,12 +576,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 	long error = 0;
 
 	switch (option) {
-	case PR_CAPBSET_READ:
-		if (!cap_valid(arg2))
-			error = -EINVAL;
-		else
-			error = !!cap_raised(current->cap_bset, arg2);
-		break;
 #ifdef CONFIG_SECURITY_FILE_CAPABILITIES
 	case PR_CAPBSET_DROP:
 		error = cap_prctl_drop(arg2);
@@ -631,22 +625,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
 
 #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
 
-	case PR_GET_KEEPCAPS:
-		if (issecure(SECURE_KEEP_CAPS))
-			error = 1;
-		break;
-	case PR_SET_KEEPCAPS:
-		if (arg2 > 1) /* Note, we rely on arg2 being unsigned here */
-			error = -EINVAL;
-		else if (issecure(SECURE_KEEP_CAPS_LOCKED))
-			error = -EPERM;
-		else if (arg2)
-			current->securebits |= issecure_mask(SECURE_KEEP_CAPS);
-		else
-			current->securebits &=
-				~issecure_mask(SECURE_KEEP_CAPS);
-		break;
-
 	default:
 		/* No functionality available - continue with default */
 		return 0;

---


^ permalink raw reply related	[flat|nested] 15+ messages in thread
* [ linus-git ] prctl(PR_SET_KEEPCAPS, ...) is broken for some configs, e.g. CONFIG_SECURITY_SELINUX
@ 2008-06-08 12:40 Dmitry Adamushko
  0 siblings, 0 replies; 15+ messages in thread
From: Dmitry Adamushko @ 2008-06-08 12:40 UTC (permalink / raw)
  To: Andrew G. Morgan; +Cc: Andrew Morton, Linus Torvalds, linux-kernel

Hi,


the commit 3898b1b4ebff8dcfbcf1807e0661585e06c9a91c has broken (always
-EINVAL as a return value)

prctl(PR_SET_KEEPCAPS, {1 | 0}, 0, 0, 0);


for the following configs:

1) CONFIG_SECURITY but without any of CONFIG_SECURITY_* modules;

2) CONFIG_SECURITY + CONFIG_SECURITY_SELINUX + CONFIG_SECURITY_SELINUX_DISABLE

both fall back to 'dummy' implementation.

3) CONFIG_SECURITY + CONFIG_SECURITY_SELINUX

for this config it will work when there is a secondary security module.


Here is what happens:

Processing of PR_SET_KEEPCAPS (and a couple of other options) has been
moved from kernel/sys.c::sys_prctl()
to security/commoncap.c::cap_task_prctl().

For the aforementioned configs cap_task_prctl() is not called
(moreover, security/commoncap.c is not compiled).

SELinux's implementation of .task_prctl callback resorts to
secondary_ops->task_prctl() which is dummy_task_prctl() (in the
absence of CONFIG_SECURITY_CAPABILITIES (or any other) as a secondary
module).


So the relevant code should be either moved back to sys_prctl() or
placed in some generic function (not in security/commoncap.c) which is
accessible for all configs.


p.s. perhaps, some would argue that such behavior might have its own
advantages. e.g. 'dhclient' on Ubuntu (for sure on 7.04) refuses to
work and, as a result, a crowd of Ubuntu followers turn their backs on
the virtual world and finally spend more time with their families. It
might be also good for the noble cause of fighting global warming...
heh, provided people don't escape into another virtual world by means
of shiny plasma-TVs :-)


-- 
Best regards,
Dmitry Adamushko

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2008-06-11 14:21 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-08 13:38 [ linus-git ] prctl(PR_SET_KEEPCAPS, ...) is broken for some configs, e.g. CONFIG_SECURITY_SELINUX Dmitry Adamushko
2008-06-08 15:10 ` Andrew Morgan
2008-06-08 18:06   ` Andrew Morton
2008-06-08 22:34     ` Andrew Morgan
2008-06-08 23:39       ` Andrew Morton
2008-06-09 17:17         ` Serge E. Hallyn
2008-06-10  4:26           ` [PATCH] bugfix: was " Andrew G. Morgan
2008-06-10  5:21             ` Andrew Morton
2008-06-10 19:12             ` Serge E. Hallyn
2008-06-11  0:39               ` Andrew G. Morgan
2008-06-10 19:14             ` Chris Wright
2008-06-11  0:37               ` Andrew G. Morgan
2008-06-11 14:21                 ` Dmitry Adamushko
2008-06-10 16:12           ` Chris Wright
  -- strict thread matches above, loose matches on Subject: below --
2008-06-08 12:40 Dmitry Adamushko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox