[PATCH 3/6] file capabilities: uninline cap_safe_nice

Previous thread: [PATCH 1/6] file capabilities: add no_file_caps switch (v3) by Serge E. Hallyn on Friday, September 26, 2008 - 7:27 pm. (4 messages)

Next thread: inconsistent lock state. (kvm) by Dave Jones on Friday, September 26, 2008 - 7:30 pm. (2 messages)
From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

This reduces the kernel size by 289 bytes.

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 security/commoncap.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/security/commoncap.c b/security/commoncap.c
index 9bfef94..d48fdd8 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -512,7 +512,7 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
  * yet with increased caps.
  * So we check for increased caps on the target process.
  */
-static inline int cap_safe_nice(struct task_struct *p)
+static int cap_safe_nice(struct task_struct *p)
 {
 	if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
 	    !capable(CAP_SYS_NICE))
-- 
1.5.1.1.GIT

--

From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

Clean up the sys_capset codepath a bit to account for the fact
that you can now not ever, never, capset on another task.

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 kernel/capability.c |   83 +++++++++++++++++++-------------------------------
 1 files changed, 32 insertions(+), 51 deletions(-)

diff --git a/kernel/capability.c b/kernel/capability.c
index d39c989..92dd85b 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -132,46 +132,31 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy)
  * process. The net result is that we can limit our use of locks to
  * when we are reading the caps of another process.
  */
-static inline int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
+static int cap_get_target_pid(pid_t pid, kernel_cap_t *pEp,
 				     kernel_cap_t *pIp, kernel_cap_t *pPp)
 {
 	int ret;
+	struct task_struct *target;
 
-	if (pid && (pid != task_pid_vnr(current))) {
-		struct task_struct *target;
+	if (!pid || pid == task_pid_vnr(current))
+		return security_capget(current, pEp, pIp, pPp);
 
-		spin_lock(&task_capability_lock);
-		read_lock(&tasklist_lock);
+	spin_lock(&task_capability_lock);
+	read_lock(&tasklist_lock);
 
-		target = find_task_by_vpid(pid);
-		if (!target)
-			ret = -ESRCH;
-		else
-			ret = security_capget(target, pEp, pIp, pPp);
+	target = find_task_by_vpid(pid);
+	if (!target)
+		ret = -ESRCH;
+	else
+		ret = security_capget(target, pEp, pIp, pPp);
 
-		read_unlock(&tasklist_lock);
-		spin_unlock(&task_capability_lock);
-	} else
-		ret = security_capget(current, pEp, pIp, pPp);
+	read_unlock(&tasklist_lock);
+	spin_unlock(&task_capability_lock);
 
 	return ret;
 }
 
 /*
- * With filesystem capability support configured, the kernel does not
- * permit the changing of capabilities in one process by another
- * process. (CAP_SETPCAP has much less broad semantics when configured
- * this way.)
- */
-static inline int do_sys_capset_other_tasks(pid_t pid,
-					    ...
From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

cap_limit_ptraced_target always returns 1, so nix it.

cap_block_setpcap can't return 1 any more, because
kernel/capabilities.c:sys_capset() will return -EPERM
if it is called on a task other than current, and will
never get to cap_capset_check.

This brings the vmlinux size with my config down another
16 bytes (making up for the 8 byte increase from the
last patch).

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 security/commoncap.c |   22 +++-------------------
 1 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/security/commoncap.c b/security/commoncap.c
index d48fdd8..e5afb7c 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -93,15 +93,6 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective,
 	return 0;
 }
 
