diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/capability.c | 19 | ||||
| -rw-r--r-- | security/commoncap.c | 152 | ||||
| -rw-r--r-- | security/keys/process_keys.c | 42 | ||||
| -rw-r--r-- | security/root_plug.c | 13 | ||||
| -rw-r--r-- | security/security.c | 26 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 283 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 11 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 3 |
8 files changed, 214 insertions, 335 deletions
diff --git a/security/capability.c b/security/capability.c index efeb6d9e0e6a..185804f99ad1 100644 --- a/security/capability.c +++ b/security/capability.c | |||
| @@ -32,24 +32,19 @@ static int cap_quota_on(struct dentry *dentry) | |||
| 32 | return 0; | 32 | return 0; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | static int cap_bprm_alloc_security(struct linux_binprm *bprm) | 35 | static int cap_bprm_check_security (struct linux_binprm *bprm) |
| 36 | { | 36 | { |
| 37 | return 0; | 37 | return 0; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | static void cap_bprm_free_security(struct linux_binprm *bprm) | 40 | static void cap_bprm_committing_creds(struct linux_binprm *bprm) |
| 41 | { | 41 | { |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static void cap_bprm_post_apply_creds(struct linux_binprm *bprm) | 44 | static void cap_bprm_committed_creds(struct linux_binprm *bprm) |
| 45 | { | 45 | { |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static int cap_bprm_check_security(struct linux_binprm *bprm) | ||
| 49 | { | ||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int cap_sb_alloc_security(struct super_block *sb) | 48 | static int cap_sb_alloc_security(struct super_block *sb) |
| 54 | { | 49 | { |
| 55 | return 0; | 50 | return 0; |
| @@ -827,11 +822,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
| 827 | set_to_cap_if_null(ops, syslog); | 822 | set_to_cap_if_null(ops, syslog); |
| 828 | set_to_cap_if_null(ops, settime); | 823 | set_to_cap_if_null(ops, settime); |
| 829 | set_to_cap_if_null(ops, vm_enough_memory); | 824 | set_to_cap_if_null(ops, vm_enough_memory); |
| 830 | set_to_cap_if_null(ops, bprm_alloc_security); | 825 | set_to_cap_if_null(ops, bprm_set_creds); |
| 831 | set_to_cap_if_null(ops, bprm_free_security); | 826 | set_to_cap_if_null(ops, bprm_committing_creds); |
| 832 | set_to_cap_if_null(ops, bprm_apply_creds); | 827 | set_to_cap_if_null(ops, bprm_committed_creds); |
| 833 | set_to_cap_if_null(ops, bprm_post_apply_creds); | ||
| 834 | set_to_cap_if_null(ops, bprm_set_security); | ||
| 835 | set_to_cap_if_null(ops, bprm_check_security); | 828 | set_to_cap_if_null(ops, bprm_check_security); |
| 836 | set_to_cap_if_null(ops, bprm_secureexec); | 829 | set_to_cap_if_null(ops, bprm_secureexec); |
| 837 | set_to_cap_if_null(ops, sb_alloc_security); | 830 | set_to_cap_if_null(ops, sb_alloc_security); |
diff --git a/security/commoncap.c b/security/commoncap.c index b5419273f92d..51dfa11e8e56 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
| @@ -167,7 +167,7 @@ int cap_capset(struct cred *new, | |||
| 167 | 167 | ||
| 168 | static inline void bprm_clear_caps(struct linux_binprm *bprm) | 168 | static inline void bprm_clear_caps(struct linux_binprm *bprm) |
| 169 | { | 169 | { |
| 170 | cap_clear(bprm->cap_post_exec_permitted); | 170 | cap_clear(bprm->cred->cap_permitted); |
| 171 | bprm->cap_effective = false; | 171 | bprm->cap_effective = false; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -198,15 +198,15 @@ int cap_inode_killpriv(struct dentry *dentry) | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | 200 | static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, |
| 201 | struct linux_binprm *bprm) | 201 | struct linux_binprm *bprm, |
| 202 | bool *effective) | ||
| 202 | { | 203 | { |
| 204 | struct cred *new = bprm->cred; | ||
| 203 | unsigned i; | 205 | unsigned i; |
| 204 | int ret = 0; | 206 | int ret = 0; |
| 205 | 207 | ||
| 206 | if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) | 208 | if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE) |
| 207 | bprm->cap_effective = true; | 209 | *effective = true; |
| 208 | else | ||
| 209 | bprm->cap_effective = false; | ||
| 210 | 210 | ||
| 211 | CAP_FOR_EACH_U32(i) { | 211 | CAP_FOR_EACH_U32(i) { |
| 212 | __u32 permitted = caps->permitted.cap[i]; | 212 | __u32 permitted = caps->permitted.cap[i]; |
| @@ -215,16 +215,13 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | |||
| 215 | /* | 215 | /* |
| 216 | * pP' = (X & fP) | (pI & fI) | 216 | * pP' = (X & fP) | (pI & fI) |
| 217 | */ | 217 | */ |
| 218 | bprm->cap_post_exec_permitted.cap[i] = | 218 | new->cap_permitted.cap[i] = |
| 219 | (current->cred->cap_bset.cap[i] & permitted) | | 219 | (new->cap_bset.cap[i] & permitted) | |
| 220 | (current->cred->cap_inheritable.cap[i] & inheritable); | 220 | (new->cap_inheritable.cap[i] & inheritable); |
| 221 | 221 | ||
| 222 | if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) { | 222 | if (permitted & ~new->cap_permitted.cap[i]) |
| 223 | /* | 223 | /* insufficient to execute correctly */ |
| 224 | * insufficient to execute correctly | ||
| 225 | */ | ||
| 226 | ret = -EPERM; | 224 | ret = -EPERM; |
| 227 | } | ||
| 228 | } | 225 | } |
| 229 | 226 | ||
| 230 | /* | 227 | /* |
| @@ -232,7 +229,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, | |||
| 232 | * do not have enough capabilities, we return an error if they are | 229 | * do not have enough capabilities, we return an error if they are |
| 233 | * missing some "forced" (aka file-permitted) capabilities. | 230 | * missing some "forced" (aka file-permitted) capabilities. |
| 234 | */ | 231 | */ |
| 235 | return bprm->cap_effective ? ret : 0; | 232 | return *effective ? ret : 0; |
| 236 | } | 233 | } |
| 237 | 234 | ||
| 238 | int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) | 235 | int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) |
| @@ -250,10 +247,9 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
| 250 | 247 | ||
| 251 | size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, | 248 | size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps, |
| 252 | XATTR_CAPS_SZ); | 249 | XATTR_CAPS_SZ); |
| 253 | if (size == -ENODATA || size == -EOPNOTSUPP) { | 250 | if (size == -ENODATA || size == -EOPNOTSUPP) |
| 254 | /* no data, that's ok */ | 251 | /* no data, that's ok */ |
| 255 | return -ENODATA; | 252 | return -ENODATA; |
| 256 | } | ||
| 257 | if (size < 0) | 253 | if (size < 0) |
| 258 | return size; | 254 | return size; |
| 259 | 255 | ||
| @@ -262,7 +258,7 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
| 262 | 258 | ||
| 263 | cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); | 259 | cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc); |
| 264 | 260 | ||
| 265 | switch ((magic_etc & VFS_CAP_REVISION_MASK)) { | 261 | switch (magic_etc & VFS_CAP_REVISION_MASK) { |
| 266 | case VFS_CAP_REVISION_1: | 262 | case VFS_CAP_REVISION_1: |
| 267 | if (size != XATTR_CAPS_SZ_1) | 263 | if (size != XATTR_CAPS_SZ_1) |
| 268 | return -EINVAL; | 264 | return -EINVAL; |
| @@ -283,11 +279,12 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data | |||
| 283 | cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); | 279 | cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted); |
| 284 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); | 280 | cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable); |
| 285 | } | 281 | } |
| 282 | |||
| 286 | return 0; | 283 | return 0; |
| 287 | } | 284 | } |
| 288 | 285 | ||
| 289 | /* Locate any VFS capabilities: */ | 286 | /* Locate any VFS capabilities: */ |
| 290 | static int get_file_caps(struct linux_binprm *bprm) | 287 | static int get_file_caps(struct linux_binprm *bprm, bool *effective) |
| 291 | { | 288 | { |
| 292 | struct dentry *dentry; | 289 | struct dentry *dentry; |
| 293 | int rc = 0; | 290 | int rc = 0; |
| @@ -313,7 +310,10 @@ static int get_file_caps(struct linux_binprm *bprm) | |||
| 313 | goto out; | 310 | goto out; |
| 314 | } | 311 | } |
| 315 | 312 | ||
| 316 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm); | 313 | rc = bprm_caps_from_vfs_caps(&vcaps, bprm, effective); |
| 314 | if (rc == -EINVAL) | ||
| 315 | printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", | ||
| 316 | __func__, rc, bprm->filename); | ||
| 317 | 317 | ||
| 318 | out: | 318 | out: |
| 319 | dput(dentry); | 319 | dput(dentry); |
| @@ -334,18 +334,27 @@ int cap_inode_killpriv(struct dentry *dentry) | |||
| 334 | return 0; | 334 | return 0; |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static inline int get_file_caps(struct linux_binprm *bprm) | 337 | static inline int get_file_caps(struct linux_binprm *bprm, bool *effective) |
| 338 | { | 338 | { |
| 339 | bprm_clear_caps(bprm); | 339 | bprm_clear_caps(bprm); |
| 340 | return 0; | 340 | return 0; |
| 341 | } | 341 | } |
| 342 | #endif | 342 | #endif |
| 343 | 343 | ||
| 344 | int cap_bprm_set_security (struct linux_binprm *bprm) | 344 | /* |
| 345 | * set up the new credentials for an exec'd task | ||
| 346 | */ | ||
| 347 | int cap_bprm_set_creds(struct linux_binprm *bprm) | ||
| 345 | { | 348 | { |
| 349 | const struct cred *old = current_cred(); | ||
| 350 | struct cred *new = bprm->cred; | ||
| 351 | bool effective; | ||
| 346 | int ret; | 352 | int ret; |
| 347 | 353 | ||
| 348 | ret = get_file_caps(bprm); | 354 | effective = false; |
| 355 | ret = get_file_caps(bprm, &effective); | ||
| 356 | if (ret < 0) | ||
| 357 | return ret; | ||
| 349 | 358 | ||
| 350 | if (!issecure(SECURE_NOROOT)) { | 359 | if (!issecure(SECURE_NOROOT)) { |
| 351 | /* | 360 | /* |
| @@ -353,63 +362,47 @@ int cap_bprm_set_security (struct linux_binprm *bprm) | |||
| 353 | * executables under compatibility mode, we override the | 362 | * executables under compatibility mode, we override the |
| 354 | * capability sets for the file. | 363 | * capability sets for the file. |
| 355 | * | 364 | * |
| 356 | * If only the real uid is 0, we do not set the effective | 365 | * If only the real uid is 0, we do not set the effective bit. |
| 357 | * bit. | ||
| 358 | */ | 366 | */ |
| 359 | if (bprm->e_uid == 0 || current_uid() == 0) { | 367 | if (new->euid == 0 || new->uid == 0) { |
| 360 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ | 368 | /* pP' = (cap_bset & ~0) | (pI & ~0) */ |
| 361 | bprm->cap_post_exec_permitted = cap_combine( | 369 | new->cap_permitted = cap_combine(old->cap_bset, |
| 362 | current->cred->cap_bset, | 370 | old->cap_inheritable); |
| 363 | current->cred->cap_inheritable); | ||
| 364 | bprm->cap_effective = (bprm->e_uid == 0); | ||
| 365 | ret = 0; | ||
| 366 | } | 371 | } |
| 372 | if (new->euid == 0) | ||
| 373 | effective = true; | ||
| 367 | } | 374 | } |
| 368 | 375 | ||
| 369 | return ret; | 376 | /* Don't let someone trace a set[ug]id/setpcap binary with the revised |
| 370 | } | 377 | * credentials unless they have the appropriate permit |
| 371 | 378 | */ | |
| 372 | int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) | 379 | if ((new->euid != old->uid || |
| 373 | { | 380 | new->egid != old->gid || |
| 374 | const struct cred *old = current_cred(); | 381 | !cap_issubset(new->cap_permitted, old->cap_permitted)) && |
| 375 | struct cred *new; | 382 | bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) { |
| 376 | 383 | /* downgrade; they get no more than they had, and maybe less */ | |
| 377 | new = prepare_creds(); | 384 | if (!capable(CAP_SETUID)) { |
| 378 | if (!new) | 385 | new->euid = new->uid; |
| 379 | return -ENOMEM; | 386 | new->egid = new->gid; |
| 380 | |||
| 381 | if (bprm->e_uid != old->uid || bprm->e_gid != old->gid || | ||
| 382 | !cap_issubset(bprm->cap_post_exec_permitted, | ||
| 383 | old->cap_permitted)) { | ||
| 384 | set_dumpable(current->mm, suid_dumpable); | ||
| 385 | current->pdeath_signal = 0; | ||
| 386 | |||
| 387 | if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { | ||
| 388 | if (!capable(CAP_SETUID)) { | ||
| 389 | bprm->e_uid = old->uid; | ||
| 390 | bprm->e_gid = old->gid; | ||
| 391 | } | ||
| 392 | if (cap_limit_ptraced_target()) { | ||
| 393 | bprm->cap_post_exec_permitted = cap_intersect( | ||
| 394 | bprm->cap_post_exec_permitted, | ||
| 395 | new->cap_permitted); | ||
| 396 | } | ||
| 397 | } | 387 | } |
| 388 | if (cap_limit_ptraced_target()) | ||
| 389 | new->cap_permitted = cap_intersect(new->cap_permitted, | ||
| 390 | old->cap_permitted); | ||
| 398 | } | 391 | } |
| 399 | 392 | ||
| 400 | new->suid = new->euid = new->fsuid = bprm->e_uid; | 393 | new->suid = new->fsuid = new->euid; |
| 401 | new->sgid = new->egid = new->fsgid = bprm->e_gid; | 394 | new->sgid = new->fsgid = new->egid; |
| 402 | 395 | ||
| 403 | /* For init, we want to retain the capabilities set | 396 | /* For init, we want to retain the capabilities set in the initial |
| 404 | * in the init_task struct. Thus we skip the usual | 397 | * task. Thus we skip the usual capability rules |
| 405 | * capability rules */ | 398 | */ |
| 406 | if (!is_global_init(current)) { | 399 | if (!is_global_init(current)) { |
| 407 | new->cap_permitted = bprm->cap_post_exec_permitted; | 400 | if (effective) |
| 408 | if (bprm->cap_effective) | 401 | new->cap_effective = new->cap_permitted; |
| 409 | new->cap_effective = bprm->cap_post_exec_permitted; | ||
| 410 | else | 402 | else |
| 411 | cap_clear(new->cap_effective); | 403 | cap_clear(new->cap_effective); |
| 412 | } | 404 | } |
| 405 | bprm->cap_effective = effective; | ||
| 413 | 406 | ||
| 414 | /* | 407 | /* |
| 415 | * Audit candidate if current->cap_effective is set | 408 | * Audit candidate if current->cap_effective is set |
| @@ -425,23 +418,31 @@ int cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) | |||
| 425 | */ | 418 | */ |
| 426 | if (!cap_isclear(new->cap_effective)) { | 419 | if (!cap_isclear(new->cap_effective)) { |
| 427 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || | 420 | if (!cap_issubset(CAP_FULL_SET, new->cap_effective) || |
| 428 | bprm->e_uid != 0 || new->uid != 0 || | 421 | new->euid != 0 || new->uid != 0 || |
| 429 | issecure(SECURE_NOROOT)) | 422 | issecure(SECURE_NOROOT)) { |
| 430 | audit_log_bprm_fcaps(bprm, new, old); | 423 | ret = audit_log_bprm_fcaps(bprm, new, old); |
| 424 | if (ret < 0) | ||
| 425 | return ret; | ||
| 426 | } | ||
| 431 | } | 427 | } |
| 432 | 428 | ||
| 433 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); | 429 | new->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
| 434 | return commit_creds(new); | 430 | return 0; |
| 435 | } | 431 | } |
| 436 | 432 | ||
| 437 | int cap_bprm_secureexec (struct linux_binprm *bprm) | 433 | /* |
| 434 | * determine whether a secure execution is required | ||
| 435 | * - the creds have been committed at this point, and are no longer available | ||
| 436 | * through bprm | ||
| 437 | */ | ||
| 438 | int cap_bprm_secureexec(struct linux_binprm *bprm) | ||
| 438 | { | 439 | { |
| 439 | const struct cred *cred = current_cred(); | 440 | const struct cred *cred = current_cred(); |
| 440 | 441 | ||
| 441 | if (cred->uid != 0) { | 442 | if (cred->uid != 0) { |
| 442 | if (bprm->cap_effective) | 443 | if (bprm->cap_effective) |
| 443 | return 1; | 444 | return 1; |
| 444 | if (!cap_isclear(bprm->cap_post_exec_permitted)) | 445 | if (!cap_isclear(cred->cap_permitted)) |
| 445 | return 1; | 446 | return 1; |
| 446 | } | 447 | } |
| 447 | 448 | ||
| @@ -477,7 +478,7 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
| 477 | } | 478 | } |
| 478 | 479 | ||
| 479 | /* moved from kernel/sys.c. */ | 480 | /* moved from kernel/sys.c. */ |
| 480 | /* | 481 | /* |
| 481 | * cap_emulate_setxuid() fixes the effective / permitted capabilities of | 482 | * cap_emulate_setxuid() fixes the effective / permitted capabilities of |
| 482 | * a process after a call to setuid, setreuid, or setresuid. | 483 | * a process after a call to setuid, setreuid, or setresuid. |
| 483 | * | 484 | * |
| @@ -491,10 +492,10 @@ int cap_inode_removexattr(struct dentry *dentry, const char *name) | |||
| 491 | * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective | 492 | * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective |
| 492 | * capabilities are set to the permitted capabilities. | 493 | * capabilities are set to the permitted capabilities. |
| 493 | * | 494 | * |
| 494 | * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should | 495 | * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should |
| 495 | * never happen. | 496 | * never happen. |
| 496 | * | 497 | * |
| 497 | * -astor | 498 | * -astor |
| 498 | * | 499 | * |
| 499 | * cevans - New behaviour, Oct '99 | 500 | * cevans - New behaviour, Oct '99 |
| 500 | * A process may, via prctl(), elect to keep its capabilities when it | 501 | * A process may, via prctl(), elect to keep its capabilities when it |
| @@ -751,4 +752,3 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 751 | cap_sys_admin = 1; | 752 | cap_sys_admin = 1; |
| 752 | return __vm_enough_memory(mm, pages, cap_sys_admin); | 753 | return __vm_enough_memory(mm, pages, cap_sys_admin); |
| 753 | } | 754 | } |
| 754 | |||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index df329f684a65..2f5d89e92b85 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
| @@ -276,48 +276,6 @@ static int install_session_keyring(struct key *keyring) | |||
| 276 | 276 | ||
| 277 | /*****************************************************************************/ | 277 | /*****************************************************************************/ |
| 278 | /* | 278 | /* |
| 279 | * deal with execve() | ||
| 280 | */ | ||
| 281 | int exec_keys(struct task_struct *tsk) | ||
| 282 | { | ||
| 283 | struct thread_group_cred *tgcred = NULL; | ||
| 284 | struct cred *new; | ||
| 285 | |||
| 286 | #ifdef CONFIG_KEYS | ||
| 287 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | ||
| 288 | if (!tgcred) | ||
| 289 | return -ENOMEM; | ||
| 290 | #endif | ||
| 291 | |||
| 292 | new = prepare_creds(); | ||
| 293 | if (new < 0) | ||
| 294 | return -ENOMEM; | ||
| 295 | |||
| 296 | /* newly exec'd tasks don't get a thread keyring */ | ||
| 297 | key_put(new->thread_keyring); | ||
| 298 | new->thread_keyring = NULL; | ||
| 299 | |||
| 300 | /* create a new per-thread-group creds for all this set of threads to | ||
| 301 | * share */ | ||
| 302 | memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred)); | ||
| 303 | |||
| 304 | atomic_set(&tgcred->usage, 1); | ||
| 305 | spin_lock_init(&tgcred->lock); | ||
| 306 | |||
| 307 | /* inherit the session keyring; new process keyring */ | ||
| 308 | key_get(tgcred->session_keyring); | ||
| 309 | tgcred->process_keyring = NULL; | ||
| 310 | |||
| 311 | release_tgcred(new); | ||
| 312 | new->tgcred = tgcred; | ||
| 313 | |||
| 314 | commit_creds(new); | ||
| 315 | return 0; | ||
| 316 | |||
| 317 | } /* end exec_keys() */ | ||
| 318 | |||
| 319 | /*****************************************************************************/ | ||
| 320 | /* | ||
| 321 | * the filesystem user ID changed | 279 | * the filesystem user ID changed |
| 322 | */ | 280 | */ |
| 323 | void key_fsuid_changed(struct task_struct *tsk) | 281 | void key_fsuid_changed(struct task_struct *tsk) |
diff --git a/security/root_plug.c b/security/root_plug.c index c3f68b5b372d..40fb4f15e27b 100644 --- a/security/root_plug.c +++ b/security/root_plug.c | |||
| @@ -55,9 +55,9 @@ static int rootplug_bprm_check_security (struct linux_binprm *bprm) | |||
| 55 | struct usb_device *dev; | 55 | struct usb_device *dev; |
| 56 | 56 | ||
| 57 | root_dbg("file %s, e_uid = %d, e_gid = %d\n", | 57 | root_dbg("file %s, e_uid = %d, e_gid = %d\n", |
| 58 | bprm->filename, bprm->e_uid, bprm->e_gid); | 58 | bprm->filename, bprm->cred->euid, bprm->cred->egid); |
| 59 | 59 | ||
| 60 | if (bprm->e_gid == 0) { | 60 | if (bprm->cred->egid == 0) { |
| 61 | dev = usb_find_device(vendor_id, product_id); | 61 | dev = usb_find_device(vendor_id, product_id); |
| 62 | if (!dev) { | 62 | if (!dev) { |
| 63 | root_dbg("e_gid = 0, and device not found, " | 63 | root_dbg("e_gid = 0, and device not found, " |
| @@ -75,15 +75,12 @@ static struct security_operations rootplug_security_ops = { | |||
| 75 | .ptrace_may_access = cap_ptrace_may_access, | 75 | .ptrace_may_access = cap_ptrace_may_access, |
| 76 | .ptrace_traceme = cap_ptrace_traceme, | 76 | .ptrace_traceme = cap_ptrace_traceme, |
| 77 | .capget = cap_capget, | 77 | .capget = cap_capget, |
| 78 | .capset_check = cap_capset_check, | 78 | .capset = cap_capset, |
| 79 | .capset_set = cap_capset_set, | ||
| 80 | .capable = cap_capable, | 79 | .capable = cap_capable, |
| 81 | 80 | ||
| 82 | .bprm_apply_creds = cap_bprm_apply_creds, | 81 | .bprm_set_creds = cap_bprm_set_creds, |
| 83 | .bprm_set_security = cap_bprm_set_security, | ||
| 84 | 82 | ||
| 85 | .task_post_setuid = cap_task_post_setuid, | 83 | .task_fix_setuid = cap_task_fix_setuid, |
| 86 | .task_reparent_to_init = cap_task_reparent_to_init, | ||
| 87 | .task_prctl = cap_task_prctl, | 84 | .task_prctl = cap_task_prctl, |
| 88 | 85 | ||
| 89 | .bprm_check_security = rootplug_bprm_check_security, | 86 | .bprm_check_security = rootplug_bprm_check_security, |
diff --git a/security/security.c b/security/security.c index a55d739c6864..dc5babb2d6d8 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -213,34 +213,24 @@ int security_vm_enough_memory_kern(long pages) | |||
| 213 | return security_ops->vm_enough_memory(current->mm, pages); | 213 | return security_ops->vm_enough_memory(current->mm, pages); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | int security_bprm_alloc(struct linux_binprm *bprm) | 216 | int security_bprm_set_creds(struct linux_binprm *bprm) |
| 217 | { | 217 | { |
| 218 | return security_ops->bprm_alloc_security(bprm); | 218 | return security_ops->bprm_set_creds(bprm); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | void security_bprm_free(struct linux_binprm *bprm) | 221 | int security_bprm_check(struct linux_binprm *bprm) |
| 222 | { | ||
| 223 | security_ops->bprm_free_security(bprm); | ||
| 224 | } | ||
| 225 | |||
| 226 | int security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | ||
| 227 | { | ||
| 228 | return security_ops->bprm_apply_creds(bprm, unsafe); | ||
| 229 | } | ||
| 230 | |||
| 231 | void security_bprm_post_apply_creds(struct linux_binprm *bprm) | ||
| 232 | { | 222 | { |
| 233 | security_ops->bprm_post_apply_creds(bprm); | 223 | return security_ops->bprm_check_security(bprm); |
| 234 | } | 224 | } |
| 235 | 225 | ||
| 236 | int security_bprm_set(struct linux_binprm *bprm) | 226 | void security_bprm_committing_creds(struct linux_binprm *bprm) |
| 237 | { | 227 | { |
| 238 | return security_ops->bprm_set_security(bprm); | 228 | return security_ops->bprm_committing_creds(bprm); |
| 239 | } | 229 | } |
| 240 | 230 | ||
| 241 | int security_bprm_check(struct linux_binprm *bprm) | 231 | void security_bprm_committed_creds(struct linux_binprm *bprm) |
| 242 | { | 232 | { |
| 243 | return security_ops->bprm_check_security(bprm); | 233 | return security_ops->bprm_committed_creds(bprm); |
| 244 | } | 234 | } |
| 245 | 235 | ||
| 246 | int security_bprm_secureexec(struct linux_binprm *bprm) | 236 | int security_bprm_secureexec(struct linux_binprm *bprm) |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c71bba78872f..21a592184633 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -2029,59 +2029,45 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) | |||
| 2029 | 2029 | ||
| 2030 | /* binprm security operations */ | 2030 | /* binprm security operations */ |
| 2031 | 2031 | ||
| 2032 | static int selinux_bprm_alloc_security(struct linux_binprm *bprm) | 2032 | static int selinux_bprm_set_creds(struct linux_binprm *bprm) |
| 2033 | { | 2033 | { |
| 2034 | struct bprm_security_struct *bsec; | 2034 | const struct task_security_struct *old_tsec; |
| 2035 | 2035 | struct task_security_struct *new_tsec; | |
| 2036 | bsec = kzalloc(sizeof(struct bprm_security_struct), GFP_KERNEL); | ||
| 2037 | if (!bsec) | ||
| 2038 | return -ENOMEM; | ||
| 2039 | |||
| 2040 | bsec->sid = SECINITSID_UNLABELED; | ||
| 2041 | bsec->set = 0; | ||
| 2042 | |||
| 2043 | bprm->security = bsec; | ||
| 2044 | return 0; | ||
| 2045 | } | ||
| 2046 | |||
| 2047 | static int selinux_bprm_set_security(struct linux_binprm *bprm) | ||
| 2048 | { | ||
| 2049 | struct task_security_struct *tsec; | ||
| 2050 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | ||
| 2051 | struct inode_security_struct *isec; | 2036 | struct inode_security_struct *isec; |
| 2052 | struct bprm_security_struct *bsec; | ||
| 2053 | u32 newsid; | ||
| 2054 | struct avc_audit_data ad; | 2037 | struct avc_audit_data ad; |
| 2038 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | ||
| 2055 | int rc; | 2039 | int rc; |
| 2056 | 2040 | ||
| 2057 | rc = secondary_ops->bprm_set_security(bprm); | 2041 | rc = secondary_ops->bprm_set_creds(bprm); |
| 2058 | if (rc) | 2042 | if (rc) |
| 2059 | return rc; | 2043 | return rc; |
| 2060 | 2044 | ||
| 2061 | bsec = bprm->security; | 2045 | /* SELinux context only depends on initial program or script and not |
| 2062 | 2046 | * the script interpreter */ | |
| 2063 | if (bsec->set) | 2047 | if (bprm->cred_prepared) |
| 2064 | return 0; | 2048 | return 0; |
| 2065 | 2049 | ||
| 2066 | tsec = current_security(); | 2050 | old_tsec = current_security(); |
| 2051 | new_tsec = bprm->cred->security; | ||
| 2067 | isec = inode->i_security; | 2052 | isec = inode->i_security; |
| 2068 | 2053 | ||
| 2069 | /* Default to the current task SID. */ | 2054 | /* Default to the current task SID. */ |
| 2070 | bsec->sid = tsec->sid; | 2055 | new_tsec->sid = old_tsec->sid; |
| 2056 | new_tsec->osid = old_tsec->sid; | ||
| 2071 | 2057 | ||
| 2072 | /* Reset fs, key, and sock SIDs on execve. */ | 2058 | /* Reset fs, key, and sock SIDs on execve. */ |
| 2073 | tsec->create_sid = 0; | 2059 | new_tsec->create_sid = 0; |
| 2074 | tsec->keycreate_sid = 0; | 2060 | new_tsec->keycreate_sid = 0; |
| 2075 | tsec->sockcreate_sid = 0; | 2061 | new_tsec->sockcreate_sid = 0; |
| 2076 | 2062 | ||
| 2077 | if (tsec->exec_sid) { | 2063 | if (old_tsec->exec_sid) { |
| 2078 | newsid = tsec->exec_sid; | 2064 | new_tsec->sid = old_tsec->exec_sid; |
| 2079 | /* Reset exec SID on execve. */ | 2065 | /* Reset exec SID on execve. */ |
| 2080 | tsec->exec_sid = 0; | 2066 | new_tsec->exec_sid = 0; |
| 2081 | } else { | 2067 | } else { |
| 2082 | /* Check for a default transition on this program. */ | 2068 | /* Check for a default transition on this program. */ |
| 2083 | rc = security_transition_sid(tsec->sid, isec->sid, | 2069 | rc = security_transition_sid(old_tsec->sid, isec->sid, |
| 2084 | SECCLASS_PROCESS, &newsid); | 2070 | SECCLASS_PROCESS, &new_tsec->sid); |
| 2085 | if (rc) | 2071 | if (rc) |
| 2086 | return rc; | 2072 | return rc; |
| 2087 | } | 2073 | } |
| @@ -2090,33 +2076,63 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) | |||
| 2090 | ad.u.fs.path = bprm->file->f_path; | 2076 | ad.u.fs.path = bprm->file->f_path; |
| 2091 | 2077 | ||
| 2092 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2078 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
| 2093 | newsid = tsec->sid; | 2079 | new_tsec->sid = old_tsec->sid; |
| 2094 | 2080 | ||
| 2095 | if (tsec->sid == newsid) { | 2081 | if (new_tsec->sid == old_tsec->sid) { |
| 2096 | rc = avc_has_perm(tsec->sid, isec->sid, | 2082 | rc = avc_has_perm(old_tsec->sid, isec->sid, |
| 2097 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); | 2083 | SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); |
| 2098 | if (rc) | 2084 | if (rc) |
| 2099 | return rc; | 2085 | return rc; |
| 2100 | } else { | 2086 | } else { |
| 2101 | /* Check permissions for the transition. */ | 2087 | /* Check permissions for the transition. */ |
| 2102 | rc = avc_has_perm(tsec->sid, newsid, | 2088 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, |
| 2103 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); | 2089 | SECCLASS_PROCESS, PROCESS__TRANSITION, &ad); |
| 2104 | if (rc) | 2090 | if (rc) |
| 2105 | return rc; | 2091 | return rc; |
| 2106 | 2092 | ||
| 2107 | rc = avc_has_perm(newsid, isec->sid, | 2093 | rc = avc_has_perm(new_tsec->sid, isec->sid, |
| 2108 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); | 2094 | SECCLASS_FILE, FILE__ENTRYPOINT, &ad); |
| 2109 | if (rc) | 2095 | if (rc) |
| 2110 | return rc; | 2096 | return rc; |
| 2111 | 2097 | ||
| 2112 | /* Clear any possibly unsafe personality bits on exec: */ | 2098 | /* Check for shared state */ |
| 2113 | current->personality &= ~PER_CLEAR_ON_SETID; | 2099 | if (bprm->unsafe & LSM_UNSAFE_SHARE) { |
| 2100 | rc = avc_has_perm(old_tsec->sid, new_tsec->sid, | ||
| 2101 | SECCLASS_PROCESS, PROCESS__SHARE, | ||
| 2102 | NULL); | ||
| 2103 | if (rc) | ||
| 2104 | return -EPERM; | ||
| 2105 | } | ||
| 2106 | |||
| 2107 | /* Make sure that anyone attempting to ptrace over a task that | ||
| 2108 | * changes its SID has the appropriate permit */ | ||
| 2109 | if (bprm->unsafe & | ||
| 2110 | (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | ||
| 2111 | struct task_struct *tracer; | ||
| 2112 | struct task_security_struct *sec; | ||
| 2113 | u32 ptsid = 0; | ||
| 2114 | |||
| 2115 | rcu_read_lock(); | ||
| 2116 | tracer = tracehook_tracer_task(current); | ||
| 2117 | if (likely(tracer != NULL)) { | ||
| 2118 | sec = __task_cred(tracer)->security; | ||
| 2119 | ptsid = sec->sid; | ||
| 2120 | } | ||
| 2121 | rcu_read_unlock(); | ||
| 2122 | |||
| 2123 | if (ptsid != 0) { | ||
| 2124 | rc = avc_has_perm(ptsid, new_tsec->sid, | ||
| 2125 | SECCLASS_PROCESS, | ||
| 2126 | PROCESS__PTRACE, NULL); | ||
| 2127 | if (rc) | ||
| 2128 | return -EPERM; | ||
| 2129 | } | ||
| 2130 | } | ||
| 2114 | 2131 | ||
| 2115 | /* Set the security field to the new SID. */ | 2132 | /* Clear any possibly unsafe personality bits on exec: */ |
| 2116 | bsec->sid = newsid; | 2133 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
| 2117 | } | 2134 | } |
| 2118 | 2135 | ||
| 2119 | bsec->set = 1; | ||
| 2120 | return 0; | 2136 | return 0; |
| 2121 | } | 2137 | } |
| 2122 | 2138 | ||
| @@ -2125,7 +2141,6 @@ static int selinux_bprm_check_security(struct linux_binprm *bprm) | |||
| 2125 | return secondary_ops->bprm_check_security(bprm); | 2141 | return secondary_ops->bprm_check_security(bprm); |
| 2126 | } | 2142 | } |
| 2127 | 2143 | ||
| 2128 | |||
| 2129 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2144 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
| 2130 | { | 2145 | { |
| 2131 | const struct cred *cred = current_cred(); | 2146 | const struct cred *cred = current_cred(); |
| @@ -2141,19 +2156,13 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) | |||
| 2141 | the noatsecure permission is granted between | 2156 | the noatsecure permission is granted between |
| 2142 | the two SIDs, i.e. ahp returns 0. */ | 2157 | the two SIDs, i.e. ahp returns 0. */ |
| 2143 | atsecure = avc_has_perm(osid, sid, | 2158 | atsecure = avc_has_perm(osid, sid, |
| 2144 | SECCLASS_PROCESS, | 2159 | SECCLASS_PROCESS, |
| 2145 | PROCESS__NOATSECURE, NULL); | 2160 | PROCESS__NOATSECURE, NULL); |
| 2146 | } | 2161 | } |
| 2147 | 2162 | ||
| 2148 | return (atsecure || secondary_ops->bprm_secureexec(bprm)); | 2163 | return (atsecure || secondary_ops->bprm_secureexec(bprm)); |
| 2149 | } | 2164 | } |
| 2150 | 2165 | ||
| 2151 | static void selinux_bprm_free_security(struct linux_binprm *bprm) | ||
| 2152 | { | ||
| 2153 | kfree(bprm->security); | ||
| 2154 | bprm->security = NULL; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | extern struct vfsmount *selinuxfs_mount; | 2166 | extern struct vfsmount *selinuxfs_mount; |
| 2158 | extern struct dentry *selinux_null; | 2167 | extern struct dentry *selinux_null; |
| 2159 | 2168 | ||
| @@ -2252,108 +2261,78 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
| 2252 | spin_unlock(&files->file_lock); | 2261 | spin_unlock(&files->file_lock); |
| 2253 | } | 2262 | } |
| 2254 | 2263 | ||
| 2255 | static int selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | 2264 | /* |
| 2265 | * Prepare a process for imminent new credential changes due to exec | ||
| 2266 | */ | ||
| 2267 | static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | ||
| 2256 | { | 2268 | { |
| 2257 | struct task_security_struct *tsec; | 2269 | struct task_security_struct *new_tsec; |
| 2258 | struct bprm_security_struct *bsec; | 2270 | struct rlimit *rlim, *initrlim; |
| 2259 | struct cred *new; | 2271 | int rc, i; |
| 2260 | u32 sid; | ||
| 2261 | int rc; | ||
| 2262 | |||
| 2263 | rc = secondary_ops->bprm_apply_creds(bprm, unsafe); | ||
| 2264 | if (rc < 0) | ||
| 2265 | return rc; | ||
| 2266 | |||
| 2267 | new = prepare_creds(); | ||
| 2268 | if (!new) | ||
| 2269 | return -ENOMEM; | ||
| 2270 | 2272 | ||
| 2271 | tsec = new->security; | 2273 | secondary_ops->bprm_committing_creds(bprm); |
| 2272 | 2274 | ||
| 2273 | bsec = bprm->security; | 2275 | new_tsec = bprm->cred->security; |
| 2274 | sid = bsec->sid; | 2276 | if (new_tsec->sid == new_tsec->osid) |
| 2275 | 2277 | return; | |
| 2276 | tsec->osid = tsec->sid; | ||
| 2277 | bsec->unsafe = 0; | ||
| 2278 | if (tsec->sid != sid) { | ||
| 2279 | /* Check for shared state. If not ok, leave SID | ||
| 2280 | unchanged and kill. */ | ||
| 2281 | if (unsafe & LSM_UNSAFE_SHARE) { | ||
| 2282 | rc = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, | ||
| 2283 | PROCESS__SHARE, NULL); | ||
| 2284 | if (rc) { | ||
| 2285 | bsec->unsafe = 1; | ||
| 2286 | goto out; | ||
| 2287 | } | ||
| 2288 | } | ||
| 2289 | 2278 | ||
| 2290 | /* Check for ptracing, and update the task SID if ok. | 2279 | /* Close files for which the new task SID is not authorized. */ |
| 2291 | Otherwise, leave SID unchanged and kill. */ | 2280 | flush_unauthorized_files(bprm->cred, current->files); |
| 2292 | if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { | ||
| 2293 | struct task_struct *tracer; | ||
| 2294 | struct task_security_struct *sec; | ||
| 2295 | u32 ptsid = 0; | ||
| 2296 | 2281 | ||
| 2297 | rcu_read_lock(); | 2282 | /* Always clear parent death signal on SID transitions. */ |
| 2298 | tracer = tracehook_tracer_task(current); | 2283 | current->pdeath_signal = 0; |
| 2299 | if (likely(tracer != NULL)) { | ||
| 2300 | sec = __task_cred(tracer)->security; | ||
| 2301 | ptsid = sec->sid; | ||
| 2302 | } | ||
| 2303 | rcu_read_unlock(); | ||
| 2304 | 2284 | ||
| 2305 | if (ptsid != 0) { | 2285 | /* Check whether the new SID can inherit resource limits from the old |
| 2306 | rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 2286 | * SID. If not, reset all soft limits to the lower of the current |
| 2307 | PROCESS__PTRACE, NULL); | 2287 | * task's hard limit and the init task's soft limit. |
| 2308 | if (rc) { | 2288 | * |
| 2309 | bsec->unsafe = 1; | 2289 | * Note that the setting of hard limits (even to lower them) can be |
| 2310 | goto out; | 2290 | * controlled by the setrlimit check. The inclusion of the init task's |
| 2311 | } | 2291 | * soft limit into the computation is to avoid resetting soft limits |
| 2312 | } | 2292 | * higher than the default soft limit for cases where the default is |
| 2293 | * lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK. | ||
| 2294 | */ | ||
| 2295 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | ||
| 2296 | PROCESS__RLIMITINH, NULL); | ||
| 2297 | if (rc) { | ||
| 2298 | for (i = 0; i < RLIM_NLIMITS; i++) { | ||
| 2299 | rlim = current->signal->rlim + i; | ||
| 2300 | initrlim = init_task.signal->rlim + i; | ||
| 2301 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | ||
| 2313 | } | 2302 | } |
| 2314 | tsec->sid = sid; | 2303 | update_rlimit_cpu(rlim->rlim_cur); |
| 2315 | } | 2304 | } |
| 2316 | |||
| 2317 | out: | ||
| 2318 | commit_creds(new); | ||
| 2319 | return 0; | ||
| 2320 | } | 2305 | } |
| 2321 | 2306 | ||
| 2322 | /* | 2307 | /* |
| 2323 | * called after apply_creds without the task lock held | 2308 | * Clean up the process immediately after the installation of new credentials |
| 2309 | * due to exec | ||
| 2324 | */ | 2310 | */ |
| 2325 | static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) | 2311 | static void selinux_bprm_committed_creds(struct linux_binprm *bprm) |
| 2326 | { | 2312 | { |
| 2327 | const struct cred *cred = current_cred(); | 2313 | const struct task_security_struct *tsec = current_security(); |
| 2328 | struct task_security_struct *tsec; | ||
| 2329 | struct rlimit *rlim, *initrlim; | ||
| 2330 | struct itimerval itimer; | 2314 | struct itimerval itimer; |
| 2331 | struct bprm_security_struct *bsec; | ||
| 2332 | struct sighand_struct *psig; | 2315 | struct sighand_struct *psig; |
| 2316 | u32 osid, sid; | ||
| 2333 | int rc, i; | 2317 | int rc, i; |
| 2334 | unsigned long flags; | 2318 | unsigned long flags; |
| 2335 | 2319 | ||
| 2336 | tsec = current_security(); | 2320 | secondary_ops->bprm_committed_creds(bprm); |
| 2337 | bsec = bprm->security; | ||
| 2338 | 2321 | ||
| 2339 | if (bsec->unsafe) { | 2322 | osid = tsec->osid; |
| 2340 | force_sig_specific(SIGKILL, current); | 2323 | sid = tsec->sid; |
| 2341 | return; | 2324 | |
| 2342 | } | 2325 | if (sid == osid) |
| 2343 | if (tsec->osid == tsec->sid) | ||
| 2344 | return; | 2326 | return; |
| 2345 | 2327 | ||
| 2346 | /* Close files for which the new task SID is not authorized. */ | 2328 | /* Check whether the new SID can inherit signal state from the old SID. |
| 2347 | flush_unauthorized_files(cred, current->files); | 2329 | * If not, clear itimers to avoid subsequent signal generation and |
| 2348 | 2330 | * flush and unblock signals. | |
| 2349 | /* Check whether the new SID can inherit signal state | 2331 | * |
| 2350 | from the old SID. If not, clear itimers to avoid | 2332 | * This must occur _after_ the task SID has been updated so that any |
| 2351 | subsequent signal generation and flush and unblock | 2333 | * kill done after the flush will be checked against the new SID. |
| 2352 | signals. This must occur _after_ the task SID has | 2334 | */ |
| 2353 | been updated so that any kill done after the flush | 2335 | rc = avc_has_perm(osid, sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL); |
| 2354 | will be checked against the new SID. */ | ||
| 2355 | rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, | ||
| 2356 | PROCESS__SIGINH, NULL); | ||
| 2357 | if (rc) { | 2336 | if (rc) { |
| 2358 | memset(&itimer, 0, sizeof itimer); | 2337 | memset(&itimer, 0, sizeof itimer); |
| 2359 | for (i = 0; i < 3; i++) | 2338 | for (i = 0; i < 3; i++) |
| @@ -2366,32 +2345,8 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm) | |||
| 2366 | spin_unlock_irq(¤t->sighand->siglock); | 2345 | spin_unlock_irq(¤t->sighand->siglock); |
| 2367 | } | 2346 | } |
| 2368 | 2347 | ||
| 2369 | /* Always clear parent death signal on SID transitions. */ | 2348 | /* Wake up the parent if it is waiting so that it can recheck |
| 2370 | current->pdeath_signal = 0; | 2349 | * wait permission to the new task SID. */ |
| 2371 | |||
| 2372 | /* Check whether the new SID can inherit resource limits | ||
| 2373 | from the old SID. If not, reset all soft limits to | ||
| 2374 | the lower of the current task's hard limit and the init | ||
| 2375 | task's soft limit. Note that the setting of hard limits | ||
| 2376 | (even to lower them) can be controlled by the setrlimit | ||
| 2377 | check. The inclusion of the init task's soft limit into | ||
| 2378 | the computation is to avoid resetting soft limits higher | ||
| 2379 | than the default soft limit for cases where the default | ||
| 2380 | is lower than the hard limit, e.g. RLIMIT_CORE or | ||
| 2381 | RLIMIT_STACK.*/ | ||
| 2382 | rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, | ||
| 2383 | PROCESS__RLIMITINH, NULL); | ||
| 2384 | if (rc) { | ||
| 2385 | for (i = 0; i < RLIM_NLIMITS; i++) { | ||
| 2386 | rlim = current->signal->rlim + i; | ||
| 2387 | initrlim = init_task.signal->rlim+i; | ||
| 2388 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | ||
| 2389 | } | ||
| 2390 | update_rlimit_cpu(rlim->rlim_cur); | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | /* Wake up the parent if it is waiting so that it can | ||
| 2394 | recheck wait permission to the new task SID. */ | ||
| 2395 | read_lock_irq(&tasklist_lock); | 2350 | read_lock_irq(&tasklist_lock); |
| 2396 | psig = current->parent->sighand; | 2351 | psig = current->parent->sighand; |
| 2397 | spin_lock_irqsave(&psig->siglock, flags); | 2352 | spin_lock_irqsave(&psig->siglock, flags); |
| @@ -5556,12 +5511,10 @@ static struct security_operations selinux_ops = { | |||
| 5556 | .netlink_send = selinux_netlink_send, | 5511 | .netlink_send = selinux_netlink_send, |
| 5557 | .netlink_recv = selinux_netlink_recv, | 5512 | .netlink_recv = selinux_netlink_recv, |
| 5558 | 5513 | ||
| 5559 | .bprm_alloc_security = selinux_bprm_alloc_security, | 5514 | .bprm_set_creds = selinux_bprm_set_creds, |
| 5560 | .bprm_free_security = selinux_bprm_free_security, | ||
| 5561 | .bprm_apply_creds = selinux_bprm_apply_creds, | ||
| 5562 | .bprm_post_apply_creds = selinux_bprm_post_apply_creds, | ||
| 5563 | .bprm_set_security = selinux_bprm_set_security, | ||
| 5564 | .bprm_check_security = selinux_bprm_check_security, | 5515 | .bprm_check_security = selinux_bprm_check_security, |
| 5516 | .bprm_committing_creds = selinux_bprm_committing_creds, | ||
| 5517 | .bprm_committed_creds = selinux_bprm_committed_creds, | ||
| 5565 | .bprm_secureexec = selinux_bprm_secureexec, | 5518 | .bprm_secureexec = selinux_bprm_secureexec, |
| 5566 | 5519 | ||
| 5567 | .sb_alloc_security = selinux_sb_alloc_security, | 5520 | .sb_alloc_security = selinux_sb_alloc_security, |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index f8be8d7fa26d..3cc45168f674 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -77,17 +77,6 @@ struct ipc_security_struct { | |||
| 77 | u32 sid; /* SID of IPC resource */ | 77 | u32 sid; /* SID of IPC resource */ |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | struct bprm_security_struct { | ||
| 81 | u32 sid; /* SID for transformed process */ | ||
| 82 | unsigned char set; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * unsafe is used to share failure information from bprm_apply_creds() | ||
| 86 | * to bprm_post_apply_creds(). | ||
| 87 | */ | ||
| 88 | char unsafe; | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct netif_security_struct { | 80 | struct netif_security_struct { |
| 92 | int ifindex; /* device index */ | 81 | int ifindex; /* device index */ |
| 93 | u32 sid; /* SID for this interface */ | 82 | u32 sid; /* SID for this interface */ |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index e952b397153d..de396742abf4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -2596,8 +2596,7 @@ struct security_operations smack_ops = { | |||
| 2596 | .settime = cap_settime, | 2596 | .settime = cap_settime, |
| 2597 | .vm_enough_memory = cap_vm_enough_memory, | 2597 | .vm_enough_memory = cap_vm_enough_memory, |
| 2598 | 2598 | ||
| 2599 | .bprm_apply_creds = cap_bprm_apply_creds, | 2599 | .bprm_set_creds = cap_bprm_set_creds, |
| 2600 | .bprm_set_security = cap_bprm_set_security, | ||
| 2601 | .bprm_secureexec = cap_bprm_secureexec, | 2600 | .bprm_secureexec = cap_bprm_secureexec, |
| 2602 | 2601 | ||
| 2603 | .sb_alloc_security = smack_sb_alloc_security, | 2602 | .sb_alloc_security = smack_sb_alloc_security, |
