Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

capability: just use a 'u64' instead of a 'u32[2]' array

Back in 2008 we extended the capability bits from 32 to 64, and we did
it by extending the single 32-bit capability word from one word to an
array of two words. It was then obfuscated by hiding the "2" behind two
macro expansions, with the reasoning being that maybe it gets extended
further some day.

That reasoning may have been valid at the time, but the last thing we
want to do is to extend the capability set any more. And the array of
values not only causes source code oddities (with loops to deal with
it), but also results in worse code generation. It's a lose-lose
situation.

So just change the 'u32[2]' into a 'u64' and be done with it.

We still have to deal with the fact that the user space interface is
designed around an array of these 32-bit values, but that was the case
before too, since the array layouts were different (ie user space
doesn't use an array of 32-bit values for individual capability masks,
but an array of 32-bit slices of multiple masks).

So that marshalling of data is actually simplified too, even if it does
remain somewhat obscure and odd.

This was all triggered by my reaction to the new "cap_isidentical()"
introduced recently. By just using a saner data structure, it went from

unsigned __capi;
CAP_FOR_EACH_U32(__capi) {
if (a.cap[__capi] != b.cap[__capi])
return false;
}
return true;

to just being

return a.val == b.val;

instead. Which is rather more obvious both to humans and to compilers.

Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Cc: Serge Hallyn <serge@hallyn.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Paul Moore <paul@paul-moore.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+148 -237
+1 -6
fs/proc/array.c
··· 300 300 static void render_cap_t(struct seq_file *m, const char *header, 301 301 kernel_cap_t *a) 302 302 { 303 - unsigned __capi; 304 - 305 303 seq_puts(m, header); 306 - CAP_FOR_EACH_U32(__capi) { 307 - seq_put_hex_ll(m, NULL, 308 - a->cap[CAP_LAST_U32 - __capi], 8); 309 - } 304 + seq_put_hex_ll(m, NULL, a->val, 16); 310 305 seq_putc(m, '\n'); 311 306 } 312 307
+29 -102
include/linux/capability.h
··· 15 15 16 16 #include <uapi/linux/capability.h> 17 17 #include <linux/uidgid.h> 18 + #include <linux/bits.h> 18 19 19 20 #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 20 - #define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 21 21 22 22 extern int file_caps_enabled; 23 23 24 - typedef struct kernel_cap_struct { 25 - __u32 cap[_KERNEL_CAPABILITY_U32S]; 26 - } kernel_cap_t; 24 + typedef struct { u64 val; } kernel_cap_t; 27 25 28 26 /* same as vfs_ns_cap_data but in cpu endian and always filled completely */ 29 27 struct cpu_vfs_cap_data { 30 28 __u32 magic_etc; 29 + kuid_t rootid; 31 30 kernel_cap_t permitted; 32 31 kernel_cap_t inheritable; 33 - kuid_t rootid; 34 32 }; 35 33 36 34 #define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) 37 35 #define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) 38 - 39 36 40 37 struct file; 41 38 struct inode; ··· 40 43 struct task_struct; 41 44 struct user_namespace; 42 45 struct mnt_idmap; 43 - 44 - extern const kernel_cap_t __cap_empty_set; 45 - extern const kernel_cap_t __cap_init_eff_set; 46 - 47 - /* 48 - * Internal kernel functions only 49 - */ 50 - 51 - #define CAP_FOR_EACH_U32(__capi) \ 52 - for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi) 53 46 54 47 /* 55 48 * CAP_FS_MASK and CAP_NFSD_MASKS: ··· 54 67 * 2. The security.* and trusted.* xattrs are fs-related MAC permissions 55 68 */ 56 69 57 - # define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ 58 - | CAP_TO_MASK(CAP_MKNOD) \ 59 - | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ 60 - | CAP_TO_MASK(CAP_DAC_READ_SEARCH) \ 61 - | CAP_TO_MASK(CAP_FOWNER) \ 62 - | CAP_TO_MASK(CAP_FSETID)) 70 + # define CAP_FS_MASK (BIT_ULL(CAP_CHOWN) \ 71 + | BIT_ULL(CAP_MKNOD) \ 72 + | BIT_ULL(CAP_DAC_OVERRIDE) \ 73 + | BIT_ULL(CAP_DAC_READ_SEARCH) \ 74 + | BIT_ULL(CAP_FOWNER) \ 75 + | BIT_ULL(CAP_FSETID) \ 76 + | BIT_ULL(CAP_MAC_OVERRIDE)) 77 + #define CAP_VALID_MASK (BIT_ULL(CAP_LAST_CAP+1)-1) 63 78 64 - # define CAP_FS_MASK_B1 (CAP_TO_MASK(CAP_MAC_OVERRIDE)) 79 + # define CAP_EMPTY_SET ((kernel_cap_t) { 0 }) 80 + # define CAP_FULL_SET ((kernel_cap_t) { CAP_VALID_MASK }) 81 + # define CAP_FS_SET ((kernel_cap_t) { CAP_FS_MASK | BIT_ULL(CAP_LINUX_IMMUTABLE) }) 82 + # define CAP_NFSD_SET ((kernel_cap_t) { CAP_FS_MASK | BIT_ULL(CAP_SYS_RESOURCE) }) 65 83 66 - #if _KERNEL_CAPABILITY_U32S != 2 67 - # error Fix up hand-coded capability macro initializers 68 - #else /* HAND-CODED capability initializers */ 84 + # define cap_clear(c) do { (c).val = 0; } while (0) 69 85 70 - #define CAP_LAST_U32 ((_KERNEL_CAPABILITY_U32S) - 1) 71 - #define CAP_LAST_U32_VALID_MASK (CAP_TO_MASK(CAP_LAST_CAP + 1) -1) 72 - 73 - # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) 74 - # define CAP_FULL_SET ((kernel_cap_t){{ ~0, CAP_LAST_U32_VALID_MASK }}) 75 - # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ 76 - | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ 77 - CAP_FS_MASK_B1 } }) 78 - # define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ 79 - | CAP_TO_MASK(CAP_SYS_RESOURCE), \ 80 - CAP_FS_MASK_B1 } }) 81 - 82 - #endif /* _KERNEL_CAPABILITY_U32S != 2 */ 83 - 84 - # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) 85 - 86 - #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) 87 - #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) 88 - #define cap_raised(c, flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag)) 89 - 90 - #define CAP_BOP_ALL(c, a, b, OP) \ 91 - do { \ 92 - unsigned __capi; \ 93 - CAP_FOR_EACH_U32(__capi) { \ 94 - c.cap[__capi] = a.cap[__capi] OP b.cap[__capi]; \ 95 - } \ 96 - } while (0) 97 - 98 - #define CAP_UOP_ALL(c, a, OP) \ 99 - do { \ 100 - unsigned __capi; \ 101 - CAP_FOR_EACH_U32(__capi) { \ 102 - c.cap[__capi] = OP a.cap[__capi]; \ 103 - } \ 104 - } while (0) 86 + #define cap_raise(c, flag) ((c).val |= BIT_ULL(flag)) 87 + #define cap_lower(c, flag) ((c).val &= ~BIT_ULL(flag)) 88 + #define cap_raised(c, flag) (((c).val & BIT_ULL(flag)) != 0) 105 89 106 90 static inline kernel_cap_t cap_combine(const kernel_cap_t a, 107 91 const kernel_cap_t b) 108 92 { 109 - kernel_cap_t dest; 110 - CAP_BOP_ALL(dest, a, b, |); 111 - return dest; 93 + return (kernel_cap_t) { a.val | b.val }; 112 94 } 113 95 114 96 static inline kernel_cap_t cap_intersect(const kernel_cap_t a, 115 97 const kernel_cap_t b) 116 98 { 117 - kernel_cap_t dest; 118 - CAP_BOP_ALL(dest, a, b, &); 119 - return dest; 99 + return (kernel_cap_t) { a.val & b.val }; 120 100 } 121 101 122 102 static inline kernel_cap_t cap_drop(const kernel_cap_t a, 123 103 const kernel_cap_t drop) 124 104 { 125 - kernel_cap_t dest; 126 - CAP_BOP_ALL(dest, a, drop, &~); 127 - return dest; 128 - } 129 - 130 - static inline kernel_cap_t cap_invert(const kernel_cap_t c) 131 - { 132 - kernel_cap_t dest; 133 - CAP_UOP_ALL(dest, c, ~); 134 - return dest; 105 + return (kernel_cap_t) { a.val &~ drop.val }; 135 106 } 136 107 137 108 static inline bool cap_isclear(const kernel_cap_t a) 138 109 { 139 - unsigned __capi; 140 - CAP_FOR_EACH_U32(__capi) { 141 - if (a.cap[__capi] != 0) 142 - return false; 143 - } 144 - return true; 110 + return !a.val; 145 111 } 146 112 147 113 static inline bool cap_isidentical(const kernel_cap_t a, const kernel_cap_t b) 148 114 { 149 - unsigned __capi; 150 - CAP_FOR_EACH_U32(__capi) { 151 - if (a.cap[__capi] != b.cap[__capi]) 152 - return false; 153 - } 154 - return true; 115 + return a.val == b.val; 155 116 } 156 117 157 118 /* ··· 111 176 */ 112 177 static inline bool cap_issubset(const kernel_cap_t a, const kernel_cap_t set) 113 178 { 114 - kernel_cap_t dest; 115 - dest = cap_drop(a, set); 116 - return cap_isclear(dest); 179 + return !(a.val & ~set.val); 117 180 } 118 181 119 182 /* Used to decide between falling back on the old suser() or fsuser(). */ 120 183 121 184 static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a) 122 185 { 123 - const kernel_cap_t __cap_fs_set = CAP_FS_SET; 124 - return cap_drop(a, __cap_fs_set); 186 + return cap_drop(a, CAP_FS_SET); 125 187 } 126 188 127 189 static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a, 128 190 const kernel_cap_t permitted) 129 191 { 130 - const kernel_cap_t __cap_fs_set = CAP_FS_SET; 131 - return cap_combine(a, 132 - cap_intersect(permitted, __cap_fs_set)); 192 + return cap_combine(a, cap_intersect(permitted, CAP_FS_SET)); 133 193 } 134 194 135 195 static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a) 136 196 { 137 - const kernel_cap_t __cap_fs_set = CAP_NFSD_SET; 138 - return cap_drop(a, __cap_fs_set); 197 + return cap_drop(a, CAP_NFSD_SET); 139 198 } 140 199 141 200 static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a, 142 201 const kernel_cap_t permitted) 143 202 { 144 - const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET; 145 - return cap_combine(a, 146 - cap_intersect(permitted, __cap_nfsd_set)); 203 + return cap_combine(a, cap_intersect(permitted, CAP_NFSD_SET)); 147 204 } 148 205 149 206 #ifdef CONFIG_MULTIUSER
+1 -3
io_uring/fdinfo.c
··· 22 22 struct user_namespace *uns = seq_user_ns(m); 23 23 struct group_info *gi; 24 24 kernel_cap_t cap; 25 - unsigned __capi; 26 25 int g; 27 26 28 27 seq_printf(m, "%5d\n", id); ··· 41 42 } 42 43 seq_puts(m, "\n\tCapEff:\t"); 43 44 cap = cred->cap_effective; 44 - CAP_FOR_EACH_U32(__capi) 45 - seq_put_hex_ll(m, NULL, cap.cap[CAP_LAST_U32 - __capi], 8); 45 + seq_put_hex_ll(m, NULL, cap.val, 16); 46 46 seq_putc(m, '\n'); 47 47 return 0; 48 48 }
+1 -5
kernel/auditsc.c
··· 1295 1295 static void audit_log_cap(struct audit_buffer *ab, char *prefix, 1296 1296 kernel_cap_t *cap) 1297 1297 { 1298 - int i; 1299 - 1300 1298 if (cap_isclear(*cap)) { 1301 1299 audit_log_format(ab, " %s=0", prefix); 1302 1300 return; 1303 1301 } 1304 - audit_log_format(ab, " %s=", prefix); 1305 - CAP_FOR_EACH_U32(i) 1306 - audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]); 1302 + audit_log_format(ab, " %s=%016llx", prefix, cap->val); 1307 1303 } 1308 1304 1309 1305 static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
+43 -57
kernel/capability.c
··· 20 20 #include <linux/user_namespace.h> 21 21 #include <linux/uaccess.h> 22 22 23 - /* 24 - * Leveraged for setting/resetting capabilities 25 - */ 26 - 27 - const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; 28 - EXPORT_SYMBOL(__cap_empty_set); 29 - 30 23 int file_caps_enabled = 1; 31 24 32 25 static int __init file_caps_disable(char *str) ··· 144 151 pid_t pid; 145 152 unsigned tocopy; 146 153 kernel_cap_t pE, pI, pP; 154 + struct __user_cap_data_struct kdata[2]; 147 155 148 156 ret = cap_validate_magic(header, &tocopy); 149 157 if ((dataptr == NULL) || (ret != 0)) ··· 157 163 return -EINVAL; 158 164 159 165 ret = cap_get_target_pid(pid, &pE, &pI, &pP); 160 - if (!ret) { 161 - struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 162 - unsigned i; 166 + if (ret) 167 + return ret; 163 168 164 - for (i = 0; i < tocopy; i++) { 165 - kdata[i].effective = pE.cap[i]; 166 - kdata[i].permitted = pP.cap[i]; 167 - kdata[i].inheritable = pI.cap[i]; 168 - } 169 + /* 170 + * Annoying legacy format with 64-bit capabilities exposed 171 + * as two sets of 32-bit fields, so we need to split the 172 + * capability values up. 173 + */ 174 + kdata[0].effective = pE.val; kdata[1].effective = pE.val >> 32; 175 + kdata[0].permitted = pP.val; kdata[1].permitted = pP.val >> 32; 176 + kdata[0].inheritable = pI.val; kdata[1].inheritable = pI.val >> 32; 169 177 170 - /* 171 - * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, 172 - * we silently drop the upper capabilities here. This 173 - * has the effect of making older libcap 174 - * implementations implicitly drop upper capability 175 - * bits when they perform a: capget/modify/capset 176 - * sequence. 177 - * 178 - * This behavior is considered fail-safe 179 - * behavior. Upgrading the application to a newer 180 - * version of libcap will enable access to the newer 181 - * capabilities. 182 - * 183 - * An alternative would be to return an error here 184 - * (-ERANGE), but that causes legacy applications to 185 - * unexpectedly fail; the capget/modify/capset aborts 186 - * before modification is attempted and the application 187 - * fails. 188 - */ 189 - if (copy_to_user(dataptr, kdata, tocopy 190 - * sizeof(struct __user_cap_data_struct))) { 191 - return -EFAULT; 192 - } 193 - } 178 + /* 179 + * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, 180 + * we silently drop the upper capabilities here. This 181 + * has the effect of making older libcap 182 + * implementations implicitly drop upper capability 183 + * bits when they perform a: capget/modify/capset 184 + * sequence. 185 + * 186 + * This behavior is considered fail-safe 187 + * behavior. Upgrading the application to a newer 188 + * version of libcap will enable access to the newer 189 + * capabilities. 190 + * 191 + * An alternative would be to return an error here 192 + * (-ERANGE), but that causes legacy applications to 193 + * unexpectedly fail; the capget/modify/capset aborts 194 + * before modification is attempted and the application 195 + * fails. 196 + */ 197 + if (copy_to_user(dataptr, kdata, tocopy * sizeof(kdata[0]))) 198 + return -EFAULT; 194 199 195 - return ret; 200 + return 0; 201 + } 202 + 203 + static kernel_cap_t mk_kernel_cap(u32 low, u32 high) 204 + { 205 + return (kernel_cap_t) { (low | ((u64)high << 32)) & CAP_VALID_MASK }; 196 206 } 197 207 198 208 /** ··· 219 221 */ 220 222 SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) 221 223 { 222 - struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; 223 - unsigned i, tocopy, copybytes; 224 + struct __user_cap_data_struct kdata[2] = { { 0, }, }; 225 + unsigned tocopy, copybytes; 224 226 kernel_cap_t inheritable, permitted, effective; 225 227 struct cred *new; 226 228 int ret; ··· 244 246 if (copy_from_user(&kdata, data, copybytes)) 245 247 return -EFAULT; 246 248 247 - for (i = 0; i < tocopy; i++) { 248 - effective.cap[i] = kdata[i].effective; 249 - permitted.cap[i] = kdata[i].permitted; 250 - inheritable.cap[i] = kdata[i].inheritable; 251 - } 252 - while (i < _KERNEL_CAPABILITY_U32S) { 253 - effective.cap[i] = 0; 254 - permitted.cap[i] = 0; 255 - inheritable.cap[i] = 0; 256 - i++; 257 - } 258 - 259 - effective.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 260 - permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 261 - inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 249 + effective = mk_kernel_cap(kdata[0].effective, kdata[1].effective); 250 + permitted = mk_kernel_cap(kdata[0].permitted, kdata[1].permitted); 251 + inheritable = mk_kernel_cap(kdata[0].inheritable, kdata[1].inheritable); 262 252 263 253 new = prepare_creds(); 264 254 if (!new)
+18 -23
kernel/umh.c
··· 501 501 void *buffer, size_t *lenp, loff_t *ppos) 502 502 { 503 503 struct ctl_table t; 504 - unsigned long cap_array[_KERNEL_CAPABILITY_U32S]; 505 - kernel_cap_t new_cap; 506 - int err, i; 504 + unsigned long cap_array[2]; 505 + kernel_cap_t new_cap, *cap; 506 + int err; 507 507 508 508 if (write && (!capable(CAP_SETPCAP) || 509 509 !capable(CAP_SYS_MODULE))) ··· 514 514 * userspace if this is a read. 515 515 */ 516 516 spin_lock(&umh_sysctl_lock); 517 - for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) { 518 - if (table->data == CAP_BSET) 519 - cap_array[i] = usermodehelper_bset.cap[i]; 520 - else if (table->data == CAP_PI) 521 - cap_array[i] = usermodehelper_inheritable.cap[i]; 522 - else 523 - BUG(); 524 - } 517 + if (table->data == CAP_BSET) 518 + cap = &usermodehelper_bset; 519 + else if (table->data == CAP_PI) 520 + cap = &usermodehelper_inheritable; 521 + else 522 + BUG(); 523 + 524 + /* Legacy format: capabilities are exposed as two 32-bit values */ 525 + cap_array[0] = (u32) cap->val; 526 + cap_array[1] = cap->val >> 32; 525 527 spin_unlock(&umh_sysctl_lock); 526 528 527 529 t = *table; ··· 537 535 if (err < 0) 538 536 return err; 539 537 540 - /* 541 - * convert from the sysctl array of ulongs to the kernel_cap_t 542 - * internal representation 543 - */ 544 - for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) 545 - new_cap.cap[i] = cap_array[i]; 538 + new_cap.val = (u32)cap_array[0]; 539 + new_cap.val += (u64)cap_array[1] << 32; 546 540 547 541 /* 548 542 * Drop everything not in the new_cap (but don't add things) 549 543 */ 550 544 if (write) { 551 545 spin_lock(&umh_sysctl_lock); 552 - if (table->data == CAP_BSET) 553 - usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap); 554 - if (table->data == CAP_PI) 555 - usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap); 546 + *cap = cap_intersect(*cap, new_cap); 556 547 spin_unlock(&umh_sysctl_lock); 557 548 } 558 549 ··· 556 561 { 557 562 .procname = "bset", 558 563 .data = CAP_BSET, 559 - .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), 564 + .maxlen = 2 * sizeof(unsigned long), 560 565 .mode = 0600, 561 566 .proc_handler = proc_cap_handler, 562 567 }, 563 568 { 564 569 .procname = "inheritable", 565 570 .data = CAP_PI, 566 - .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), 571 + .maxlen = 2 * sizeof(unsigned long), 567 572 .mode = 0600, 568 573 .proc_handler = proc_cap_handler, 569 574 },
+30 -10
security/apparmor/policy_unpack.c
··· 304 304 } 305 305 EXPORT_SYMBOL_IF_KUNIT(aa_unpack_u64); 306 306 307 + static bool aa_unpack_cap_low(struct aa_ext *e, kernel_cap_t *data, const char *name) 308 + { 309 + u32 val; 310 + 311 + if (!aa_unpack_u32(e, &val, name)) 312 + return false; 313 + data->val = val; 314 + return true; 315 + } 316 + 317 + static bool aa_unpack_cap_high(struct aa_ext *e, kernel_cap_t *data, const char *name) 318 + { 319 + u32 val; 320 + 321 + if (!aa_unpack_u32(e, &val, name)) 322 + return false; 323 + data->val = (u32)data->val | ((u64)val << 32); 324 + return true; 325 + } 326 + 307 327 VISIBLE_IF_KUNIT bool aa_unpack_array(struct aa_ext *e, const char *name, u16 *size) 308 328 { 309 329 void *pos = e->pos; ··· 917 897 profile->path_flags = PATH_MEDIATE_DELETED; 918 898 919 899 info = "failed to unpack profile capabilities"; 920 - if (!aa_unpack_u32(e, &(rules->caps.allow.cap[0]), NULL)) 900 + if (!aa_unpack_cap_low(e, &rules->caps.allow, NULL)) 921 901 goto fail; 922 - if (!aa_unpack_u32(e, &(rules->caps.audit.cap[0]), NULL)) 902 + if (!aa_unpack_cap_low(e, &rules->caps.audit, NULL)) 923 903 goto fail; 924 - if (!aa_unpack_u32(e, &(rules->caps.quiet.cap[0]), NULL)) 904 + if (!aa_unpack_cap_low(e, &rules->caps.quiet, NULL)) 925 905 goto fail; 926 - if (!aa_unpack_u32(e, &tmpcap.cap[0], NULL)) 906 + if (!aa_unpack_cap_low(e, &tmpcap, NULL)) 927 907 goto fail; 928 908 929 909 info = "failed to unpack upper profile capabilities"; 930 910 if (aa_unpack_nameX(e, AA_STRUCT, "caps64")) { 931 911 /* optional upper half of 64 bit caps */ 932 - if (!aa_unpack_u32(e, &(rules->caps.allow.cap[1]), NULL)) 912 + if (!aa_unpack_cap_high(e, &rules->caps.allow, NULL)) 933 913 goto fail; 934 - if (!aa_unpack_u32(e, &(rules->caps.audit.cap[1]), NULL)) 914 + if (!aa_unpack_cap_high(e, &rules->caps.audit, NULL)) 935 915 goto fail; 936 - if (!aa_unpack_u32(e, &(rules->caps.quiet.cap[1]), NULL)) 916 + if (!aa_unpack_cap_high(e, &rules->caps.quiet, NULL)) 937 917 goto fail; 938 - if (!aa_unpack_u32(e, &(tmpcap.cap[1]), NULL)) 918 + if (!aa_unpack_cap_high(e, &tmpcap, NULL)) 939 919 goto fail; 940 920 if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 941 921 goto fail; ··· 944 924 info = "failed to unpack extended profile capabilities"; 945 925 if (aa_unpack_nameX(e, AA_STRUCT, "capsx")) { 946 926 /* optional extended caps mediation mask */ 947 - if (!aa_unpack_u32(e, &(rules->caps.extended.cap[0]), NULL)) 927 + if (!aa_unpack_cap_low(e, &rules->caps.extended, NULL)) 948 928 goto fail; 949 - if (!aa_unpack_u32(e, &(rules->caps.extended.cap[1]), NULL)) 929 + if (!aa_unpack_cap_high(e, &rules->caps.extended, NULL)) 950 930 goto fail; 951 931 if (!aa_unpack_nameX(e, AA_STRUCTEND, NULL)) 952 932 goto fail;
+22 -27
security/commoncap.c
··· 589 589 bool *has_fcap) 590 590 { 591 591 struct cred *new = bprm->cred; 592 - unsigned i; 593 592 int ret = 0; 594 593 595 594 if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) ··· 597 598 if (caps->magic_etc & VFS_CAP_REVISION_MASK) 598 599 *has_fcap = true; 599 600 600 - CAP_FOR_EACH_U32(i) { 601 - __u32 permitted = caps->permitted.cap[i]; 602 - __u32 inheritable = caps->inheritable.cap[i]; 601 + /* 602 + * pP' = (X & fP) | (pI & fI) 603 + * The addition of pA' is handled later. 604 + */ 605 + new->cap_permitted.val = 606 + (new->cap_bset.val & caps->permitted.val) | 607 + (new->cap_inheritable.val & caps->inheritable.val); 603 608 604 - /* 605 - * pP' = (X & fP) | (pI & fI) 606 - * The addition of pA' is handled later. 607 - */ 608 - new->cap_permitted.cap[i] = 609 - (new->cap_bset.cap[i] & permitted) | 610 - (new->cap_inheritable.cap[i] & inheritable); 611 - 612 - if (permitted & ~new->cap_permitted.cap[i]) 613 - /* insufficient to execute correctly */ 614 - ret = -EPERM; 615 - } 609 + if (caps->permitted.val & ~new->cap_permitted.val) 610 + /* insufficient to execute correctly */ 611 + ret = -EPERM; 616 612 617 613 /* 618 614 * For legacy apps, with no internal support for recognizing they ··· 638 644 { 639 645 struct inode *inode = d_backing_inode(dentry); 640 646 __u32 magic_etc; 641 - unsigned tocopy, i; 642 647 int size; 643 648 struct vfs_ns_cap_data data, *nscaps = &data; 644 649 struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; ··· 670 677 case VFS_CAP_REVISION_1: 671 678 if (size != XATTR_CAPS_SZ_1) 672 679 return -EINVAL; 673 - tocopy = VFS_CAP_U32_1; 674 680 break; 675 681 case VFS_CAP_REVISION_2: 676 682 if (size != XATTR_CAPS_SZ_2) 677 683 return -EINVAL; 678 - tocopy = VFS_CAP_U32_2; 679 684 break; 680 685 case VFS_CAP_REVISION_3: 681 686 if (size != XATTR_CAPS_SZ_3) 682 687 return -EINVAL; 683 - tocopy = VFS_CAP_U32_3; 684 688 rootkuid = make_kuid(fs_ns, le32_to_cpu(nscaps->rootid)); 685 689 break; 686 690 ··· 695 705 if (!rootid_owns_currentns(rootvfsuid)) 696 706 return -ENODATA; 697 707 698 - CAP_FOR_EACH_U32(i) { 699 - if (i >= tocopy) 700 - break; 701 - cpu_caps->permitted.cap[i] = le32_to_cpu(caps->data[i].permitted); 702 - cpu_caps->inheritable.cap[i] = le32_to_cpu(caps->data[i].inheritable); 708 + cpu_caps->permitted.val = le32_to_cpu(caps->data[0].permitted); 709 + cpu_caps->inheritable.val = le32_to_cpu(caps->data[0].inheritable); 710 + 711 + /* 712 + * Rev1 had just a single 32-bit word, later expanded 713 + * to a second one for the high bits 714 + */ 715 + if ((magic_etc & VFS_CAP_REVISION_MASK) != VFS_CAP_REVISION_1) { 716 + cpu_caps->permitted.val += (u64)le32_to_cpu(caps->data[1].permitted) << 32; 717 + cpu_caps->inheritable.val += (u64)le32_to_cpu(caps->data[1].inheritable) << 32; 703 718 } 704 719 705 - cpu_caps->permitted.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 706 - cpu_caps->inheritable.cap[CAP_LAST_U32] &= CAP_LAST_U32_VALID_MASK; 720 + cpu_caps->permitted.val &= CAP_VALID_MASK; 721 + cpu_caps->inheritable.val &= CAP_VALID_MASK; 707 722 708 723 cpu_caps->rootid = vfsuid_into_kuid(rootvfsuid); 709 724
+3 -4
tools/testing/selftests/bpf/progs/test_deny_namespace.c
··· 6 6 #include <linux/capability.h> 7 7 8 8 struct kernel_cap_struct { 9 - __u32 cap[_LINUX_CAPABILITY_U32S_3]; 9 + __u64 val; 10 10 } __attribute__((preserve_access_index)); 11 11 12 12 struct cred { ··· 19 19 int BPF_PROG(test_userns_create, const struct cred *cred, int ret) 20 20 { 21 21 struct kernel_cap_struct caps = cred->cap_effective; 22 - int cap_index = CAP_TO_INDEX(CAP_SYS_ADMIN); 23 - __u32 cap_mask = CAP_TO_MASK(CAP_SYS_ADMIN); 22 + __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN); 24 23 25 24 if (ret) 26 25 return 0; 27 26 28 27 ret = -EPERM; 29 - if (caps.cap[cap_index] & cap_mask) 28 + if (caps.val & cap_mask) 30 29 return 0; 31 30 32 31 return -EPERM;