diff options
Diffstat (limited to 'fs/exec.c')
| -rw-r--r-- | fs/exec.c | 67 |
1 files changed, 40 insertions, 27 deletions
| @@ -678,8 +678,8 @@ exit: | |||
| 678 | } | 678 | } |
| 679 | EXPORT_SYMBOL(open_exec); | 679 | EXPORT_SYMBOL(open_exec); |
| 680 | 680 | ||
| 681 | int kernel_read(struct file *file, unsigned long offset, | 681 | int kernel_read(struct file *file, loff_t offset, |
| 682 | char *addr, unsigned long count) | 682 | char *addr, unsigned long count) |
| 683 | { | 683 | { |
| 684 | mm_segment_t old_fs; | 684 | mm_segment_t old_fs; |
| 685 | loff_t pos = offset; | 685 | loff_t pos = offset; |
| @@ -1016,6 +1016,35 @@ out: | |||
| 1016 | EXPORT_SYMBOL(flush_old_exec); | 1016 | EXPORT_SYMBOL(flush_old_exec); |
| 1017 | 1017 | ||
| 1018 | /* | 1018 | /* |
| 1019 | * Prepare credentials and lock ->cred_guard_mutex. | ||
| 1020 | * install_exec_creds() commits the new creds and drops the lock. | ||
| 1021 | * Or, if exec fails before, free_bprm() should release ->cred and | ||
| 1022 | * and unlock. | ||
| 1023 | */ | ||
| 1024 | int prepare_bprm_creds(struct linux_binprm *bprm) | ||
| 1025 | { | ||
| 1026 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | ||
| 1027 | return -ERESTARTNOINTR; | ||
| 1028 | |||
| 1029 | bprm->cred = prepare_exec_creds(); | ||
| 1030 | if (likely(bprm->cred)) | ||
| 1031 | return 0; | ||
| 1032 | |||
| 1033 | mutex_unlock(¤t->cred_guard_mutex); | ||
| 1034 | return -ENOMEM; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | void free_bprm(struct linux_binprm *bprm) | ||
| 1038 | { | ||
| 1039 | free_arg_pages(bprm); | ||
| 1040 | if (bprm->cred) { | ||
| 1041 | mutex_unlock(¤t->cred_guard_mutex); | ||
| 1042 | abort_creds(bprm->cred); | ||
| 1043 | } | ||
| 1044 | kfree(bprm); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | /* | ||
| 1019 | * install the new credentials for this executable | 1048 | * install the new credentials for this executable |
| 1020 | */ | 1049 | */ |
| 1021 | void install_exec_creds(struct linux_binprm *bprm) | 1050 | void install_exec_creds(struct linux_binprm *bprm) |
| @@ -1024,12 +1053,13 @@ void install_exec_creds(struct linux_binprm *bprm) | |||
| 1024 | 1053 | ||
| 1025 | commit_creds(bprm->cred); | 1054 | commit_creds(bprm->cred); |
| 1026 | bprm->cred = NULL; | 1055 | bprm->cred = NULL; |
| 1027 | 1056 | /* | |
| 1028 | /* cred_guard_mutex must be held at least to this point to prevent | 1057 | * cred_guard_mutex must be held at least to this point to prevent |
| 1029 | * ptrace_attach() from altering our determination of the task's | 1058 | * ptrace_attach() from altering our determination of the task's |
| 1030 | * credentials; any time after this it may be unlocked */ | 1059 | * credentials; any time after this it may be unlocked. |
| 1031 | 1060 | */ | |
| 1032 | security_bprm_committed_creds(bprm); | 1061 | security_bprm_committed_creds(bprm); |
| 1062 | mutex_unlock(¤t->cred_guard_mutex); | ||
| 1033 | } | 1063 | } |
| 1034 | EXPORT_SYMBOL(install_exec_creds); | 1064 | EXPORT_SYMBOL(install_exec_creds); |
| 1035 | 1065 | ||
| @@ -1246,14 +1276,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
| 1246 | 1276 | ||
| 1247 | EXPORT_SYMBOL(search_binary_handler); | 1277 | EXPORT_SYMBOL(search_binary_handler); |
| 1248 | 1278 | ||
| 1249 | void free_bprm(struct linux_binprm *bprm) | ||
| 1250 | { | ||
| 1251 | free_arg_pages(bprm); | ||
| 1252 | if (bprm->cred) | ||
| 1253 | abort_creds(bprm->cred); | ||
| 1254 | kfree(bprm); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /* | 1279 | /* |
| 1258 | * sys_execve() executes a new program. | 1280 | * sys_execve() executes a new program. |
| 1259 | */ | 1281 | */ |
| @@ -1277,20 +1299,15 @@ int do_execve(char * filename, | |||
| 1277 | if (!bprm) | 1299 | if (!bprm) |
| 1278 | goto out_files; | 1300 | goto out_files; |
| 1279 | 1301 | ||
| 1280 | retval = -ERESTARTNOINTR; | 1302 | retval = prepare_bprm_creds(bprm); |
| 1281 | if (mutex_lock_interruptible(¤t->cred_guard_mutex)) | 1303 | if (retval) |
| 1282 | goto out_free; | 1304 | goto out_free; |
| 1283 | current->in_execve = 1; | ||
| 1284 | |||
| 1285 | retval = -ENOMEM; | ||
| 1286 | bprm->cred = prepare_exec_creds(); | ||
| 1287 | if (!bprm->cred) | ||
| 1288 | goto out_unlock; | ||
| 1289 | 1305 | ||
| 1290 | retval = check_unsafe_exec(bprm); | 1306 | retval = check_unsafe_exec(bprm); |
| 1291 | if (retval < 0) | 1307 | if (retval < 0) |
| 1292 | goto out_unlock; | 1308 | goto out_free; |
| 1293 | clear_in_exec = retval; | 1309 | clear_in_exec = retval; |
| 1310 | current->in_execve = 1; | ||
| 1294 | 1311 | ||
| 1295 | file = open_exec(filename); | 1312 | file = open_exec(filename); |
| 1296 | retval = PTR_ERR(file); | 1313 | retval = PTR_ERR(file); |
| @@ -1340,7 +1357,6 @@ int do_execve(char * filename, | |||
| 1340 | /* execve succeeded */ | 1357 | /* execve succeeded */ |
| 1341 | current->fs->in_exec = 0; | 1358 | current->fs->in_exec = 0; |
| 1342 | current->in_execve = 0; | 1359 | current->in_execve = 0; |
| 1343 | mutex_unlock(¤t->cred_guard_mutex); | ||
| 1344 | acct_update_integrals(current); | 1360 | acct_update_integrals(current); |
| 1345 | free_bprm(bprm); | 1361 | free_bprm(bprm); |
| 1346 | if (displaced) | 1362 | if (displaced) |
| @@ -1360,10 +1376,7 @@ out_file: | |||
| 1360 | out_unmark: | 1376 | out_unmark: |
| 1361 | if (clear_in_exec) | 1377 | if (clear_in_exec) |
| 1362 | current->fs->in_exec = 0; | 1378 | current->fs->in_exec = 0; |
| 1363 | |||
| 1364 | out_unlock: | ||
| 1365 | current->in_execve = 0; | 1379 | current->in_execve = 0; |
| 1366 | mutex_unlock(¤t->cred_guard_mutex); | ||
| 1367 | 1380 | ||
| 1368 | out_free: | 1381 | out_free: |
| 1369 | free_bprm(bprm); | 1382 | free_bprm(bprm); |
