Commit e338d263a76af78fe8f38a72131188b58fceb591

Authored by Andrew Morgan
Committed by Linus Torvalds
1 parent 8f6936f4d2

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>

Showing 7 changed files with 349 additions and 125 deletions Side-by-side Diff

... ... @@ -11,8 +11,6 @@
11 11 #include <linux/nfsd/nfsd.h>
12 12 #include <linux/nfsd/export.h>
13 13  
14   -#define CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
15   -
16 14 int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
17 15 {
18 16 struct exp_flavor_info *f;
19 17  
... ... @@ -69,10 +67,12 @@
69 67 ret = set_current_groups(cred.cr_group_info);
70 68 put_group_info(cred.cr_group_info);
71 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 72 } else {
74   - cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
75   - current->cap_permitted);
  73 + current->cap_effective =
  74 + cap_raise_nfsd_set(current->cap_effective,
  75 + current->cap_permitted);
76 76 }
77 77 return ret;
78 78 }
... ... @@ -281,14 +281,23 @@
281 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 296 static inline char *task_cap(struct task_struct *p, char *buffer)
285 297 {
286   - return buffer + sprintf(buffer, "CapInh:\t%016x\n"
287   - "CapPrm:\t%016x\n"
288   - "CapEff:\t%016x\n",
289   - cap_t(p->cap_inheritable),
290   - cap_t(p->cap_permitted),
291   - cap_t(p->cap_effective));
  298 + buffer = render_cap_t("CapInh:\t", &p->cap_inheritable, buffer);
  299 + buffer = render_cap_t("CapPrm:\t", &p->cap_permitted, buffer);
  300 + return render_cap_t("CapEff:\t", &p->cap_effective, buffer);
292 301 }
293 302  
294 303 static inline char *task_context_switch_counts(struct task_struct *p,
include/linux/capability.h
... ... @@ -23,14 +23,21 @@
23 23 kernel might be somewhat backwards compatible, but don't bet on
24 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 27 a set of three capability sets. The transposition of 3*the
28 28 following structure to such a composite is better handled in a user
29 29 library since the draft standard requires the use of malloc/free
30 30 etc.. */
31 31  
32   -#define _LINUX_CAPABILITY_VERSION 0x19980330
  32 +#define _LINUX_CAPABILITY_VERSION_1 0x19980330
  33 +#define _LINUX_CAPABILITY_U32S_1 1
33 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
  40 +
34 41 typedef struct __user_cap_header_struct {
35 42 __u32 version;
36 43 int pid;
37 44  
38 45  
39 46  
40 47  
41 48  
42 49  
43 50  
44 51  
45 52  
46 53  
47 54  
... ... @@ -42,43 +49,42 @@
42 49 __u32 inheritable;
43 50 } __user *cap_user_data_t;
44 51  
  52 +
45 53 #define XATTR_CAPS_SUFFIX "capability"
46 54 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
47 55  
48   -#define XATTR_CAPS_SZ (3*sizeof(__le32))
49 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 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))
53 67  
54   -#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
55   -#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
  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
56 71  
  72 +
57 73 struct vfs_cap_data {
58   - __u32 magic_etc; /* Little endian */
  74 + __le32 magic_etc; /* Little endian */
59 75 struct {
60   - __u32 permitted; /* Little endian */
61   - __u32 inheritable; /* Little endian */
62   - } data[1];
  76 + __le32 permitted; /* Little endian */
  77 + __le32 inheritable; /* Little endian */
  78 + } data[VFS_CAP_U32];
63 79 };
64 80  
65 81 #ifdef __KERNEL__
66 82  
67   -/* #define STRICT_CAP_T_TYPECHECKS */
68   -
69   -#ifdef STRICT_CAP_T_TYPECHECKS
70   -
71 83 typedef struct kernel_cap_struct {
72   - __u32 cap;
  84 + __u32 cap[_LINUX_CAPABILITY_U32S];
73 85 } kernel_cap_t;
74 86  
75   -#else
76   -
77   -typedef __u32 kernel_cap_t;
78   -
79   -#endif
80   -
81   -#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
  87 +#define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct))
82 88 #define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
83 89  
84 90 #endif
... ... @@ -121,10 +127,6 @@
121 127  
122 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 130 /* Overrides the restriction that the real or effective user ID of a
129 131 process sending a signal must match the real or effective user ID
130 132 of the process receiving the signal. */
... ... @@ -147,8 +149,12 @@
147 149 ** Linux-specific capabilities
148 150 **/
149 151  
150   -/* Transfer any capability in your permitted set to any pid,
151   - remove any capability in your permitted set from any pid */
  152 +/* Without VFS support for capabilities:
  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 159 #define CAP_SETPCAP 8
154 160  
155 161  
156 162  
157 163  
158 164  
159 165  
160 166  
161 167  
162 168  
163 169  
164 170  
165 171  
166 172  
167 173  
168 174  
169 175  
170 176  
171 177  
172 178  
... ... @@ -309,70 +315,153 @@
309 315  
310 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 325 #ifdef __KERNEL__
313 326  
314 327 /*
315 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)
319 333  
320   -#define to_cap_t(x) { x }
321   -#define cap_t(x) (x).cap
  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))
322 339  
323   -#else
  340 +#if _LINUX_CAPABILITY_U32S != 2
  341 +# error Fix up hand-coded capability macro initializers
  342 +#else /* HAND-CODED capability initializers */
