diff options
| -rw-r--r-- | fs/proc/array.c | 2 | ||||
| -rw-r--r-- | include/linux/capability.h | 29 | ||||
| -rw-r--r-- | kernel/capability.c | 111 |
3 files changed, 95 insertions, 47 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index 9e3b8c33c24..797d775e035 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
| @@ -288,7 +288,7 @@ static void render_cap_t(struct seq_file *m, const char *header, | |||
| 288 | seq_printf(m, "%s", header); | 288 | seq_printf(m, "%s", header); |
| 289 | CAP_FOR_EACH_U32(__capi) { | 289 | CAP_FOR_EACH_U32(__capi) { |
| 290 | seq_printf(m, "%08x", | 290 | seq_printf(m, "%08x", |
| 291 | a->cap[(_LINUX_CAPABILITY_U32S-1) - __capi]); | 291 | a->cap[(_KERNEL_CAPABILITY_U32S-1) - __capi]); |
| 292 | } | 292 | } |
| 293 | seq_printf(m, "\n"); | 293 | seq_printf(m, "\n"); |
| 294 | } | 294 | } |
diff --git a/include/linux/capability.h b/include/linux/capability.h index f4ea0dd9a61..fa830f8de03 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
| @@ -31,11 +31,11 @@ struct task_struct; | |||
| 31 | #define _LINUX_CAPABILITY_VERSION_1 0x19980330 | 31 | #define _LINUX_CAPABILITY_VERSION_1 0x19980330 |
| 32 | #define _LINUX_CAPABILITY_U32S_1 1 | 32 | #define _LINUX_CAPABILITY_U32S_1 1 |
| 33 | 33 | ||
| 34 | #define _LINUX_CAPABILITY_VERSION_2 0x20071026 | 34 | #define _LINUX_CAPABILITY_VERSION_2 0x20071026 /* deprecated - use v3 */ |
| 35 | #define _LINUX_CAPABILITY_U32S_2 2 | 35 | #define _LINUX_CAPABILITY_U32S_2 2 |
| 36 | 36 | ||
| 37 | #define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_2 | 37 | #define _LINUX_CAPABILITY_VERSION_3 0x20080522 |
| 38 | #define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_2 | 38 | #define _LINUX_CAPABILITY_U32S_3 2 |
| 39 | 39 | ||
| 40 | typedef struct __user_cap_header_struct { | 40 | typedef struct __user_cap_header_struct { |
| 41 | __u32 version; | 41 | __u32 version; |
| @@ -77,10 +77,23 @@ struct vfs_cap_data { | |||
| 77 | } data[VFS_CAP_U32]; | 77 | } data[VFS_CAP_U32]; |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | #ifdef __KERNEL__ | 80 | #ifndef __KERNEL__ |
| 81 | |||
| 82 | /* | ||
| 83 | * Backwardly compatible definition for source code - trapped in a | ||
| 84 | * 32-bit world. If you find you need this, please consider using | ||
| 85 | * libcap to untrap yourself... | ||
| 86 | */ | ||
| 87 | #define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1 | ||
| 88 | #define _LINUX_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_1 | ||
| 89 | |||
| 90 | #else | ||
| 91 | |||
| 92 | #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 | ||
| 93 | #define _KERNEL_CAPABILITY_U32S _LINUX_CAPABILITY_U32S_3 | ||
| 81 | 94 | ||
| 82 | typedef struct kernel_cap_struct { | 95 | typedef struct kernel_cap_struct { |
| 83 | __u32 cap[_LINUX_CAPABILITY_U32S]; | 96 | __u32 cap[_KERNEL_CAPABILITY_U32S]; |
| 84 | } kernel_cap_t; | 97 | } kernel_cap_t; |
| 85 | 98 | ||
| 86 | #define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) | 99 | #define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) |
| @@ -351,7 +364,7 @@ typedef struct kernel_cap_struct { | |||
| 351 | */ | 364 | */ |
| 352 | 365 | ||
| 353 | #define CAP_FOR_EACH_U32(__capi) \ | 366 | #define CAP_FOR_EACH_U32(__capi) \ |
| 354 | for (__capi = 0; __capi < _LINUX_CAPABILITY_U32S; ++__capi) | 367 | for (__capi = 0; __capi < _KERNEL_CAPABILITY_U32S; ++__capi) |
| 355 | 368 | ||
| 356 | # define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ | 369 | # define CAP_FS_MASK_B0 (CAP_TO_MASK(CAP_CHOWN) \ |
| 357 | | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ | 370 | | CAP_TO_MASK(CAP_DAC_OVERRIDE) \ |
| @@ -361,7 +374,7 @@ typedef struct kernel_cap_struct { | |||
| 361 | 374 | ||
| 362 | # define CAP_FS_MASK_B1 (CAP_TO_MASK(CAP_MAC_OVERRIDE)) | 375 | # define CAP_FS_MASK_B1 (CAP_TO_MASK(CAP_MAC_OVERRIDE)) |
| 363 | 376 | ||
| 364 | #if _LINUX_CAPABILITY_U32S != 2 | 377 | #if _KERNEL_CAPABILITY_U32S != 2 |
| 365 | # error Fix up hand-coded capability macro initializers | 378 | # error Fix up hand-coded capability macro initializers |
| 366 | #else /* HAND-CODED capability initializers */ | 379 | #else /* HAND-CODED capability initializers */ |
| 367 | 380 | ||
| @@ -372,7 +385,7 @@ typedef struct kernel_cap_struct { | |||
| 372 | # define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \ | 385 | # define CAP_NFSD_SET ((kernel_cap_t){{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \ |
| 373 | CAP_FS_MASK_B1 } }) | 386 | CAP_FS_MASK_B1 } }) |
| 374 | 387 | ||
| 375 | #endif /* _LINUX_CAPABILITY_U32S != 2 */ | 388 | #endif /* _KERNEL_CAPABILITY_U32S != 2 */ |
| 376 | 389 | ||
| 377 | #define CAP_INIT_INH_SET CAP_EMPTY_SET | 390 | #define CAP_INIT_INH_SET CAP_EMPTY_SET |
| 378 | 391 | ||
diff --git a/kernel/capability.c b/kernel/capability.c index 39e8193b41e..cfbe4429948 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
| @@ -53,6 +53,69 @@ static void warn_legacy_capability_use(void) | |||
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | /* | 55 | /* |
| 56 | * Version 2 capabilities worked fine, but the linux/capability.h file | ||
| 57 | * that accompanied their introduction encouraged their use without | ||
| 58 | * the necessary user-space source code changes. As such, we have | ||
| 59 | * created a version 3 with equivalent functionality to version 2, but | ||
| 60 | * with a header change to protect legacy source code from using | ||
| 61 | * version 2 when it wanted to use version 1. If your system has code | ||
| 62 | * that trips the following warning, it is using version 2 specific | ||
| 63 | * capabilities and may be doing so insecurely. | ||
| 64 | * | ||
| 65 | * The remedy is to either upgrade your version of libcap (to 2.10+, | ||
| 66 | * if the application is linked against it), or recompile your | ||
| 67 | * application with modern kernel headers and this warning will go | ||
| 68 | * away. | ||
| 69 | */ | ||
| 70 | |||
| 71 | static void warn_deprecated_v2(void) | ||
| 72 | { | ||
| 73 | static int warned; | ||
| 74 | |||
| 75 | if (!warned) { | ||
| 76 | char name[sizeof(current->comm)]; | ||
| 77 | |||
| 78 | printk(KERN_INFO "warning: `%s' uses deprecated v2" | ||
| 79 | " capabilities in a way that may be insecure.\n", | ||
| 80 | get_task_comm(name, current)); | ||
| 81 | warned = 1; | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Version check. Return the number of u32s in each capability flag | ||
| 87 | * array, or a negative value on error. | ||
| 88 | */ | ||
| 89 | static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) | ||
| 90 | { | ||
| 91 | __u32 version; | ||
| 92 | |||
| 93 | if (get_user(version, &header->version)) | ||
| 94 | return -EFAULT; | ||
| 95 | |||
| 96 | switch (version) { | ||
| 97 | case _LINUX_CAPABILITY_VERSION_1: | ||
| 98 | warn_legacy_capability_use(); | ||
| 99 | *tocopy = _LINUX_CAPABILITY_U32S_1; | ||
| 100 | break; | ||
| 101 | case _LINUX_CAPABILITY_VERSION_2: | ||
| 102 | warn_deprecated_v2(); | ||
| 103 | /* | ||
| 104 | * fall through - v3 is otherwise equivalent to v2. | ||
| 105 | */ | ||
| 106 | case _LINUX_CAPABILITY_VERSION_3: | ||
| 107 | *tocopy = _LINUX_CAPABILITY_U32S_3; | ||
| 108 | break; | ||
| 109 | default: | ||
| 110 | if (put_user((u32)_KERNEL_CAPABILITY_VERSION, &header->version)) | ||
| 111 | return -EFAULT; | ||
| 112 | return -EINVAL; | ||
| 113 | } | ||
| 114 | |||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* | ||
| 56 | * For sys_getproccap() and sys_setproccap(), any of the three | 119 | * For sys_getproccap() and sys_setproccap(), any of the three |
| 57 | * capability set pointers may be NULL -- indicating that that set is | 120 | * capability set pointers may be NULL -- indicating that that set is |
| 58 | * uninteresting and/or not to be changed. | 121 | * uninteresting and/or not to be changed. |
| @@ -71,27 +134,13 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) | |||
| 71 | { | 134 | { |
| 72 | int ret = 0; | 135 | int ret = 0; |
| 73 | pid_t pid; | 136 | pid_t pid; |
| 74 | __u32 version; | ||
| 75 | struct task_struct *target; | 137 | struct task_struct *target; |
| 76 | unsigned tocopy; | 138 | unsigned tocopy; |
| 77 | kernel_cap_t pE, pI, pP; | 139 | kernel_cap_t pE, pI, pP; |
| 78 | 140 | ||
| 79 | if (get_user(version, &header->version)) | 141 | ret = cap_validate_magic(header, &tocopy); |
| 80 | return -EFAULT; | 142 | if (ret != 0) |
| 81 | 143 | return ret; | |
| 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: | ||
| 91 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | ||
| 92 | return -EFAULT; | ||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | 144 | ||
| 96 | if (get_user(pid, &header->pid)) | 145 | if (get_user(pid, &header->pid)) |
| 97 | return -EFAULT; | 146 | return -EFAULT; |
| @@ -118,7 +167,7 @@ out: | |||
| 118 | spin_unlock(&task_capability_lock); | 167 | spin_unlock(&task_capability_lock); |
| 119 | 168 | ||
| 120 | if (!ret) { | 169 | if (!ret) { |
| 121 | struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S]; | 170 | struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; |
| 122 | unsigned i; | 171 | unsigned i; |
| 123 | 172 | ||
| 124 | for (i = 0; i < tocopy; i++) { | 173 | for (i = 0; i < tocopy; i++) { |
| @@ -128,7 +177,7 @@ out: | |||
| 128 | } | 177 | } |
| 129 | 178 | ||
| 130 | /* | 179 | /* |
| 131 | * Note, in the case, tocopy < _LINUX_CAPABILITY_U32S, | 180 | * Note, in the case, tocopy < _KERNEL_CAPABILITY_U32S, |
| 132 | * we silently drop the upper capabilities here. This | 181 | * we silently drop the upper capabilities here. This |
| 133 | * has the effect of making older libcap | 182 | * has the effect of making older libcap |
| 134 | * implementations implicitly drop upper capability | 183 | * implementations implicitly drop upper capability |
| @@ -240,30 +289,16 @@ static inline int cap_set_all(kernel_cap_t *effective, | |||
| 240 | */ | 289 | */ |
| 241 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) | 290 | asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) |
| 242 | { | 291 | { |
| 243 | struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S]; | 292 | struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; |
| 244 | unsigned i, tocopy; | 293 | unsigned i, tocopy; |
| 245 | kernel_cap_t inheritable, permitted, effective; | 294 | kernel_cap_t inheritable, permitted, effective; |
| 246 | __u32 version; | ||
| 247 | struct task_struct *target; | 295 | struct task_struct *target; |
| 248 | int ret; | 296 | int ret; |
| 249 | pid_t pid; | 297 | pid_t pid; |
| 250 | 298 | ||
| 251 | if (get_user(version, &header->version)) | 299 | ret = cap_validate_magic(header, &tocopy); |
| 252 | return -EFAULT; | 300 | if (ret != 0) |
| 253 | 301 | return ret; | |
| 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: | ||
| 263 | if (put_user(_LINUX_CAPABILITY_VERSION, &header->version)) | ||
| 264 | return -EFAULT; | ||
| 265 | return -EINVAL; | ||
| 266 | } | ||
| 267 | 302 | ||
| 268 | if (get_user(pid, &header->pid)) | 303 | if (get_user(pid, &header->pid)) |
| 269 | return -EFAULT; | 304 | return -EFAULT; |
| @@ -281,7 +316,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) | |||
| 281 | permitted.cap[i] = kdata[i].permitted; | 316 | permitted.cap[i] = kdata[i].permitted; |
| 282 | inheritable.cap[i] = kdata[i].inheritable; | 317 | inheritable.cap[i] = kdata[i].inheritable; |
| 283 | } | 318 | } |
| 284 | while (i < _LINUX_CAPABILITY_U32S) { | 319 | while (i < _KERNEL_CAPABILITY_U32S) { |
| 285 | effective.cap[i] = 0; | 320 | effective.cap[i] = 0; |
| 286 | permitted.cap[i] = 0; | 321 | permitted.cap[i] = 0; |
| 287 | inheritable.cap[i] = 0; | 322 | inheritable.cap[i] = 0; |
