aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-04-22 05:11:59 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-04-25 09:23:53 -0400
commitfd8328be874f4190a811c58cd4778ec2c74d2c05 (patch)
treeb44ae8e99ce96a1a4739b04d4d1a23c40ab8b163 /fs/exec.c
parent6b335d9c80d7f3c2a3f6545f664ae9007a0f3821 (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.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 54a0a557b678..475543002f13 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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
1037mmap_failed:
1038 reset_files_struct(current, files);
1039out: 1025out:
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:
1363out_kfree: 1362out_kfree:
1364 kfree(bprm); 1363 kfree(bprm);
1365 1364
1365out_files:
1366 if (files)
1367 reset_files_struct(current, files);
1366out_ret: 1368out_ret:
1367 return retval; 1369 return retval;
1368} 1370}