324 343  
325   -#define to_cap_t(x) (x)
326   -#define cap_t(x) (x)
  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 }}
327 349  
328   -#endif
  350 +#endif /* _LINUX_CAPABILITY_U32S != 2 */
329 351  
330   -#define CAP_EMPTY_SET to_cap_t(0)
331   -#define CAP_FULL_SET to_cap_t(~0)
332   -#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
333   -#define CAP_INIT_INH_SET to_cap_t(0)
  352 +#define CAP_INIT_INH_SET CAP_EMPTY_SET
334 353  
335   -#define CAP_TO_MASK(x) (1 << (x))
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))
  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)
339 357  
340   -static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
  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) \
  363 +do { \
  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) \
  371 +do { \
  372 + unsigned __capi; \
  373 + CAP_FOR_EACH_U32(__capi) { \
  374 + c.cap[__capi] = OP a.cap[__capi]; \
  375 + } \
  376 +} while (0)
  377 +
  378 +static inline kernel_cap_t cap_combine(const kernel_cap_t a,
  379 + const kernel_cap_t b)
341 380 {
342   - kernel_cap_t dest;
343   - cap_t(dest) = cap_t(a) | cap_t(b);
344   - return dest;
  381 + kernel_cap_t dest;
  382 + CAP_BOP_ALL(dest, a, b, |);
  383 + return dest;
345 384 }
346 385  
347   -static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
  386 +static inline kernel_cap_t cap_intersect(const kernel_cap_t a,
  387 + const kernel_cap_t b)
348 388 {
349   - kernel_cap_t dest;
350   - cap_t(dest) = cap_t(a) & cap_t(b);
351   - return dest;
  389 + kernel_cap_t dest;
  390 + CAP_BOP_ALL(dest, a, b, &);
  391 + return dest;
352 392 }
353 393  
354   -static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
  394 +static inline kernel_cap_t cap_drop(const kernel_cap_t a,
  395 + const kernel_cap_t drop)
355 396 {
356   - kernel_cap_t dest;
357   - cap_t(dest) = cap_t(a) & ~cap_t(drop);
358   - return dest;
  397 + kernel_cap_t dest;
  398 + CAP_BOP_ALL(dest, a, drop, &~);
  399 + return dest;
359 400 }
360 401  
361   -static inline kernel_cap_t cap_invert(kernel_cap_t c)
  402 +static inline kernel_cap_t cap_invert(const kernel_cap_t c)
362 403 {
363   - kernel_cap_t dest;
364   - cap_t(dest) = ~cap_t(c);
365   - return dest;
  404 + kernel_cap_t dest;
  405 + CAP_UOP_ALL(dest, c, ~);
  406 + return dest;
366 407 }
367 408  
368   -#define cap_isclear(c) (!cap_t(c))
369   -#define cap_issubset(a,set) (!(cap_t(a) & ~cap_t(set)))
  409 +static 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 +}
370 418  
371   -#define cap_clear(c) do { cap_t(c) = 0; } while(0)
372   -#define cap_set_full(c) do { cap_t(c) = ~0; } while(0)
373   -#define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0)
  419 +static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set)
  420 +{
  421 + kernel_cap_t dest;
  422 + dest = cap_drop(a, set);
  423 + return cap_isclear(dest);
  424 +}
374 425  
375   -#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
  426 +/* Used to decide between falling back on the old suser() or fsuser(). */
  427 +
  428 +static inline int cap_is_fs_cap(int cap)
  429 +{
  430 + const kernel_cap_t __cap_fs_set = CAP_FS_SET;
  431 + return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]);
  432 +}
  433 +
  434 +static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a)
  435 +{
  436 + const kernel_cap_t __cap_fs_set = CAP_FS_SET;
  437 + return cap_drop(a, __cap_fs_set);
  438 +}
  439 +
  440 +static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a,
  441 + const kernel_cap_t permitted)
  442 +{
  443 + const kernel_cap_t __cap_fs_set = CAP_FS_SET;
  444 + return cap_combine(a,
  445 + cap_intersect(permitted, __cap_fs_set));
  446 +}
  447 +
  448 +static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a)
  449 +{
  450 + const kernel_cap_t __cap_fs_set = CAP_NFSD_SET;
  451 + return cap_drop(a, __cap_fs_set);
  452 +}
  453 +
  454 +static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a,
  455 + const kernel_cap_t permitted)
  456 +{
  457 + const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET;
  458 + return cap_combine(a,
  459 + cap_intersect(permitted, __cap_nfsd_set));
  460 +}
  461 +
  462 +extern const kernel_cap_t __cap_empty_set;
  463 +extern const kernel_cap_t __cap_full_set;
  464 +extern const kernel_cap_t __cap_init_eff_set;
