aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
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 /include/linux
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>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/capability.h221
1 files changed, 155 insertions, 66 deletions
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);