diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-22 05:11:59 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-25 09:23:53 -0400 |
commit | fd8328be874f4190a811c58cd4778ec2c74d2c05 (patch) | |
tree | b44ae8e99ce96a1a4739b04d4d1a23c40ab8b163 /fs/exec.c | |
parent | 6b335d9c80d7f3c2a3f6545f664ae9007a0f3821 (diff) |
[PATCH] sanitize handling of shared descriptor tables in failing execve()
* unshare_files() can fail; doing it after irreversible actions is wrong
and de_thread() is certainly irreversible.
* since we do it unconditionally anyway, we might as well do it in do_execve()
and save ourselves the PITA in binfmt handlers, etc.
* while we are at it, binfmt_som actually leaked files_struct on failure.
As a side benefit, unshare_files(), put_files_struct() and reset_files_struct()
become unexported.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/exec.c')
-rw-r--r-- | fs/exec.c | 34 |
1 files changed, 18 insertions, 16 deletions
@@ -953,7 +953,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
953 | { | 953 | { |
954 | char * name; | 954 | char * name; |
955 | int i, ch, retval; | 955 | int i, ch, retval; |
956 | struct files_struct *files; | ||
957 | char tcomm[sizeof(current->comm)]; | 956 | char tcomm[sizeof(current->comm)]; |
958 | 957 | ||
959 | /* | 958 | /* |
@@ -965,26 +964,15 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
965 | goto out; | 964 | goto out; |
966 | 965 | ||
967 | /* | 966 | /* |
968 | * Make sure we have private file handles. Ask the | ||
969 | * fork helper to do the work for us and the exit | ||
970 | * helper to do the cleanup of the old one. | ||
971 | */ | ||
972 | files = current->files; /* refcounted so safe to hold */ | ||
973 | retval = unshare_files(); | ||
974 | if (retval) | ||
975 | goto out; | ||
976 | /* | ||
977 | * Release all of the old mmap stuff | 967 | * Release all of the old mmap stuff |
978 | */ | 968 | */ |
979 | retval = exec_mmap(bprm->mm); | 969 | retval = exec_mmap(bprm->mm); |
980 | if (retval) | 970 | if (retval) |
981 | goto mmap_failed; | 971 | goto out; |
982 | 972 | ||
983 | bprm->mm = NULL; /* We're using it now */ | 973 | bprm->mm = NULL; /* We're using it now */ |
984 | 974 | ||
985 | /* This is the point of no return */ | 975 | /* This is the point of no return */ |
986 | put_files_struct(files); | ||
987 | |||
988 | current->sas_ss_sp = current->sas_ss_size = 0; | 976 | current->sas_ss_sp = current->sas_ss_size = 0; |
989 | 977 | ||
990 | if (current->euid == current->uid && current->egid == current->gid) | 978 | if (current->euid == current->uid && current->egid == current->gid) |
@@ -1034,8 +1022,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1034 | 1022 | ||
1035 | return 0; | 1023 | return 0; |
1036 | 1024 | ||
1037 | mmap_failed: | ||
1038 | reset_files_struct(current, files); | ||
1039 | out: | 1025 | out: |
1040 | return retval; | 1026 | return retval; |
1041 | } | 1027 | } |
@@ -1283,12 +1269,23 @@ int do_execve(char * filename, | |||
1283 | struct linux_binprm *bprm; | 1269 | struct linux_binprm *bprm; |
1284 | struct file *file; | 1270 | struct file *file; |
1285 | unsigned long env_p; | 1271 | unsigned long env_p; |
1272 | struct files_struct *files; | ||
1286 | int retval; | 1273 | int retval; |
1287 | 1274 | ||
1275 | files = current->files; | ||
1276 | retval = unshare_files(); | ||
1277 | if (retval) | ||
1278 | goto out_ret; | ||
1279 | |||
1280 | if (files == current->files) { | ||
1281 | put_files_struct(files); | ||
1282 | files = NULL; | ||
1283 | } | ||
1284 | |||
1288 | retval = -ENOMEM; | 1285 | retval = -ENOMEM; |
1289 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); | 1286 | bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); |
1290 | if (!bprm) | 1287 | if (!bprm) |
1291 | goto out_ret; | 1288 | goto out_files; |
1292 | 1289 | ||
1293 | file = open_exec(filename); | 1290 | file = open_exec(filename); |
1294 | retval = PTR_ERR(file); | 1291 | retval = PTR_ERR(file); |
@@ -1343,6 +1340,8 @@ int do_execve(char * filename, | |||
1343 | security_bprm_free(bprm); | 1340 | security_bprm_free(bprm); |
1344 | acct_update_integrals(current); | 1341 | acct_update_integrals(current); |
1345 | kfree(bprm); | 1342 | kfree(bprm); |
1343 | if (files) | ||
1344 | put_files_struct(files); | ||
1346 | return retval; | 1345 | return retval; |
1347 | } | 1346 | } |
1348 | 1347 | ||
@@ -1363,6 +1362,9 @@ out_file: | |||
1363 | out_kfree: | 1362 | out_kfree: |
1364 | kfree(bprm); | 1363 | kfree(bprm); |
1365 | 1364 | ||
1365 | out_files: | ||
1366 | if (files) | ||
1367 | reset_files_struct(current, files); | ||
1366 | out_ret: | 1368 | out_ret: |
1367 | return retval; | 1369 | return retval; |
1368 | } | 1370 | } |