376 465  
377 466 int capable(int cap);
378 467 int __capable(struct task_struct *t, int cap);
... ... @@ -22,6 +22,37 @@
22 22 static DEFINE_SPINLOCK(task_capability_lock);
23 23  
24 24 /*
  25 + * Leveraged for setting/resetting capabilities
  26 + */
  27 +
  28 +const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
  29 +const kernel_cap_t __cap_full_set = CAP_FULL_SET;
  30 +const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
  31 +
  32 +EXPORT_SYMBOL(__cap_empty_set);
  33 +EXPORT_SYMBOL(__cap_full_set);
  34 +EXPORT_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 +
  42 +static 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 56 * For sys_getproccap() and sys_setproccap(), any of the three
26 57 * capability set pointers may be NULL -- indicating that that set is
27 58 * uninteresting and/or not to be changed.
28 59  
... ... @@ -42,12 +73,21 @@
42 73 pid_t pid;
43 74 __u32 version;
44 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 79 if (get_user(version, &header->version))
48 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 91 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
52 92 return -EFAULT;
53 93 return -EINVAL;
54 94  
55 95  
... ... @@ -71,15 +111,48 @@
71 111 } else
72 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  
76 116 out:
77 117 read_unlock(&tasklist_lock);
78 118 spin_unlock(&task_capability_lock);
79 119  
80   - if (!ret && copy_to_user(dataptr, &data, sizeof data))
81   - return -EFAULT;
  120 + if (!ret) {
  121 + struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
  122 + unsigned i;
82 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 + }
  155 +
83 156 return ret;
84 157 }
85 158  
... ... @@ -167,6 +240,8 @@
167 240 */
168 241 asmlinkage 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 245 kernel_cap_t inheritable, permitted, effective;
171 246 __u32 version;
172 247 struct task_struct *target;
... ... @@ -176,7 +251,15 @@
176 251 if (get_user(version, &header->version))
177 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 263 if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
181 264 return -EFAULT;
182 265 return -EINVAL;
183 266  
... ... @@ -188,10 +271,22 @@
188 271 if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
189 272 return -EPERM;
190 273  
191   - if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
192   - copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
193   - copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
  274 + if (copy_from_user(&kdata, data, tocopy
  275 + * sizeof(struct __user_cap_data_struct))) {
194 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 291 spin_lock(&task_capability_lock);
197 292 read_lock(&tasklist_lock);
... ... @@ -125,8 +125,7 @@
125 125 * Superuser processes are usually more important, so we make it
126 126 * less likely that we kill those.
127 127 */
128   - if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
129   - p->uid == 0 || p->euid == 0)
  128 + if (__capable(p, CAP_SYS_ADMIN) || p->uid == 0 || p->euid == 0)
130 129 points /= 4;
131 130  
132 131 /*
... ... @@ -135,7 +134,7 @@
135 134 * tend to only have this flag set on applications they think
136 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 138 points /= 4;
140 139  
141 140 /*
security/commoncap.c
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 3 * This program is free software; you can redistribute it and/or modify
4 4 * it under the terms of the GNU General Public License as published by
... ... @@ -93,9 +93,9 @@
93 93 kernel_cap_t *inheritable, kernel_cap_t *permitted)
94 94 {
95 95 /* Derived from kernel/capability.c:sys_capget. */
96   - *effective = cap_t (target->cap_effective);
97   - *inheritable = cap_t (target->cap_inheritable);
98   - *permitted = cap_t (target->cap_permitted);
  96 + *effective = target->cap_effective;
  97 + *inheritable = target->cap_inheritable;
  98 + *permitted = target->cap_permitted;
99 99 return 0;
100 100 }
101 101  
102 102  
103 103  
104 104  
105 105  
106 106  
... ... @@ -197,28 +197,51 @@
197 197 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
198 198 }
199 199  
200   -static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
201   - int size)
  200 +static inline int cap_from_disk(struct vfs_cap_data *caps,
  201 + struct linux_binprm *bprm, unsigned size)