-static inline int cap_block_setpcap(struct task_struct *target)
-{
-	/*
-	 * No support for remote process capability manipulation with
-	 * filesystem capability support.
-	 */
-	return (target != current);
-}
-
 static inline int cap_inh_is_capped(void)
 {
 	/*
@@ -112,14 +103,9 @@ static inline int cap_inh_is_capped(void)
 	return (cap_capable(current, CAP_SETPCAP) != 0);
 }
 
-static inline int cap_limit_ptraced_target(void) { return 1; }
-
 int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
 		      kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
-	if (cap_block_setpcap(target)) {
-		return -EPERM;
-	}
 	if (cap_inh_is_capped()
 	    && !cap_issubset(*inheritable,
 			     cap_combine(target->cap_inheritable,
@@ -343,11 +329,9 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 				bprm->e_uid = current->uid;
 				bprm->e_gid = current->gid;
 			}
-			if (cap_limit_ptraced_target()) {
-				bprm->cap_post_exec_permitted = cap_intersect(
-					bprm->cap_post_exec_permitted,
-					current->cap_permitted);
-			}
+			bprm->cap_post_exec_permitted = cap_intersect(
+				bprm->cap_post_exec_permitted,
+				current->cap_permitted);
 		}
 ...
From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

Two error conditions at the top of get_file_caps() call
bprm_clear_caps().  However, the bprm capabilities have not
yet been set at this point.

Remove those calls (saving another 16 bytes on vmlinux).

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
---
 security/commoncap.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/security/commoncap.c b/security/commoncap.c
index e5afb7c..43bba7a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -250,15 +250,11 @@ static int get_file_caps(struct linux_binprm *bprm)
 	struct vfs_cap_data vcaps;
 	struct inode *inode;
 
-	if (!file_caps_enabled) {
-		bprm_clear_caps(bprm);
+	if (!file_caps_enabled)
 		return 0;
-	}
 
-	if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
-		bprm_clear_caps(bprm);
+	if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)
 		return 0;
-	}
 
 	dentry = dget(bprm->file->f_dentry);
 	inode = dentry->d_inode;
-- 
1.5.1.1.GIT

--

From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

Andrew Morgan, if you have a moment, please do take a close look
and make sure I'm not doing anything stupid/wrong in the cleanups!
However ltp shows no difference with and without the patchset.

Following are the kernel sizes after some of the patches.

original, pre-patch, with file capabilities compiled out:
   text    data     bss     dec     hex filename
4188468  234432  316472 4739372  48512c vmlinux

original, pre-patch, with file capabilities compiled in:
4189356  234432  316472 4740260  4854a4 vmlinux

plain with fcaps always-on:
4189392  234456  316472 4740320  4854e0 vmlinux

with non-inline cap_safe_nice:
4189112  234456  316472 4740040  4853c8 vmlinux

with cleaned-up setcap:
4189120  234456  316472 4740048  4853d0 vmlinux

with needless check for target!=current removed from cap_capset:
4189104  234456  316472 4740032  4853c0 vmlinux

with needless(?) bprm_clear_caps calls removed:
4189088  234456  316472 4740016  4853b0 vmlinux


thanks,
-serge
--

From: Serge E. Hallyn
Date: Friday, September 26, 2008 - 7:27 pm

From: Andrew G. Morgan
Date: Friday, September 26, 2008 - 9:39 pm

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

Serge,

I'd much rather simply remove the target argument from the
security_capset_check() call. Relying on the caller to not do something
bad seems fragile... If the code internally operates on current only,
then it doesn't need a target argument... No? (Evidently, such a change
is also needed to selinux_capset_check() too, but this doesn't look like
it will pose a problem for the selinux code.)

Cheers

Andrew

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

iD8DBQFI3bjz+bHCR3gb8jsRAqJpAJ9Ca1pADkG5BnGoOVZA+EmZbuRPfgCgoQ95
ljvsvj7Ssp+0mXDuCy0/TnU=
=79ni
-----END PGP SIGNATURE-----
--

From: Serge E. Hallyn
Date: Saturday, September 27, 2008 - 6:40 am

Yes, I did do that in a patch on top of all of these.  It increased the
kernel size by 8 (or was it 16) bytes :)  I assume that was because
now there were more references to 'current' which is inlined?  So I
should be able to fix that by saving current() away at the top of
the fn.

Will try that.

thanks,
--

From: Serge E. Hallyn
Date: Monday, September 29, 2008 - 2:53 pm

Here is a patch (on top of the others) doing that.

thanks,
-serge

Subject: [PATCH] capabilities: remove target argument from capset_check and set

Since it is no longer possible to set capabilities on another task,
remove the 'target' option from capset_set and capset_check.

Since the userspace API shouldn't change, we maintain 'pid' as a
valid option to the actual sys_capset(), continuing to return
-EPERM when pid is not current's pid.

Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>

---

 include/linux/security.h |   49 ++++++++++++++++------------------------------
 kernel/capability.c      |    6 ++----
 security/commoncap.c     |   29 +++++++++++++++------------
 security/security.c      |   18 ++++++++---------
 security/selinux/hooks.c |   15 ++++++++------
 5 files changed, 51 insertions(+), 66 deletions(-)

35b1a7906d26fd10da34e5cd350470abb812a91c
diff --git a/include/linux/security.h b/include/linux/security.h
index 80c4d00..7b9f7a2 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -49,8 +49,8 @@ extern int cap_settime(struct timespec *
 extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode);
 extern int cap_ptrace_traceme(struct task_struct *parent);
 extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
-extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
-extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+extern int cap_capset_check(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
+extern void cap_capset_set(kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern int cap_bprm_set_security(struct linux_binprm *bprm);
 extern void cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe);
 extern int ...
From: Andrew G. Morgan
Date: Friday, September 26, 2008 - 9:58 pm

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

Serge,

I have to say I'm a bit confused by this one. Specifically, the
cap_get_target_pid() change. In your 5/6 patch, you say this change
("the previous patch") makes the kernel bigger? Is this because of the
cap_get_target_pid() changes? Since you are fighting to reduce space, if
it bloats the code does the cap_get_target_pid() part of the change make
sense?

Cheers

Andrew

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

iD8DBQFI3b1s+bHCR3gb8jsRAkWCAJ4j5Q5NQc2TD8B+WOYJ1JIqV1GdqQCg1qQU
+qzZPOvwo/W/73BuA+HvuxQ=
=fRje
-----END PGP SIGNATURE-----
--

From: Serge E. Hallyn
Date: Saturday, September 27, 2008 - 6:43 am

Yes I think it does.  Yes my goal was to decrease the kernel size, but
having cleaner code - and getting rid of dead codepaths - is more
important.

It may be hard to tell by looking at the patch, but I think the
end-result is really far better.

thanks,
-serge
--

From: Andrew G. Morgan
Date: Friday, September 26, 2008 - 9:26 pm

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




Acked-by: Andrew G. Morgan <morgan@kernel.org>

Cheers

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

iD8DBQFI3bX0+bHCR3gb8jsRApVqAKCuFmvJTlIiAYxXW5W3JNncFYmmrQCfa95h
Ik/MLVnpPtZdmuInkJSOof4=
=3aYe
-----END PGP SIGNATURE-----
--

From: James Morris
Date: Friday, September 26, 2008 - 10:27 pm

This one makes sense on its own, applied to:
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6#next


- James
-- 
James Morris
<jmorris@namei.org>
--

Previous thread: [PATCH 1/6] file capabilities: add no_file_caps switch (v3) by Serge E. Hallyn on Friday, September 26, 2008 - 7:27 pm. (4 messages)

Next thread: inconsistent lock state. (kvm) by Dave Jones on Friday, September 26, 2008 - 7:30 pm. (2 messages)