diff options
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 2 | ||||
-rw-r--r-- | fs/binfmt_aout.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 2 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 2 | ||||
-rw-r--r-- | fs/binfmt_flat.c | 2 | ||||
-rw-r--r-- | fs/binfmt_som.c | 2 | ||||
-rw-r--r-- | fs/compat.c | 42 | ||||
-rw-r--r-- | fs/exec.c | 149 | ||||
-rw-r--r-- | fs/internal.h | 6 | ||||
-rw-r--r-- | include/linux/audit.h | 16 | ||||
-rw-r--r-- | include/linux/binfmts.h | 16 | ||||
-rw-r--r-- | include/linux/cred.h | 3 | ||||
-rw-r--r-- | include/linux/key.h | 2 | ||||
-rw-r--r-- | include/linux/security.h | 103 | ||||
-rw-r--r-- | kernel/cred.c | 46 | ||||
-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 |
23 files changed, 429 insertions, 515 deletions
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 127ec3f07214..2a4d073d2cf1 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -327,7 +327,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
327 | current->mm->cached_hole_size = 0; | 327 | current->mm->cached_hole_size = 0; |
328 | 328 | ||
329 | current->mm->mmap = NULL; | 329 | current->mm->mmap = NULL; |
330 | compute_creds(bprm); | 330 | install_exec_creds(bprm); |
331 | current->flags &= ~PF_FORKNOEXEC; | 331 | current->flags &= ~PF_FORKNOEXEC; |
332 | 332 | ||
333 | if (N_MAGIC(ex) == OMAGIC) { | 333 | if (N_MAGIC(ex) == OMAGIC) { |
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c index 204cfd1d7676..f1f3f4192a60 100644 --- a/fs/binfmt_aout.c +++ b/fs/binfmt_aout.c | |||
@@ -320,7 +320,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
320 | current->mm->free_area_cache = current->mm->mmap_base; | 320 | current->mm->free_area_cache = current->mm->mmap_base; |
321 | current->mm->cached_hole_size = 0; | 321 | current->mm->cached_hole_size = 0; |
322 | 322 | ||
323 | compute_creds(bprm); | 323 | install_exec_creds(bprm); |
324 | current->flags &= ~PF_FORKNOEXEC; | 324 | current->flags &= ~PF_FORKNOEXEC; |
325 | #ifdef __sparc__ | 325 | #ifdef __sparc__ |
326 | if (N_MAGIC(ex) == NMAGIC) { | 326 | if (N_MAGIC(ex) == NMAGIC) { |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 9142ff5dc8e6..f458c1217c5e 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -956,7 +956,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
956 | } | 956 | } |
957 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ | 957 | #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ |
958 | 958 | ||
959 | compute_creds(bprm); | 959 | install_exec_creds(bprm); |
960 | current->flags &= ~PF_FORKNOEXEC; | 960 | current->flags &= ~PF_FORKNOEXEC; |
961 | retval = create_elf_tables(bprm, &loc->elf_ex, | 961 | retval = create_elf_tables(bprm, &loc->elf_ex, |
962 | load_addr, interp_load_addr); | 962 | load_addr, interp_load_addr); |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 45dabd59936f..aa5b43205e37 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -404,7 +404,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, | |||
404 | current->mm->start_stack = current->mm->start_brk + stack_size; | 404 | current->mm->start_stack = current->mm->start_brk + stack_size; |
405 | #endif | 405 | #endif |
406 | 406 | ||
407 | compute_creds(bprm); | 407 | install_exec_creds(bprm); |
408 | current->flags &= ~PF_FORKNOEXEC; | 408 | current->flags &= ~PF_FORKNOEXEC; |
409 | if (create_elf_fdpic_tables(bprm, current->mm, | 409 | if (create_elf_fdpic_tables(bprm, current->mm, |
410 | &exec_params, &interp_params) < 0) | 410 | &exec_params, &interp_params) < 0) |
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index ccb781a6a804..7bbd5c6b3725 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -880,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
880 | (libinfo.lib_list[j].loaded)? | 880 | (libinfo.lib_list[j].loaded)? |
881 | libinfo.lib_list[j].start_data:UNLOADED_LIB; | 881 | libinfo.lib_list[j].start_data:UNLOADED_LIB; |
882 | 882 | ||
883 | compute_creds(bprm); | 883 | install_exec_creds(bprm); |
884 | current->flags &= ~PF_FORKNOEXEC; | 884 | current->flags &= ~PF_FORKNOEXEC; |
885 | 885 | ||
886 | set_binfmt(&flat_format); | 886 | set_binfmt(&flat_format); |
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index 74e587a52796..08644a61616e 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c | |||
@@ -255,7 +255,7 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
255 | kfree(hpuxhdr); | 255 | kfree(hpuxhdr); |
256 | 256 | ||
257 | set_binfmt(&som_format); | 257 | set_binfmt(&som_format); |
258 | compute_creds(bprm); | 258 | install_exec_creds(bprm); |
259 | setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); | 259 | setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); |
260 | 260 | ||
261 | create_som_tables(bprm); | 261 | create_som_tables(bprm); |
diff --git a/fs/compat.c b/fs/compat.c index e5f49f538502..d1ece79b6411 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -1393,10 +1393,20 @@ int compat_do_execve(char * filename, | |||
1393 | if (!bprm) | 1393 | if (!bprm) |
1394 | goto out_ret; | 1394 | goto out_ret; |
1395 | 1395 | ||
1396 | retval = mutex_lock_interruptible(¤t->cred_exec_mutex); | ||
1397 | if (retval < 0) | ||
1398 | goto out_free; | ||
1399 | |||
1400 | retval = -ENOMEM; | ||
1401 | bprm->cred = prepare_exec_creds(); | ||
1402 | if (!bprm->cred) | ||
1403 | goto out_unlock; | ||
1404 | check_unsafe_exec(bprm); | ||
1405 | |||
1396 | file = open_exec(filename); | 1406 | file = open_exec(filename); |
1397 | retval = PTR_ERR(file); | 1407 | retval = PTR_ERR(file); |
1398 | if (IS_ERR(file)) | 1408 | if (IS_ERR(file)) |
1399 | goto out_kfree; | 1409 | goto out_unlock; |
1400 | 1410 | ||
1401 | sched_exec(); | 1411 | sched_exec(); |
1402 | 1412 | ||
@@ -1410,14 +1420,10 @@ int compat_do_execve(char * filename, | |||
1410 | 1420 | ||
1411 | bprm->argc = compat_count(argv, MAX_ARG_STRINGS); | 1421 | bprm->argc = compat_count(argv, MAX_ARG_STRINGS); |
1412 | if ((retval = bprm->argc) < 0) | 1422 | if ((retval = bprm->argc) < 0) |
1413 | goto out_mm; | 1423 | goto out; |
1414 | 1424 | ||
1415 | bprm->envc = compat_count(envp, MAX_ARG_STRINGS); | 1425 | bprm->envc = compat_count(envp, MAX_ARG_STRINGS); |
1416 | if ((retval = bprm->envc) < 0) | 1426 | if ((retval = bprm->envc) < 0) |
1417 | goto out_mm; | ||
1418 | |||
1419 | retval = security_bprm_alloc(bprm); | ||
1420 | if (retval) | ||
1421 | goto out; | 1427 | goto out; |
1422 | 1428 | ||
1423 | retval = prepare_binprm(bprm); | 1429 | retval = prepare_binprm(bprm); |
@@ -1438,19 +1444,16 @@ int compat_do_execve(char * filename, | |||
1438 | goto out; | 1444 | goto out; |
1439 | 1445 | ||
1440 | retval = search_binary_handler(bprm, regs); | 1446 | retval = search_binary_handler(bprm, regs); |
1441 | if (retval >= 0) { | 1447 | if (retval < 0) |
1442 | /* execve success */ | 1448 | goto out; |
1443 | security_bprm_free(bprm); | ||
1444 | acct_update_integrals(current); | ||
1445 | free_bprm(bprm); | ||
1446 | return retval; | ||
1447 | } | ||
1448 | 1449 | ||
1449 | out: | 1450 | /* execve succeeded */ |
1450 | if (bprm->security) | 1451 | mutex_unlock(¤t->cred_exec_mutex); |
1451 | security_bprm_free(bprm); | 1452 | acct_update_integrals(current); |
1453 | free_bprm(bprm); | ||
1454 | return retval; | ||
1452 | 1455 | ||
1453 | out_mm: | 1456 | out: |
1454 | if (bprm->mm) | 1457 | if (bprm->mm) |
1455 | mmput(bprm->mm); | 1458 | mmput(bprm->mm); |
1456 | 1459 | ||
@@ -1460,7 +1463,10 @@ out_file: | |||
1460 | fput(bprm->file); | 1463 | fput(bprm->file); |
1461 | } | 1464 | } |
1462 | 1465 | ||
1463 | out_kfree: | 1466 | out_unlock: |
1467 | mutex_unlock(¤t->cred_exec_mutex); | ||
1468 | |||
1469 | out_free: | ||
1464 | free_bprm(bprm); | 1470 | free_bprm(bprm); |
1465 | 1471 | ||
1466 | out_ret: | 1472 | out_ret: |
@@ -55,6 +55,7 @@ | |||
55 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
56 | #include <asm/mmu_context.h> | 56 | #include <asm/mmu_context.h> |
57 | #include <asm/tlb.h> | 57 | #include <asm/tlb.h> |
58 | #include "internal.h" | ||
58 | 59 | ||
59 | #ifdef __alpha__ | 60 | #ifdef __alpha__ |
60 | /* for /sbin/loader handling in search_binary_handler() */ | 61 | /* for /sbin/loader handling in search_binary_handler() */ |
@@ -1007,15 +1008,17 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1007 | */ | 1008 | */ |
1008 | current->mm->task_size = TASK_SIZE; | 1009 | current->mm->task_size = TASK_SIZE; |
1009 | 1010 | ||
1010 | if (bprm->e_uid != current_euid() || | 1011 | /* install the new credentials */ |
1011 | bprm->e_gid != current_egid()) { | 1012 | if (bprm->cred->uid != current_euid() || |
1012 | set_dumpable(current->mm, suid_dumpable); | 1013 | bprm->cred->gid != current_egid()) { |
1013 | current->pdeath_signal = 0; | 1014 | current->pdeath_signal = 0; |
1014 | } else if (file_permission(bprm->file, MAY_READ) || | 1015 | } else if (file_permission(bprm->file, MAY_READ) || |
1015 | (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { | 1016 | bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP) { |
1016 | set_dumpable(current->mm, suid_dumpable); | 1017 | set_dumpable(current->mm, suid_dumpable); |
1017 | } | 1018 | } |
1018 | 1019 | ||
1020 | current->personality &= ~bprm->per_clear; | ||
1021 | |||
1019 | /* An exec changes our domain. We are no longer part of the thread | 1022 | /* An exec changes our domain. We are no longer part of the thread |
1020 | group */ | 1023 | group */ |
1021 | 1024 | ||
@@ -1032,13 +1035,50 @@ out: | |||
1032 | 1035 | ||
1033 | EXPORT_SYMBOL(flush_old_exec); | 1036 | EXPORT_SYMBOL(flush_old_exec); |
1034 | 1037 | ||
1038 | /* | ||
1039 | * install the new credentials for this executable | ||
1040 | */ | ||
1041 | void install_exec_creds(struct linux_binprm *bprm) | ||
1042 | { | ||
1043 | security_bprm_committing_creds(bprm); | ||
1044 | |||
1045 | commit_creds(bprm->cred); | ||
1046 | bprm->cred = NULL; | ||
1047 | |||
1048 | /* cred_exec_mutex must be held at least to this point to prevent | ||
1049 | * ptrace_attach() from altering our determination of the task's | ||
1050 | * credentials; any time after this it may be unlocked */ | ||
1051 | |||
1052 | security_bprm_committed_creds(bprm); | ||
1053 | } | ||
1054 | EXPORT_SYMBOL(install_exec_creds); | ||
1055 | |||
1056 | /* | ||
1057 | * determine how safe it is to execute the proposed program | ||
1058 | * - the caller must hold current->cred_exec_mutex to protect against | ||
1059 | * PTRACE_ATTACH | ||
1060 | */ | ||
1061 | void check_unsafe_exec(struct linux_binprm *bprm) | ||
1062 | { | ||
1063 | struct task_struct *p = current; | ||
1064 | |||
1065 | bprm->unsafe = tracehook_unsafe_exec(p); | ||
1066 | |||
1067 | if (atomic_read(&p->fs->count) > 1 || | ||
1068 | atomic_read(&p->files->count) > 1 || | ||
1069 | atomic_read(&p->sighand->count) > 1) | ||
1070 | bprm->unsafe |= LSM_UNSAFE_SHARE; | ||
1071 | } | ||
1072 | |||
1035 | /* | 1073 | /* |
1036 | * Fill the binprm structure from the inode. | 1074 | * Fill the binprm structure from the inode. |
1037 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes | 1075 | * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes |
1076 | * | ||
1077 | * This may be called multiple times for binary chains (scripts for example). | ||
1038 | */ | 1078 | */ |
1039 | int prepare_binprm(struct linux_binprm *bprm) | 1079 | int prepare_binprm(struct linux_binprm *bprm) |
1040 | { | 1080 | { |
1041 | int mode; | 1081 | umode_t mode; |
1042 | struct inode * inode = bprm->file->f_path.dentry->d_inode; | 1082 | struct inode * inode = bprm->file->f_path.dentry->d_inode; |
1043 | int retval; | 1083 | int retval; |
1044 | 1084 | ||
@@ -1046,14 +1086,15 @@ int prepare_binprm(struct linux_binprm *bprm) | |||
1046 | if (bprm->file->f_op == NULL) | 1086 | if (bprm->file->f_op == NULL) |
1047 | return -EACCES; | 1087 | return -EACCES; |
1048 | 1088 | ||
1049 | bprm->e_uid = current_euid(); | 1089 | /* clear any previous set[ug]id data from a previous binary */ |
1050 | bprm->e_gid = current_egid(); | 1090 | bprm->cred->euid = current_euid(); |
1091 | bprm->cred->egid = current_egid(); | ||
1051 | 1092 | ||
1052 | if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { | 1093 | if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) { |
1053 | /* Set-uid? */ | 1094 | /* Set-uid? */ |
1054 | if (mode & S_ISUID) { | 1095 | if (mode & S_ISUID) { |
1055 | current->personality &= ~PER_CLEAR_ON_SETID; | 1096 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
1056 | bprm->e_uid = inode->i_uid; | 1097 | bprm->cred->euid = inode->i_uid; |
1057 | } | 1098 | } |
1058 | 1099 | ||
1059 | /* Set-gid? */ | 1100 | /* Set-gid? */ |
@@ -1063,50 +1104,23 @@ int prepare_binprm(struct linux_binprm *bprm) | |||
1063 | * executable. | 1104 | * executable. |
1064 | */ | 1105 | */ |
1065 | if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { | 1106 | if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { |
1066 | current->personality &= ~PER_CLEAR_ON_SETID; | 1107 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
1067 | bprm->e_gid = inode->i_gid; | 1108 | bprm->cred->egid = inode->i_gid; |
1068 | } | 1109 | } |
1069 | } | 1110 | } |
1070 | 1111 | ||
1071 | /* fill in binprm security blob */ | 1112 | /* fill in binprm security blob */ |
1072 | retval = security_bprm_set(bprm); | 1113 | retval = security_bprm_set_creds(bprm); |
1073 | if (retval) | 1114 | if (retval) |
1074 | return retval; | 1115 | return retval; |
1116 | bprm->cred_prepared = 1; | ||
1075 | 1117 | ||
1076 | memset(bprm->buf,0,BINPRM_BUF_SIZE); | 1118 | memset(bprm->buf, 0, BINPRM_BUF_SIZE); |
1077 | return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); | 1119 | return kernel_read(bprm->file, 0, bprm->buf, BINPRM_BUF_SIZE); |
1078 | } | 1120 | } |
1079 | 1121 | ||
1080 | EXPORT_SYMBOL(prepare_binprm); | 1122 | EXPORT_SYMBOL(prepare_binprm); |
1081 | 1123 | ||
1082 | static int unsafe_exec(struct task_struct *p) | ||
1083 | { | ||
1084 | int unsafe = tracehook_unsafe_exec(p); | ||
1085 | |||
1086 | if (atomic_read(&p->fs->count) > 1 || | ||
1087 | atomic_read(&p->files->count) > 1 || | ||
1088 | atomic_read(&p->sighand->count) > 1) | ||
1089 | unsafe |= LSM_UNSAFE_SHARE; | ||
1090 | |||
1091 | return unsafe; | ||
1092 | } | ||
1093 | |||
1094 | void compute_creds(struct linux_binprm *bprm) | ||
1095 | { | ||
1096 | int unsafe; | ||
1097 | |||
1098 | if (bprm->e_uid != current_uid()) | ||
1099 | current->pdeath_signal = 0; | ||
1100 | exec_keys(current); | ||
1101 | |||
1102 | task_lock(current); | ||
1103 | unsafe = unsafe_exec(current); | ||
1104 | security_bprm_apply_creds(bprm, unsafe); | ||
1105 | task_unlock(current); | ||
1106 | security_bprm_post_apply_creds(bprm); | ||
1107 | } | ||
1108 | EXPORT_SYMBOL(compute_creds); | ||
1109 | |||
1110 | /* | 1124 | /* |
1111 | * Arguments are '\0' separated strings found at the location bprm->p | 1125 | * Arguments are '\0' separated strings found at the location bprm->p |
1112 | * points to; chop off the first by relocating brpm->p to right after | 1126 | * points to; chop off the first by relocating brpm->p to right after |
@@ -1259,6 +1273,8 @@ EXPORT_SYMBOL(search_binary_handler); | |||
1259 | void free_bprm(struct linux_binprm *bprm) | 1273 | void free_bprm(struct linux_binprm *bprm) |
1260 | { | 1274 | { |
1261 | free_arg_pages(bprm); | 1275 | free_arg_pages(bprm); |
1276 | if (bprm->cred) | ||
1277 | abort_creds(bprm->cred); | ||
1262 | kfree(bprm); | 1278 | kfree(bprm); |
1263 | } | 1279 | } |
1264 | 1280 | ||
@@ -1284,10 +1300,20 @@ int do_execve(char * filename, | |||
1284 | if (!bprm) | 1300 | if (!bprm) |
1285 | goto out_files; | 1301 | goto out_files; |
1286 | 1302 | ||
1303 | retval = mutex_lock_interruptible(¤t->cred_exec_mutex); | ||
1304 | if (retval < 0) | ||
1305 | goto out_free; | ||
1306 | |||
1307 | retval = -ENOMEM; | ||
1308 | bprm->cred = prepare_exec_creds(); | ||
1309 | if (!bprm->cred) | ||
1310 | goto out_unlock; | ||
1311 | check_unsafe_exec(bprm); | ||
1312 | |||
1287 | file = open_exec(filename); | 1313 | file = open_exec(filename); |
1288 | retval = PTR_ERR(file); | 1314 | retval = PTR_ERR(file); |
1289 | if (IS_ERR(file)) | 1315 | if (IS_ERR(file)) |
1290 | goto out_kfree; | 1316 | goto out_unlock; |
1291 | 1317 | ||
1292 | sched_exec(); | 1318 | sched_exec(); |
1293 | 1319 | ||
@@ -1301,14 +1327,10 @@ int do_execve(char * filename, | |||
1301 | 1327 | ||
1302 | bprm->argc = count(argv, MAX_ARG_STRINGS); | 1328 | bprm->argc = count(argv, MAX_ARG_STRINGS); |
1303 | if ((retval = bprm->argc) < 0) | 1329 | if ((retval = bprm->argc) < 0) |
1304 | goto out_mm; | 1330 | goto out; |
1305 | 1331 | ||
1306 | bprm->envc = count(envp, MAX_ARG_STRINGS); | 1332 | bprm->envc = count(envp, MAX_ARG_STRINGS); |
1307 | if ((retval = bprm->envc) < 0) | 1333 | if ((retval = bprm->envc) < 0) |
1308 | goto out_mm; | ||
1309 | |||
1310 | retval = security_bprm_alloc(bprm); | ||
1311 | if (retval) | ||
1312 | goto out; | 1334 | goto out; |
1313 | 1335 | ||
1314 | retval = prepare_binprm(bprm); | 1336 | retval = prepare_binprm(bprm); |
@@ -1330,21 +1352,18 @@ int do_execve(char * filename, | |||
1330 | 1352 | ||
1331 | current->flags &= ~PF_KTHREAD; | 1353 | current->flags &= ~PF_KTHREAD; |
1332 | retval = search_binary_handler(bprm,regs); | 1354 | retval = search_binary_handler(bprm,regs); |
1333 | if (retval >= 0) { | 1355 | if (retval < 0) |
1334 | /* execve success */ | 1356 | goto out; |
1335 | security_bprm_free(bprm); | ||
1336 | acct_update_integrals(current); | ||
1337 | free_bprm(bprm); | ||
1338 | if (displaced) | ||
1339 | put_files_struct(displaced); | ||
1340 | return retval; | ||
1341 | } | ||
1342 | 1357 | ||
1343 | out: | 1358 | /* execve succeeded */ |
1344 | if (bprm->security) | 1359 | mutex_unlock(¤t->cred_exec_mutex); |
1345 | security_bprm_free(bprm); | 1360 | acct_update_integrals(current); |
1361 | free_bprm(bprm); | ||
1362 | if (displaced) | ||
1363 | put_files_struct(displaced); | ||
1364 | return retval; | ||
1346 | 1365 | ||
1347 | out_mm: | 1366 | out: |
1348 | if (bprm->mm) | 1367 | if (bprm->mm) |
1349 | mmput (bprm->mm); | 1368 | mmput (bprm->mm); |
1350 | 1369 | ||
@@ -1353,7 +1372,11 @@ out_file: | |||
1353 | allow_write_access(bprm->file); | 1372 | allow_write_access(bprm->file); |
1354 | fput(bprm->file); | 1373 | fput(bprm->file); |
1355 | } | 1374 | } |
1356 | out_kfree: | 1375 | |
1376 | out_unlock: | ||
1377 | mutex_unlock(¤t->cred_exec_mutex); | ||
1378 | |||
1379 | out_free: | ||
1357 | free_bprm(bprm); | 1380 | free_bprm(bprm); |
1358 | 1381 | ||
1359 | out_files: | 1382 | out_files: |
diff --git a/fs/internal.h b/fs/internal.h index 80aa9a023372..53af885f1732 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | struct super_block; | 12 | struct super_block; |
13 | struct linux_binprm; | ||
13 | 14 | ||
14 | /* | 15 | /* |
15 | * block_dev.c | 16 | * block_dev.c |
@@ -40,6 +41,11 @@ static inline int sb_is_blkdev_sb(struct super_block *sb) | |||
40 | extern void __init chrdev_init(void); | 41 | extern void __init chrdev_init(void); |
41 | 42 | ||
42 | /* | 43 | /* |
44 | * exec.c | ||
45 | */ | ||
46 | extern void check_unsafe_exec(struct linux_binprm *); | ||
47 | |||
48 | /* | ||
43 | * namespace.c | 49 | * namespace.c |
44 | */ | 50 | */ |
45 | extern int copy_mount_options(const void __user *, unsigned long *); | 51 | extern int copy_mount_options(const void __user *, unsigned long *); |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 0b2fcb698a63..e8ce2c4c7ac7 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -508,22 +508,6 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) | |||
508 | return 0; | 508 | return 0; |
509 | } | 509 | } |
510 | 510 | ||
511 | /* | ||
512 | * ieieeeeee, an audit function without a return code! | ||
513 | * | ||
514 | * This function might fail! I decided that it didn't matter. We are too late | ||
515 | * to fail the syscall and the information isn't REQUIRED for any purpose. It's | ||
516 | * just nice to have. We should be able to look at past audit logs to figure | ||
517 | * out this process's current cap set along with the fcaps from the PATH record | ||
518 | * and use that to come up with the final set. Yeah, its ugly, but all the info | ||
519 | * is still in the audit log. So I'm not going to bother mentioning we failed | ||
520 | * if we couldn't allocate memory. | ||
521 | * | ||
522 | * If someone changes their mind they could create the aux record earlier and | ||
523 | * then search here and use that earlier allocation. But I don't wanna. | ||
524 | * | ||
525 | * -Eric | ||
526 | */ | ||
527 | static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, | 511 | static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, |
528 | const struct cred *new, | 512 | const struct cred *new, |
529 | const struct cred *old) | 513 | const struct cred *old) |
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 7394b5b349ff..6cbfbe297180 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
@@ -35,16 +35,20 @@ struct linux_binprm{ | |||
35 | struct mm_struct *mm; | 35 | struct mm_struct *mm; |
36 | unsigned long p; /* current top of mem */ | 36 | unsigned long p; /* current top of mem */ |
37 | unsigned int sh_bang:1, | 37 | unsigned int sh_bang:1, |
38 | misc_bang:1; | 38 | misc_bang:1, |
39 | cred_prepared:1,/* true if creds already prepared (multiple | ||
40 | * preps happen for interpreters) */ | ||
41 | cap_effective:1;/* true if has elevated effective capabilities, | ||
42 | * false if not; except for init which inherits | ||
43 | * its parent's caps anyway */ | ||
39 | #ifdef __alpha__ | 44 | #ifdef __alpha__ |
40 | unsigned int taso:1; | 45 | unsigned int taso:1; |
41 | #endif | 46 | #endif |
42 | unsigned int recursion_depth; | 47 | unsigned int recursion_depth; |
43 | struct file * file; | 48 | struct file * file; |
44 | int e_uid, e_gid; | 49 | struct cred *cred; /* new credentials */ |
45 | kernel_cap_t cap_post_exec_permitted; | 50 | int unsafe; /* how unsafe this exec is (mask of LSM_UNSAFE_*) */ |
46 | bool cap_effective; | 51 | unsigned int per_clear; /* bits to clear in current->personality */ |
47 | void *security; | ||
48 | int argc, envc; | 52 | int argc, envc; |
49 | char * filename; /* Name of binary as seen by procps */ | 53 | char * filename; /* Name of binary as seen by procps */ |
50 | char * interp; /* Name of the binary really executed. Most | 54 | char * interp; /* Name of the binary really executed. Most |
@@ -101,7 +105,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, | |||
101 | int executable_stack); | 105 | int executable_stack); |
102 | extern int bprm_mm_init(struct linux_binprm *bprm); | 106 | extern int bprm_mm_init(struct linux_binprm *bprm); |
103 | extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm); | 107 | extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm); |
104 | extern void compute_creds(struct linux_binprm *binprm); | 108 | extern void install_exec_creds(struct linux_binprm *bprm); |
105 | extern int do_coredump(long signr, int exit_code, struct pt_regs * regs); | 109 | extern int do_coredump(long signr, int exit_code, struct pt_regs * regs); |
106 | extern int set_binfmt(struct linux_binfmt *new); | 110 | extern int set_binfmt(struct linux_binfmt *new); |
107 | extern void free_bprm(struct linux_binprm *); | 111 | extern void free_bprm(struct linux_binprm *); |
diff --git a/include/linux/cred.h b/include/linux/cred.h index eaf6fa695a04..8edb4d1d5427 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -84,8 +84,6 @@ struct thread_group_cred { | |||
84 | struct key *process_keyring; /* keyring private to this process */ | 84 | struct key *process_keyring; /* keyring private to this process */ |
85 | struct rcu_head rcu; /* RCU deletion hook */ | 85 | struct rcu_head rcu; /* RCU deletion hook */ |
86 | }; | 86 | }; |
87 | |||
88 | extern void release_tgcred(struct cred *cred); | ||
89 | #endif | 87 | #endif |
90 | 88 | ||
91 | /* | 89 | /* |
@@ -144,6 +142,7 @@ struct cred { | |||
144 | extern void __put_cred(struct cred *); | 142 | extern void __put_cred(struct cred *); |
145 | extern int copy_creds(struct task_struct *, unsigned long); | 143 | extern int copy_creds(struct task_struct *, unsigned long); |
146 | extern struct cred *prepare_creds(void); | 144 | extern struct cred *prepare_creds(void); |
145 | extern struct cred *prepare_exec_creds(void); | ||
147 | extern struct cred *prepare_usermodehelper_creds(void); | 146 | extern struct cred *prepare_usermodehelper_creds(void); |
148 | extern int commit_creds(struct cred *); | 147 | extern int commit_creds(struct cred *); |
149 | extern void abort_creds(struct cred *); | 148 | extern void abort_creds(struct cred *); |
diff --git a/include/linux/key.h b/include/linux/key.h index 69ecf0934b02..21d32a142c00 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -278,7 +278,6 @@ extern ctl_table key_sysctls[]; | |||
278 | * the userspace interface | 278 | * the userspace interface |
279 | */ | 279 | */ |
280 | extern int install_thread_keyring_to_cred(struct cred *cred); | 280 | extern int install_thread_keyring_to_cred(struct cred *cred); |
281 | extern int exec_keys(struct task_struct *tsk); | ||
282 | extern void key_fsuid_changed(struct task_struct *tsk); | 281 | extern void key_fsuid_changed(struct task_struct *tsk); |
283 | extern void key_fsgid_changed(struct task_struct *tsk); | 282 | extern void key_fsgid_changed(struct task_struct *tsk); |
284 | extern void key_init(void); | 283 | extern void key_init(void); |
@@ -294,7 +293,6 @@ extern void key_init(void); | |||
294 | #define make_key_ref(k, p) NULL | 293 | #define make_key_ref(k, p) NULL |
295 | #define key_ref_to_ptr(k) NULL | 294 | #define key_ref_to_ptr(k) NULL |
296 | #define is_key_possessed(k) 0 | 295 | #define is_key_possessed(k) 0 |
297 | #define exec_keys(t) do { } while(0) | ||
298 | #define key_fsuid_changed(t) do { } while(0) | 296 | #define key_fsuid_changed(t) do { } while(0) |
299 | #define key_fsgid_changed(t) do { } while(0) | 297 | #define key_fsgid_changed(t) do { } while(0) |
300 | #define key_init() do { } while(0) | 298 | #define key_init() do { } while(0) |
diff --git a/include/linux/security.h b/include/linux/security.h index 68be11251447..56a0eed65673 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -57,8 +57,7 @@ extern int cap_capset(struct cred *new, const struct cred *old, | |||
57 | const kernel_cap_t *effective, | 57 | const kernel_cap_t *effective, |
58 | const kernel_cap_t *inheritable, | 58 | const kernel_cap_t *inheritable, |
59 | const kernel_cap_t *permitted); | 59 | const kernel_cap_t *permitted); |
60 | extern int cap_bprm_set_security(struct linux_binprm *bprm); | 60 | extern int cap_bprm_set_creds(struct linux_binprm *bprm); |
61 | extern int cap_bprm_apply_creds(struct linux_binprm *bprm, int unsafe); | ||
62 | extern int cap_bprm_secureexec(struct linux_binprm *bprm); | 61 | extern int cap_bprm_secureexec(struct linux_binprm *bprm); |
63 | extern int cap_inode_setxattr(struct dentry *dentry, const char *name, | 62 | extern int cap_inode_setxattr(struct dentry *dentry, const char *name, |
64 | const void *value, size_t size, int flags); | 63 | const void *value, size_t size, int flags); |
@@ -110,7 +109,7 @@ extern unsigned long mmap_min_addr; | |||
110 | struct sched_param; | 109 | struct sched_param; |
111 | struct request_sock; | 110 | struct request_sock; |
112 | 111 | ||
113 | /* bprm_apply_creds unsafe reasons */ | 112 | /* bprm->unsafe reasons */ |
114 | #define LSM_UNSAFE_SHARE 1 | 113 | #define LSM_UNSAFE_SHARE 1 |
115 | #define LSM_UNSAFE_PTRACE 2 | 114 | #define LSM_UNSAFE_PTRACE 2 |
116 | #define LSM_UNSAFE_PTRACE_CAP 4 | 115 | #define LSM_UNSAFE_PTRACE_CAP 4 |
@@ -154,36 +153,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
154 | * | 153 | * |
155 | * Security hooks for program execution operations. | 154 | * Security hooks for program execution operations. |
156 | * | 155 | * |
157 | * @bprm_alloc_security: | 156 | * @bprm_set_creds: |
158 | * Allocate and attach a security structure to the @bprm->security field. | ||
159 | * The security field is initialized to NULL when the bprm structure is | ||
160 | * allocated. | ||
161 | * @bprm contains the linux_binprm structure to be modified. | ||
162 | * Return 0 if operation was successful. | ||
163 | * @bprm_free_security: | ||
164 | * @bprm contains the linux_binprm structure to be modified. | ||
165 | * Deallocate and clear the @bprm->security field. | ||
166 | * @bprm_apply_creds: | ||
167 | * Compute and set the security attributes of a process being transformed | ||
168 | * by an execve operation based on the old attributes (current->security) | ||
169 | * and the information saved in @bprm->security by the set_security hook. | ||
170 | * Since this function may return an error, in which case the process will | ||
171 | * be killed. However, it can leave the security attributes of the | ||
172 | * process unchanged if an access failure occurs at this point. | ||
173 | * bprm_apply_creds is called under task_lock. @unsafe indicates various | ||
174 | * reasons why it may be unsafe to change security state. | ||
175 | * @bprm contains the linux_binprm structure. | ||
176 | * @bprm_post_apply_creds: | ||
177 | * Runs after bprm_apply_creds with the task_lock dropped, so that | ||
178 | * functions which cannot be called safely under the task_lock can | ||
179 | * be used. This hook is a good place to perform state changes on | ||
180 | * the process such as closing open file descriptors to which access | ||
181 | * is no longer granted if the attributes were changed. | ||
182 | * Note that a security module might need to save state between | ||
183 | * bprm_apply_creds and bprm_post_apply_creds to store the decision | ||
184 | * on whether the process may proceed. | ||
185 | * @bprm contains the linux_binprm structure. | ||
186 | * @bprm_set_security: | ||
187 | * Save security information in the bprm->security field, typically based | 157 | * Save security information in the bprm->security field, typically based |
188 | * on information about the bprm->file, for later use by the apply_creds | 158 | * on information about the bprm->file, for later use by the apply_creds |
189 | * hook. This hook may also optionally check permissions (e.g. for | 159 | * hook. This hook may also optionally check permissions (e.g. for |
@@ -196,15 +166,30 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
196 | * @bprm contains the linux_binprm structure. | 166 | * @bprm contains the linux_binprm structure. |
197 | * Return 0 if the hook is successful and permission is granted. | 167 | * Return 0 if the hook is successful and permission is granted. |
198 | * @bprm_check_security: | 168 | * @bprm_check_security: |
199 | * This hook mediates the point when a search for a binary handler will | 169 | * This hook mediates the point when a search for a binary handler will |
200 | * begin. It allows a check the @bprm->security value which is set in | 170 | * begin. It allows a check the @bprm->security value which is set in the |
201 | * the preceding set_security call. The primary difference from | 171 | * preceding set_creds call. The primary difference from set_creds is |
202 | * set_security is that the argv list and envp list are reliably | 172 | * that the argv list and envp list are reliably available in @bprm. This |
203 | * available in @bprm. This hook may be called multiple times | 173 | * hook may be called multiple times during a single execve; and in each |
204 | * during a single execve; and in each pass set_security is called | 174 | * pass set_creds is called first. |
205 | * first. | ||
206 | * @bprm contains the linux_binprm structure. | 175 | * @bprm contains the linux_binprm structure. |
207 | * Return 0 if the hook is successful and permission is granted. | 176 | * Return 0 if the hook is successful and permission is granted. |
177 | * @bprm_committing_creds: | ||
178 | * Prepare to install the new security attributes of a process being | ||
179 | * transformed by an execve operation, based on the old credentials | ||
180 | * pointed to by @current->cred and the information set in @bprm->cred by | ||
181 | * the bprm_set_creds hook. @bprm points to the linux_binprm structure. | ||
182 | * This hook is a good place to perform state changes on the process such | ||
183 | * as closing open file descriptors to which access will no longer be | ||
184 | * granted when the attributes are changed. This is called immediately | ||
185 | * before commit_creds(). | ||
186 | * @bprm_committed_creds: | ||
187 | * Tidy up after the installation of the new security attributes of a | ||
188 | * process being transformed by an execve operation. The new credentials | ||
189 | * have, by this point, been set to @current->cred. @bprm points to the | ||
190 | * linux_binprm structure. This hook is a good place to perform state | ||
191 | * changes on the process such as clearing out non-inheritable signal | ||
192 | * state. This is called immediately after commit_creds(). | ||
208 | * @bprm_secureexec: | 193 | * @bprm_secureexec: |
209 | * Return a boolean value (0 or 1) indicating whether a "secure exec" | 194 | * Return a boolean value (0 or 1) indicating whether a "secure exec" |
210 | * is required. The flag is passed in the auxiliary table | 195 | * is required. The flag is passed in the auxiliary table |
@@ -1301,13 +1286,11 @@ struct security_operations { | |||
1301 | int (*settime) (struct timespec *ts, struct timezone *tz); | 1286 | int (*settime) (struct timespec *ts, struct timezone *tz); |
1302 | int (*vm_enough_memory) (struct mm_struct *mm, long pages); | 1287 | int (*vm_enough_memory) (struct mm_struct *mm, long pages); |
1303 | 1288 | ||
1304 | int (*bprm_alloc_security) (struct linux_binprm *bprm); | 1289 | int (*bprm_set_creds) (struct linux_binprm *bprm); |
1305 | void (*bprm_free_security) (struct linux_binprm *bprm); | ||
1306 | int (*bprm_apply_creds) (struct linux_binprm *bprm, int unsafe); | ||
1307 | void (*bprm_post_apply_creds) (struct linux_binprm *bprm); | ||
1308 | int (*bprm_set_security) (struct linux_binprm *bprm); | ||
1309 | int (*bprm_check_security) (struct linux_binprm *bprm); | 1290 | int (*bprm_check_security) (struct linux_binprm *bprm); |
1310 | int (*bprm_secureexec) (struct linux_binprm *bprm); | 1291 | int (*bprm_secureexec) (struct linux_binprm *bprm); |
1292 | void (*bprm_committing_creds) (struct linux_binprm *bprm); | ||
1293 | void (*bprm_committed_creds) (struct linux_binprm *bprm); | ||
1311 | 1294 | ||
1312 | int (*sb_alloc_security) (struct super_block *sb); | 1295 | int (*sb_alloc_security) (struct super_block *sb); |
1313 | void (*sb_free_security) (struct super_block *sb); | 1296 | void (*sb_free_security) (struct super_block *sb); |
@@ -1569,12 +1552,10 @@ int security_settime(struct timespec *ts, struct timezone *tz); | |||
1569 | int security_vm_enough_memory(long pages); | 1552 | int security_vm_enough_memory(long pages); |
1570 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); | 1553 | int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); |
1571 | int security_vm_enough_memory_kern(long pages); | 1554 | int security_vm_enough_memory_kern(long pages); |
1572 | int security_bprm_alloc(struct linux_binprm *bprm); | 1555 | int security_bprm_set_creds(struct linux_binprm *bprm); |
1573 | void security_bprm_free(struct linux_binprm *bprm); | ||
1574 | int security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe); | ||
1575 | void security_bprm_post_apply_creds(struct linux_binprm *bprm); | ||
1576 | int security_bprm_set(struct linux_binprm *bprm); | ||
1577 | int security_bprm_check(struct linux_binprm *bprm); | 1556 | int security_bprm_check(struct linux_binprm *bprm); |
1557 | void security_bprm_committing_creds(struct linux_binprm *bprm); | ||
1558 | void security_bprm_committed_creds(struct linux_binprm *bprm); | ||
1578 | int security_bprm_secureexec(struct linux_binprm *bprm); | 1559 | int security_bprm_secureexec(struct linux_binprm *bprm); |
1579 | int security_sb_alloc(struct super_block *sb); | 1560 | int security_sb_alloc(struct super_block *sb); |
1580 | void security_sb_free(struct super_block *sb); | 1561 | void security_sb_free(struct super_block *sb); |
@@ -1812,32 +1793,22 @@ static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) | |||
1812 | return cap_vm_enough_memory(mm, pages); | 1793 | return cap_vm_enough_memory(mm, pages); |
1813 | } | 1794 | } |
1814 | 1795 | ||
1815 | static inline int security_bprm_alloc(struct linux_binprm *bprm) | 1796 | static inline int security_bprm_set_creds(struct linux_binprm *bprm) |
1816 | { | ||
1817 | return 0; | ||
1818 | } | ||
1819 | |||
1820 | static inline void security_bprm_free(struct linux_binprm *bprm) | ||
1821 | { } | ||
1822 | |||
1823 | static inline int security_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) | ||
1824 | { | 1797 | { |
1825 | return cap_bprm_apply_creds(bprm, unsafe); | 1798 | return cap_bprm_set_creds(bprm); |
1826 | } | 1799 | } |
1827 | 1800 | ||
1828 | static inline void security_bprm_post_apply_creds(struct linux_binprm *bprm) | 1801 | static inline int security_bprm_check(struct linux_binprm *bprm) |
1829 | { | 1802 | { |
1830 | return; | 1803 | return 0; |
1831 | } | 1804 | } |
1832 | 1805 | ||
1833 | static inline int security_bprm_set(struct linux_binprm *bprm) | 1806 | static inline void security_bprm_committing_creds(struct linux_binprm *bprm) |
1834 | { | 1807 | { |
1835 | return cap_bprm_set_security(bprm); | ||
1836 | } | 1808 | } |
1837 | 1809 | ||
1838 | static inline int security_bprm_check(struct linux_binprm *bprm) | 1810 | static inline void security_bprm_committed_creds(struct linux_binprm *bprm) |
1839 | { | 1811 | { |
1840 | return 0; | ||
1841 | } | 1812 | } |
1842 | 1813 | ||
1843 | static inline int security_bprm_secureexec(struct linux_binprm *bprm) | 1814 | static inline int security_bprm_secureexec(struct linux_binprm *bprm) |
diff --git a/kernel/cred.c b/kernel/cred.c index cb6b5eda978d..e6fcdd67b2ec 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -68,7 +68,7 @@ static void release_tgcred_rcu(struct rcu_head *rcu) | |||
68 | /* | 68 | /* |
69 | * Release a set of thread group credentials. | 69 | * Release a set of thread group credentials. |
70 | */ | 70 | */ |
71 | void release_tgcred(struct cred *cred) | 71 | static void release_tgcred(struct cred *cred) |
72 | { | 72 | { |
73 | #ifdef CONFIG_KEYS | 73 | #ifdef CONFIG_KEYS |
74 | struct thread_group_cred *tgcred = cred->tgcred; | 74 | struct thread_group_cred *tgcred = cred->tgcred; |
@@ -164,6 +164,50 @@ error: | |||
164 | EXPORT_SYMBOL(prepare_creds); | 164 | EXPORT_SYMBOL(prepare_creds); |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * Prepare credentials for current to perform an execve() | ||
168 | * - The caller must hold current->cred_exec_mutex | ||
169 | */ | ||
170 | struct cred *prepare_exec_creds(void) | ||
171 | { | ||
172 | struct thread_group_cred *tgcred = NULL; | ||
173 | struct cred *new; | ||
174 | |||
175 | #ifdef CONFIG_KEYS | ||
176 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | ||
177 | if (!tgcred) | ||
178 | return NULL; | ||
179 | #endif | ||
180 | |||
181 | new = prepare_creds(); | ||
182 | if (!new) { | ||
183 | kfree(tgcred); | ||
184 | return new; | ||
185 | } | ||
186 | |||
187 | #ifdef CONFIG_KEYS | ||
188 | /* newly exec'd tasks don't get a thread keyring */ | ||
189 | key_put(new->thread_keyring); | ||
190 | new->thread_keyring = NULL; | ||
191 | |||
192 | /* create a new per-thread-group creds for all this set of threads to | ||
193 | * share */ | ||
194 | memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred)); | ||
195 | |||
196 | atomic_set(&tgcred->usage, 1); | ||
197 | spin_lock_init(&tgcred->lock); | ||
198 | |||
199 | /* inherit the session keyring; new process keyring */ | ||
200 | key_get(tgcred->session_keyring); | ||
201 | tgcred->process_keyring = NULL; | ||
202 | |||
203 | release_tgcred(new); | ||
204 | new->tgcred = tgcred; | ||
205 | #endif | ||
206 | |||
207 | return new; | ||
208 | } | ||
209 | |||
210 | /* | ||
167 | * prepare new credentials for the usermode helper dispatcher | 211 | * prepare new credentials for the usermode helper dispatcher |
168 | */ | 212 | */ |
169 | struct cred *prepare_usermodehelper_creds(void) | 213 | struct cred *prepare_usermodehelper_creds(void) |
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, |