202 202 {
203 203 __u32 magic_etc;
  204 + unsigned tocopy, i;
204 205  
205   - if (size != XATTR_CAPS_SZ)
  206 + if (size < sizeof(magic_etc))
206 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 211 switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
211   - case VFS_CAP_REVISION:
212   - if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
213   - bprm->cap_effective = true;
214   - else
215   - bprm->cap_effective = false;
216   - bprm->cap_permitted = to_cap_t(le32_to_cpu(caps[1]));
217   - bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps[2]));
218   - return 0;
  212 + case VFS_CAP_REVISION_1:
  213 + if (size != XATTR_CAPS_SZ_1)
  214 + return -EINVAL;
  215 + tocopy = VFS_CAP_U32_1;
  216 + break;
  217 + case VFS_CAP_REVISION_2:
  218 + if (size != XATTR_CAPS_SZ_2)
  219 + return -EINVAL;
  220 + tocopy = VFS_CAP_U32_2;
  221 + break;
219 222 default:
220 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 247 /* Locate any VFS capabilities: */
... ... @@ -226,7 +249,7 @@
226 249 {
227 250 struct dentry *dentry;
228 251 int rc = 0;
229   - __le32 v1caps[XATTR_CAPS_SZ];
  252 + struct vfs_cap_data vcaps;
230 253 struct inode *inode;
231 254  
232 255 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
... ... @@ -239,8 +262,8 @@
239 262 if (!inode->i_op || !inode->i_op->getxattr)
240 263 goto out;
241 264  
242   - rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps,
243   - XATTR_CAPS_SZ);
  265 + rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps,
  266 + XATTR_CAPS_SZ);
244 267 if (rc == -ENODATA || rc == -EOPNOTSUPP) {
245 268 /* no data, that's ok */
246 269 rc = 0;
... ... @@ -249,7 +272,7 @@
249 272 if (rc < 0)
250 273 goto out;
251 274  
252   - rc = cap_from_disk(v1caps, bprm, rc);
  275 + rc = cap_from_disk(&vcaps, bprm, rc);
253 276 if (rc)
254 277 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
255 278 __FUNCTION__, rc, bprm->filename);
... ... @@ -344,8 +367,10 @@
344 367 * capability rules */
345 368 if (!is_global_init(current)) {
346 369 current->cap_permitted = new_permitted;
347   - current->cap_effective = bprm->cap_effective ?
348   - new_permitted : 0;
  370 + if (bprm->cap_effective)
  371 + current->cap_effective = new_permitted;
  372 + else
  373 + cap_clear(current->cap_effective);
349 374 }
350 375  
351 376 /* AUD: Audit candidate if current->cap_effective is set */
352 377  
... ... @@ -467,13 +492,15 @@
467 492  
468 493 if (!issecure (SECURE_NO_SETUID_FIXUP)) {
469 494 if (old_fsuid == 0 && current->fsuid != 0) {
470   - cap_t (current->cap_effective) &=
471   - ~CAP_FS_MASK;
  495 + current->cap_effective =
  496 + cap_drop_fs_set(
  497 + current->cap_effective);
472 498 }
473 499 if (old_fsuid != 0 && current->fsuid == 0) {
474   - cap_t (current->cap_effective) |=
475   - (cap_t (current->cap_permitted) &
476   - CAP_FS_MASK);
  500 + current->cap_effective =
  501 + cap_raise_fs_set(
  502 + current->cap_effective,
  503 + current->cap_permitted);
477 504 }
478 505 }
479 506 break;
... ... @@ -577,9 +604,9 @@
577 604  
578 605 void cap_task_reparent_to_init (struct task_struct *p)
579 606 {
580   - p->cap_effective = CAP_INIT_EFF_SET;
581   - p->cap_inheritable = CAP_INIT_INH_SET;
582   - p->cap_permitted = CAP_FULL_SET;
  607 + cap_set_init_eff(p->cap_effective);
  608 + cap_clear(p->cap_inheritable);
  609 + cap_set_full(p->cap_permitted);
583 610 p->keep_capabilities = 0;
584 611 return;
585 612 }
... ... @@ -36,14 +36,19 @@
36 36 static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
37 37 kernel_cap_t * inheritable, kernel_cap_t * permitted)
38 38 {
39   - *effective = *inheritable = *permitted = 0;
40 39 if (target->euid == 0) {
41   - *permitted |= (~0 & ~CAP_FS_MASK);
42   - *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
  40 + cap_set_full(*permitted);
  41 + cap_set_init_eff(*effective);
  42 + } else {
  43 + cap_clear(*permitted);
  44 + cap_clear(*effective);
43 45 }
44   - if (target->fsuid == 0) {
45   - *permitted |= CAP_FS_MASK;
46   - *effective |= CAP_FS_MASK;
  46 +
  47 + cap_clear(*inheritable);
  48 +
  49 + if (target->fsuid != 0) {
  50 + *permitted = cap_drop_fs_set(*permitted);
  51 + *effective = cap_drop_fs_set(*effective);
47 52 }
48 53 return 0;
49 54 }