diff options
author | Andrew Morgan <morgan@kernel.org> | 2008-02-05 01:29:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-05 12:44:20 -0500 |
commit | e338d263a76af78fe8f38a72131188b58fceb591 (patch) | |
tree | f3f046fc6fd66de43de7191830f0daf3bc4ec8eb /fs | |
parent | 8f6936f4d29aa14e54a2470b954a2e1f96322988 (diff) |
Add 64-bit capability support to the kernel
The patch supports legacy (32-bit) capability userspace, and where possible
translates 32-bit capabilities to/from userspace and the VFS to 64-bit
kernel space capabilities. If a capability set cannot be compressed into
32-bits for consumption by user space, the system call fails, with -ERANGE.
FWIW libcap-2.00 supports this change (and earlier capability formats)
http://www.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
[akpm@linux-foundation.org: coding-syle fixes]
[akpm@linux-foundation.org: use get_task_comm()]
[ezk@cs.sunysb.edu: build fix]
[akpm@linux-foundation.org: do not initialise statics to 0 or NULL]
[akpm@linux-foundation.org: unused var]
[serue@us.ibm.com: export __cap_ symbols]
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/auth.c | 10 | ||||
-rw-r--r-- | fs/proc/array.c | 21 |
2 files changed, 20 insertions, 11 deletions
diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c index 21928056e35e..d13403e33622 100644 --- a/fs/nfsd/auth.c +++ b/fs/nfsd/auth.c | |||
@@ -11,8 +11,6 @@ | |||
11 | #include <linux/nfsd/nfsd.h> | 11 | #include <linux/nfsd/nfsd.h> |
12 | #include <linux/nfsd/export.h> | 12 | #include <linux/nfsd/export.h> |
13 | 13 | ||
14 | #define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE)) | ||
15 | |||
16 | int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) | 14 | int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) |
17 | { | 15 | { |
18 | struct exp_flavor_info *f; | 16 | struct exp_flavor_info *f; |
@@ -69,10 +67,12 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp) | |||
69 | ret = set_current_groups(cred.cr_group_info); | 67 | ret = set_current_groups(cred.cr_group_info); |
70 | put_group_info(cred.cr_group_info); | 68 | put_group_info(cred.cr_group_info); |
71 | if ((cred.cr_uid)) { | 69 | if ((cred.cr_uid)) { |
72 | cap_t(current->cap_effective) &= ~CAP_NFSD_MASK; | 70 | current->cap_effective = |
71 | cap_drop_nfsd_set(current->cap_effective); | ||
73 | } else { | 72 | } else { |
74 | cap_t(current->cap_effective) |= (CAP_NFSD_MASK & | 73 | current->cap_effective = |
75 | current->cap_permitted); | 74 | cap_raise_nfsd_set(current->cap_effective, |
75 | current->cap_permitted); | ||
76 | } | 76 | } |
77 | return ret; | 77 | return ret; |
78 | } | 78 | } |
diff --git a/fs/proc/array.c b/fs/proc/array.c index b380313092bd..6ba2746e4517 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -281,14 +281,23 @@ static inline char *task_sig(struct task_struct *p, char *buffer) | |||
281 | return buffer; | 281 | return buffer; |
282 | } | 282 | } |
283 | 283 | ||
284 | static char *render_cap_t(const char *header, kernel_cap_t *a, char *buffer) | ||
285 | { | ||
286 | unsigned __capi; | ||
287 | |||
288 | buffer += sprintf(buffer, "%s", header); | ||
289 | CAP_FOR_EACH_U32(__capi) { | ||
290 | buffer += sprintf(buffer, "%08x", | ||
291 | a->cap[(_LINUX_CAPABILITY_U32S-1) - __capi]); | ||
292 | } | ||
293 | return buffer + sprintf(buffer, "\n"); | ||
294 | } | ||
295 | |||
284 | static inline char *task_cap(struct task_struct *p, char *buffer) | 296 | static inline char *task_cap(struct task_struct *p, char *buffer) |
285 | { | 297 | { |
286 | return buffer + sprintf(buffer, "CapInh:\t%016x\n" | 298 | buffer = render_cap_t("CapInh:\t", &p->cap_inheritable, buffer); |
287 | "CapPrm:\t%016x\n" | 299 | buffer = render_cap_t("CapPrm:\t", &p->cap_permitted, buffer); |
288 | "CapEff:\t%016x\n", | 300 | return render_cap_t("CapEff:\t", &p->cap_effective, buffer); |
289 | cap_t(p->cap_inheritable), | ||
290 | cap_t(p->cap_permitted), | ||
291 | cap_t(p->cap_effective)); | ||
292 | } | 301 | } |
293 | 302 | ||
294 | static inline char *task_context_switch_counts(struct task_struct *p, | 303 | static inline char *task_context_switch_counts(struct task_struct *p, |