aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Morgan <morgan@kernel.org>2008-02-05 01:29:42 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:20 -0500
commite338d263a76af78fe8f38a72131188b58fceb591 (patch)
treef3f046fc6fd66de43de7191830f0daf3bc4ec8eb
parent8f6936f4d29aa14e54a2470b954a2e1f96322988 (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>
-rw-r--r--fs/nfsd/auth.c10
-rw-r--r--fs/proc/array.c21
-rw-r--r--include/linux/capability.h221
-rw-r--r--kernel/capability.c113
-rw-r--r--mm/oom_kill.c5
-rw-r--r--security/commoncap.c87
-rw-r--r--security/dummy.c17
7 files changed, 349 insertions, 125 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
16int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp) 14int 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
284static 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
284static inline char *task_cap(struct task_struct *p, char *buffer) 296static 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
294static inline char *task_context_switch_counts(struct task_struct *p, 303static inline char *task_context_switch_counts(struct task_struct *p,
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 7a8d7ade28a0..a934dac672dd 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -23,13 +23,20 @@ struct task_struct;
23 kernel might be somewhat backwards compatible, but don't bet on 23 kernel might be somewhat backwards compatible, but don't bet on
24 it. */ 24 it. */
25 25
26/* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to 26/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to
27 a set of three capability sets. The transposition of 3*the 27 a set of three capability sets. The transposition of 3*the
28 following structure to such a composite is better handled in a user 28 following structure to such a composite is better handled in a user
29 library since the draft standard requires the use of malloc/free 29 library since the draft standard requires the use of malloc/free
30 etc.. */ 30 etc.. */
31 31
32#define _LINUX_CAPABILITY_VERSION 0x19980330 32#define _LINUX_CAPABILITY_VERSION_1 0x19980330
33#define _LINUX_CAPABILITY_U32S_1 1
34
35#define _LINUX_CAPABILITY_VERSION_2 0x20071026
36#define _LINUX_CAPABILITY_U32S_2 2
37
38#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2
39#define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2
33 40
34typedef struct __user_cap_header_struct { 41typedef struct __user_cap_header_struct {
35 __u32 version; 42 __u32 version;
@@ -42,43 +49,42 @@ typedef struct __user_cap_data_struct {
42 __u32 inheritable; 49 __u32 inheritable;
43} __user *cap_user_data_t; 50} __user *cap_user_data_t;
44 51
52
45#define XATTR_CAPS_SUFFIX "capability" 53#define XATTR_CAPS_SUFFIX "capability"
46#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX 54#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
47 55
48#define XATTR_CAPS_SZ (3*sizeof(__le32))
49#define VFS_CAP_REVISION_MASK 0xFF000000 56#define VFS_CAP_REVISION_MASK 0xFF000000
57#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
58#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
59
50#define VFS_CAP_REVISION_1 0x01000000 60#define VFS_CAP_REVISION_1 0x01000000
61#define VFS_CAP_U32_1 1
62#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
51 63
52#define VFS_CAP_REVISION VFS_CAP_REVISION_1 64#define VFS_CAP_REVISION_2 0x02000000
65#define VFS_CAP_U32_2 2
66#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
67
68#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
69#define VFS_CAP_U32 VFS_CAP_U32_2
70#define VFS_CAP_REVISION VFS_CAP_REVISION_2
53 71
54#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
55#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
56 72
57struct vfs_cap_data { 73struct vfs_cap_data {
58 __u32 magic_etc; /* Little endian */ 74 __le32 magic_etc; /* Little endian */
59 struct { 75 struct {
60 __u32 permitted; /* Little endian */ 76 __le32 permitted; /* Little endian */
61 __u32 inheritable; /* Little endian */ 77 __le32 inheritable; /* Little endian */
62 } data[1]; 78 } data[VFS_CAP_U32];
63}; 79};
64 80
65#ifdef __KERNEL__ 81#ifdef __KERNEL__
66 82
67/* #define STRICT_CAP_T_TYPECHECKS */
68
69#ifdef STRICT_CAP_T_TYPECHECKS
70
71typedef struct kernel_cap_struct { 83typedef struct kernel_cap_struct {
72 __u32 cap; 84 __u32 cap[_LINUX_CAPABILITY_U32S];
73} kernel_cap_t; 85} kernel_cap_t;
74 86
75#else 87#define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct))
76
77typedef __u32 kernel_cap_t;
78
79#endif
80
81#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
82#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) 88#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
83 89
84#endif 90#endif
@@ -121,10 +127,6 @@ typedef __u32 kernel_cap_t;
121 127
122#define CAP_FSETID 4 128#define CAP_FSETID 4
123 129
124/* Used to decide between falling back on the old suser() or fsuser(). */
125
126#define CAP_FS_MASK 0x1f
127
128/* Overrides the restriction that the real or effective user ID of a 130/* Overrides the restriction that the real or effective user ID of a
129 process sending a signal must match the real or effective user ID 131 process sending a signal must match the real or effective user ID
130 of the process receiving the signal. */ 132 of the process receiving the signal. */
@@ -147,8 +149,12 @@ typedef __u32 kernel_cap_t;
147 ** Linux-specific capabilities 149 ** Linux-specific capabilities
148 **/ 150 **/
149 151
150/* Transfer any capability in your permitted set to any pid, 152/* Without VFS support for capabilities:
151 remove any capability in your permitted set from any pid */ 153 * Transfer any capability in your permitted set to any pid,
154 * remove any capability in your permitted set from any pid
155 * With VFS support for capabilities (neither of above, but)
156 * Add any capability to the current process' inheritable set
157 */
152 158
153#define CAP_SETPCAP 8 159#define CAP_SETPCAP 8
154 160
@@ -309,70 +315,153 @@ typedef __u32 kernel_cap_t;
309 315
310#define CAP_SETFCAP 31 316#define CAP_SETFCAP 31
311 317
318/*
319 * Bit location of each capability (used by user-space library and kernel)
320 */
321
322#define CAP_TO_INDEX(x) ((x) >> 5) /* 1 << 5 == bits in __u32 */
323#define CAP_TO_MASK(x) (1 << ((x) & 31)) /* mask for indexed __u32 */
324
312#ifdef __KERNEL__ 325#ifdef __KERNEL__
313 326
314/* 327/*
315 * Internal kernel functions only 328 * Internal kernel functions only
316 */ 329 */
317 330
318#ifdef STRICT_CAP_T_TYPECHECKS 331#define CAP_FOR_EACH_U32(__capi) \
332 for (__capi = 0; __capi < _LINUX_CAPABILITY_U32S; ++__capi)
333
334# define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \
335 | CAP_TO_MASK(CAP_DAC_OVERRIDE) \
336 | CAP_TO_MASK(CAP_DAC_READ_SEARCH) \
337 | CAP_TO_MASK(CAP_FOWNER) \
338 | CAP_TO_MASK(CAP_FSETID))
339
340#if _LINUX_CAPABILITY_U32S != 2
341# error Fix up hand-coded capability macro initializers
342#else /* HAND-CODED capability initializers */
343
344# define CAP_EMPTY_SET {{ 0, 0 }}
345# define CAP_FULL_SET {{ ~0, ~0 }}
346# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}
347# define CAP_FS_SET {{ CAP_FS_MASK_B0, 0 }}
348# define CAP_NFSD_SET {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), 0 }}
349
350#endif /* _LINUX_CAPABILITY_U32S != 2 */
351
352#define CAP_INIT_INH_SET CAP_EMPTY_SET
353
354# define cap_clear(c) do { (c) = __cap_empty_set; } while (0)
355# define cap_set_full(c) do { (c) = __cap_full_set; } while (0)
356# define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0)
357
358#define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
359#define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
360#define cap_raised(c, flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag))
361
362#define CAP_BOP_ALL(c, a, b, OP) \
363do { \
364 unsigned __capi; \
365 CAP_FOR_EACH_U32(__capi) { \
366 c.cap[__capi] = a.cap[__capi] OP b.cap[__capi]; \
367 } \
368} while (0)
369
370#define CAP_UOP_ALL(c, a, OP) \
371do { \
372 unsigned __capi; \
373 CAP_FOR_EACH_U32(__capi) { \
374 c.cap[__capi] = OP a.cap[__capi]; \
375 } \
376} while (0)
377
378static inline kernel_cap_t cap_combine(const kernel_cap_t a,
379 const kernel_cap_t b)
380{
381 kernel_cap_t dest;
382 CAP_BOP_ALL(dest, a, b, |);
383 return dest;
384}
319 385
320#define to_cap_t(x) { x } 386static inline kernel_cap_t cap_intersect(const kernel_cap_t a,
321#define cap_t(x) (x).cap 387 const kernel_cap_t b)
388{
389 kernel_cap_t dest;
390 CAP_BOP_ALL(dest, a, b, &);
391 return dest;
392}
322 393
323#else 394static inline kernel_cap_t cap_drop(const kernel_cap_t a,
395 const kernel_cap_t drop)
396{
397 kernel_cap_t dest;
398 CAP_BOP_ALL(dest, a, drop, &~);
399 return dest;
400}
324 401
325#define to_cap_t(x) (x) 402static inline kernel_cap_t cap_invert(const kernel_cap_t c)
326#define cap_t(x) (x) 403{
404 kernel_cap_t dest;
405 CAP_UOP_ALL(dest, c, ~);
406 return dest;
407}
327 408
328#endif 409static inline int cap_isclear(const kernel_cap_t a)
410{
411 unsigned __capi;
412 CAP_FOR_EACH_U32(__capi) {
413 if (a.cap[__capi] != 0)
414 return 0;
415 }
416 return 1;
417}
329 418
330#define CAP_EMPTY_SET to_cap_t(0) 419static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set)
331#define CAP_FULL_SET to_cap_t(~0) 420{
332#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP)) 421 kernel_cap_t dest;
333#define CAP_INIT_INH_SET to_cap_t(0) 422 dest = cap_drop(a, set);
423 return cap_isclear(dest);
424}
334 425
335#define CAP_TO_MASK(x) (1 << (x)) 426/* Used to decide between falling back on the old suser() or fsuser(). */
336#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag))
337#define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag))
338#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag))
339 427
340static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b) 428static inline int cap_is_fs_cap(int cap)
341{ 429{
342 kernel_cap_t dest; 430 const kernel_cap_t __cap_fs_set = CAP_FS_SET;
343 cap_t(dest) = cap_t(a) | cap_t(b); 431 return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]);
344 return dest;
345} 432}
346 433
347static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b) 434static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a)
348{ 435{
349 kernel_cap_t dest; 436 const kernel_cap_t __cap_fs_set = CAP_FS_SET;
350 cap_t(dest) = cap_t(a) & cap_t(b); 437 return cap_drop(a, __cap_fs_set);
351 return dest;
352} 438}
353 439
354static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop) 440static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a,
441 const kernel_cap_t permitted)
355{ 442{
356 kernel_cap_t dest; 443 const kernel_cap_t __cap_fs_set = CAP_FS_SET;
357 cap_t(dest) = cap_t(a) & ~cap_t(drop); 444 return cap_combine(a,
358 return dest; 445 cap_intersect(permitted, __cap_fs_set));
359} 446}
360 447
361static inline kernel_cap_t cap_invert(kernel_cap_t c) 448static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a)
362{ 449{
363 kernel_cap_t dest; 450 const kernel_cap_t __cap_fs_set = CAP_NFSD_SET;
364 cap_t(dest) = ~cap_t(c); 451 return cap_drop(a, __cap_fs_set);
365 return dest;
366} 452}
367 453
368#define cap_isclear(c) (!cap_t(c)) 454static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a,
369#define cap_issubset(a,set) (!(cap_t(a) & ~cap_t(set))) 455 const kernel_cap_t permitted)
370 456{
371#define cap_clear(c) do { cap_t(c) = 0; } while(0) 457 const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET;
372#define cap_set_full(c) do { cap_t(c) = ~0; } while(0) 458 return cap_combine(a,
373#define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0) 459 cap_intersect(permitted, __cap_nfsd_set));
460}
374 461
375#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK) 462extern const kernel_cap_t __cap_empty_set;
463extern const kernel_cap_t __cap_full_set;
464extern const kernel_cap_t __cap_init_eff_set;
376 465
377int capable(int cap); 466int capable(int cap);
378int __capable(struct task_struct *t, int cap); 467int __capable(struct task_struct *t, int cap);
diff --git a/kernel/capability.c b/kernel/capability.c
index efbd9cdce132..39e8193b41ea 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -22,6 +22,37 @@
22static DEFINE_SPINLOCK(task_capability_lock); 22static DEFINE_SPINLOCK(task_capability_lock);
23 23
24/* 24/*
25 * Leveraged for setting/resetting capabilities
26 */
27
28const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
29const kernel_cap_t __cap_full_set = CAP_FULL_SET;
30const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
31
32EXPORT_SYMBOL(__cap_empty_set);
33EXPORT_SYMBOL(__cap_full_set);
34EXPORT_SYMBOL(__cap_init_eff_set);
35
36/*
37 * More recent versions of libcap are available from:
38 *
39 * http://www.kernel.org/pub/linux/libs/security/linux-privs/
40 */
41
42static void warn_legacy_capability_use(void)
43{
44 static int warned;
45 if (!warned) {
46 char name[sizeof(current->comm)];
47
48 printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
49 " (legacy support in use)\n",
50 get_task_comm(name, current));
51 warned = 1;
52 }
53}
54
55/*
25 * For sys_getproccap() and sys_setproccap(), any of the three 56 * For sys_getproccap() and sys_setproccap(), any of the three
26 * capability set pointers may be NULL -- indicating that that set is 57 * capability set pointers may be NULL -- indicating that that set is
27 * uninteresting and/or not to be changed. 58 * uninteresting and/or not to be changed.
@@ -42,12 +73,21 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
42 pid_t pid; 73 pid_t pid;
43 __u32 version; 74 __u32 version;
44 struct task_struct *target; 75 struct task_struct *target;
45 struct __user_cap_data_struct data; 76 unsigned tocopy;
77 kernel_cap_t pE, pI, pP;
46 78
47 if (get_user(version, &header->version)) 79 if (get_user(version, &header->version))
48 return -EFAULT; 80 return -EFAULT;
49 81
50 if (version != _LINUX_CAPABILITY_VERSION) { 82 switch (version) {
83 case _LINUX_CAPABILITY_VERSION_1:
84 warn_legacy_capability_use();
85 tocopy = _LINUX_CAPABILITY_U32S_1;
86 break;
87 case _LINUX_CAPABILITY_VERSION_2:
88 tocopy = _LINUX_CAPABILITY_U32S_2;
89 break;
90 default:
51 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) 91 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
52 return -EFAULT; 92 return -EFAULT;
53 return -EINVAL; 93 return -EINVAL;
@@ -71,14 +111,47 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
71 } else 111 } else
72 target = current; 112 target = current;
73 113
74 ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted); 114 ret = security_capget(target, &pE, &pI, &pP);
75 115
76out: 116out:
77 read_unlock(&tasklist_lock); 117 read_unlock(&tasklist_lock);
78 spin_unlock(&task_capability_lock); 118 spin_unlock(&task_capability_lock);
79 119
80 if (!ret && copy_to_user(dataptr, &data, sizeof data)) 120 if (!ret) {
81 return -EFAULT; 121 struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
122 unsigned i;
123
124 for (i = 0; i < tocopy; i++) {
125 kdata[i].effective = pE.cap[i];
126 kdata[i].permitted = pP.cap[i];
127 kdata[i].inheritable = pI.cap[i];
128 }
129
130 /*
131 * Note, in the case, tocopy < _LINUX_CAPABILITY_U32S,
132 * we silently drop the upper capabilities here. This
133 * has the effect of making older libcap
134 * implementations implicitly drop upper capability
135 * bits when they perform a: capget/modify/capset
136 * sequence.
137 *
138 * This behavior is considered fail-safe
139 * behavior. Upgrading the application to a newer
140 * version of libcap will enable access to the newer
141 * capabilities.
142 *
143 * An alternative would be to return an error here
144 * (-ERANGE), but that causes legacy applications to
145 * unexpectidly fail; the capget/modify/capset aborts
146 * before modification is attempted and the application
147 * fails.
148 */
149
150 if (copy_to_user(dataptr, kdata, tocopy
151 * sizeof(struct __user_cap_data_struct))) {
152 return -EFAULT;
153 }
154 }
82 155
83 return ret; 156 return ret;
84} 157}
@@ -167,6 +240,8 @@ static inline int cap_set_all(kernel_cap_t *effective,
167 */ 240 */
168asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) 241asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
169{ 242{
243 struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
244 unsigned i, tocopy;
170 kernel_cap_t inheritable, permitted, effective; 245 kernel_cap_t inheritable, permitted, effective;
171 __u32 version; 246 __u32 version;
172 struct task_struct *target; 247 struct task_struct *target;
@@ -176,7 +251,15 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
176 if (get_user(version, &header->version)) 251 if (get_user(version, &header->version))
177 return -EFAULT; 252 return -EFAULT;
178 253
179 if (version != _LINUX_CAPABILITY_VERSION) { 254 switch (version) {
255 case _LINUX_CAPABILITY_VERSION_1:
256 warn_legacy_capability_use();
257 tocopy = _LINUX_CAPABILITY_U32S_1;
258 break;
259 case _LINUX_CAPABILITY_VERSION_2:
260 tocopy = _LINUX_CAPABILITY_U32S_2;
261 break;
262 default:
180 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) 263 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
181 return -EFAULT; 264 return -EFAULT;
182 return -EINVAL; 265 return -EINVAL;
@@ -188,10 +271,22 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
188 if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP)) 271 if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
189 return -EPERM; 272 return -EPERM;
190 273
191 if (copy_from_user(&effective, &data->effective, sizeof(effective)) || 274 if (copy_from_user(&kdata, data, tocopy
192 copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || 275 * sizeof(struct __user_cap_data_struct))) {
193 copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
194 return -EFAULT; 276 return -EFAULT;
277 }
278
279 for (i = 0; i < tocopy; i++) {
280 effective.cap[i] = kdata[i].effective;
281 permitted.cap[i] = kdata[i].permitted;
282 inheritable.cap[i] = kdata[i].inheritable;
283 }
284 while (i < _LINUX_CAPABILITY_U32S) {
285 effective.cap[i] = 0;
286 permitted.cap[i] = 0;
287 inheritable.cap[i] = 0;
288 i++;
289 }
195 290
196 spin_lock(&task_capability_lock); 291 spin_lock(&task_capability_lock);
197 read_lock(&tasklist_lock); 292 read_lock(&tasklist_lock);
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 96473b482099..320d74e707af 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -125,8 +125,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
125 * Superuser processes are usually more important, so we make it 125 * Superuser processes are usually more important, so we make it
126 * less likely that we kill those. 126 * less likely that we kill those.
127 */ 127 */
128 if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) || 128 if (__capable(p, CAP_SYS_ADMIN) || p->uid == 0 || p->euid == 0)
129 p->uid == 0 || p->euid == 0)
130 points /= 4; 129 points /= 4;
131 130
132 /* 131 /*
@@ -135,7 +134,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
135 * tend to only have this flag set on applications they think 134 * tend to only have this flag set on applications they think
136 * of as important. 135 * of as important.
137 */ 136 */
138 if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) 137 if (__capable(p, CAP_SYS_RAWIO))
139 points /= 4; 138 points /= 4;
140 139
141 /* 140 /*
diff --git a/security/commoncap.c b/security/commoncap.c
index b06617b35b93..01ab47845dcf 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -1,4 +1,4 @@
1/* Common capabilities, needed by capability.o and root_plug.o 1/* Common capabilities, needed by capability.o and root_plug.o
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by 4 * it under the terms of the GNU General Public License as published by
@@ -93,9 +93,9 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective,
93 kernel_cap_t *inheritable, kernel_cap_t *permitted) 93 kernel_cap_t *inheritable, kernel_cap_t *permitted)
94{ 94{
95 /* Derived from kernel/capability.c:sys_capget. */ 95 /* Derived from kernel/capability.c:sys_capget. */
96 *effective = cap_t (target->cap_effective); 96 *effective = target->cap_effective;
97 *inheritable = cap_t (target->cap_inheritable); 97 *inheritable = target->cap_inheritable;
98 *permitted = cap_t (target->cap_permitted); 98 *permitted = target->cap_permitted;
99 return 0; 99 return 0;
100} 100}
101 101
@@ -197,28 +197,51 @@ int cap_inode_killpriv(struct dentry *dentry)
197 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS); 197 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
198} 198}
199 199
200static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, 200static inline int cap_from_disk(struct vfs_cap_data *caps,
201 int size) 201 struct linux_binprm *bprm, unsigned size)
202{ 202{
203 __u32 magic_etc; 203 __u32 magic_etc;
204 unsigned tocopy, i;
204 205
205 if (size != XATTR_CAPS_SZ) 206 if (size < sizeof(magic_etc))
206 return -EINVAL; 207 return -EINVAL;
207 208
208 magic_etc = le32_to_cpu(caps[0]); 209 magic_etc = le32_to_cpu(caps->magic_etc);
209 210
210 switch ((magic_etc & VFS_CAP_REVISION_MASK)) { 211 switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
211 case VFS_CAP_REVISION: 212 case VFS_CAP_REVISION_1:
212 if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) 213 if (size != XATTR_CAPS_SZ_1)
213 bprm->cap_effective = true; 214 return -EINVAL;
214 else 215 tocopy = VFS_CAP_U32_1;
215 bprm->cap_effective = false; 216 break;
216 bprm->cap_permitted = to_cap_t(le32_to_cpu(caps[1])); 217 case VFS_CAP_REVISION_2:
217 bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps[2])); 218 if (size != XATTR_CAPS_SZ_2)
218 return 0; 219 return -EINVAL;
220 tocopy = VFS_CAP_U32_2;
221 break;
219 default: 222 default:
220 return -EINVAL; 223 return -EINVAL;
221 } 224 }
225
226 if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
227 bprm->cap_effective = true;
228 } else {
229 bprm->cap_effective = false;
230 }
231
232 for (i = 0; i < tocopy; ++i) {
233 bprm->cap_permitted.cap[i] =
234 le32_to_cpu(caps->data[i].permitted);
235 bprm->cap_inheritable.cap[i] =
236 le32_to_cpu(caps->data[i].inheritable);
237 }
238 while (i < VFS_CAP_U32) {
239 bprm->cap_permitted.cap[i] = 0;
240 bprm->cap_inheritable.cap[i] = 0;
241 i++;
242 }
243
244 return 0;
222} 245}
223 246
224/* Locate any VFS capabilities: */ 247/* Locate any VFS capabilities: */
@@ -226,7 +249,7 @@ static int get_file_caps(struct linux_binprm *bprm)
226{ 249{
227 struct dentry *dentry; 250 struct dentry *dentry;
228 int rc = 0; 251 int rc = 0;
229 __le32 v1caps[XATTR_CAPS_SZ]; 252 struct vfs_cap_data vcaps;
230 struct inode *inode; 253 struct inode *inode;
231 254
232 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { 255 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
@@ -239,8 +262,8 @@ static int get_file_caps(struct linux_binprm *bprm)
239 if (!inode->i_op || !inode->i_op->getxattr) 262 if (!inode->i_op || !inode->i_op->getxattr)
240 goto out; 263 goto out;
241 264
242 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps, 265 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps,
243 XATTR_CAPS_SZ); 266 XATTR_CAPS_SZ);
244 if (rc == -ENODATA || rc == -EOPNOTSUPP) { 267 if (rc == -ENODATA || rc == -EOPNOTSUPP) {
245 /* no data, that's ok */ 268 /* no data, that's ok */
246 rc = 0; 269 rc = 0;
@@ -249,7 +272,7 @@ static int get_file_caps(struct linux_binprm *bprm)
249 if (rc < 0) 272 if (rc < 0)
250 goto out; 273 goto out;
251 274
252 rc = cap_from_disk(v1caps, bprm, rc); 275 rc = cap_from_disk(&vcaps, bprm, rc);
253 if (rc) 276 if (rc)
254 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", 277 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
255 __FUNCTION__, rc, bprm->filename); 278 __FUNCTION__, rc, bprm->filename);
@@ -344,8 +367,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
344 * capability rules */ 367 * capability rules */
345 if (!is_global_init(current)) { 368 if (!is_global_init(current)) {
346 current->cap_permitted = new_permitted; 369 current->cap_permitted = new_permitted;
347 current->cap_effective = bprm->cap_effective ? 370 if (bprm->cap_effective)
348 new_permitted : 0; 371 current->cap_effective = new_permitted;
372 else
373 cap_clear(current->cap_effective);
349 } 374 }
350 375
351 /* AUD: Audit candidate if current->cap_effective is set */ 376 /* AUD: Audit candidate if current->cap_effective is set */
@@ -467,13 +492,15 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
467 492
468 if (!issecure (SECURE_NO_SETUID_FIXUP)) { 493 if (!issecure (SECURE_NO_SETUID_FIXUP)) {
469 if (old_fsuid == 0 && current->fsuid != 0) { 494 if (old_fsuid == 0 && current->fsuid != 0) {
470 cap_t (current->cap_effective) &= 495 current->cap_effective =
471 ~CAP_FS_MASK; 496 cap_drop_fs_set(
497 current->cap_effective);
472 } 498 }
473 if (old_fsuid != 0 && current->fsuid == 0) { 499 if (old_fsuid != 0 && current->fsuid == 0) {
474 cap_t (current->cap_effective) |= 500 current->cap_effective =
475 (cap_t (current->cap_permitted) & 501 cap_raise_fs_set(
476 CAP_FS_MASK); 502 current->cap_effective,
503 current->cap_permitted);
477 } 504 }
478 } 505 }
479 break; 506 break;
@@ -577,9 +604,9 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
577 604
578void cap_task_reparent_to_init (struct task_struct *p) 605void cap_task_reparent_to_init (struct task_struct *p)
579{ 606{
580 p->cap_effective = CAP_INIT_EFF_SET; 607 cap_set_init_eff(p->cap_effective);
581 p->cap_inheritable = CAP_INIT_INH_SET; 608 cap_clear(p->cap_inheritable);
582 p->cap_permitted = CAP_FULL_SET; 609 cap_set_full(p->cap_permitted);
583 p->keep_capabilities = 0; 610 p->keep_capabilities = 0;
584 return; 611 return;
585} 612}
diff --git a/security/dummy.c b/security/dummy.c
index c505122e22db..649326bf64ea 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -36,14 +36,19 @@ static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
36static int dummy_capget (struct task_struct *target, kernel_cap_t * effective, 36static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
37 kernel_cap_t * inheritable, kernel_cap_t * permitted) 37 kernel_cap_t * inheritable, kernel_cap_t * permitted)
38{ 38{
39 *effective = *inheritable = *permitted = 0;
40 if (target->euid == 0) { 39 if (target->euid == 0) {
41 *permitted |= (~0 & ~CAP_FS_MASK); 40 cap_set_full(*permitted);
42 *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK); 41 cap_set_init_eff(*effective);
42 } else {
43 cap_clear(*permitted);
44 cap_clear(*effective);
43 } 45 }
44 if (target->fsuid == 0) { 46
45 *permitted |= CAP_FS_MASK; 47 cap_clear(*inheritable);
46 *effective |= CAP_FS_MASK; 48
49 if (target->fsuid != 0) {
50 *permitted = cap_drop_fs_set(*permitted);
51 *effective = cap_drop_fs_set(*effective);
47 } 52 }
48 return 0; 53 return 0;
49} 54}