Commit 08a6fac1c63233c87eec129938022f1a9a4d51f6

Authored by Al Viro
1 parent 5f719558ed

[PATCH] get rid of leak in compat_execve()

Even though copy_compat_strings() doesn't cache the pages,
copy_strings_kernel() and stuff indirectly called by e.g.
->load_binary() is doing that, so we need to drop the
cache contents in the end.

[found by WANG Cong <wangcong@zeuux.org>]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 3 changed files with 11 additions and 6 deletions Side-by-side Diff

... ... @@ -1405,7 +1405,7 @@
1405 1405 /* execve success */
1406 1406 security_bprm_free(bprm);
1407 1407 acct_update_integrals(current);
1408   - kfree(bprm);
  1408 + free_bprm(bprm);
1409 1409 return retval;
1410 1410 }
1411 1411  
... ... @@ -1424,7 +1424,7 @@
1424 1424 }
1425 1425  
1426 1426 out_kfree:
1427   - kfree(bprm);
  1427 + free_bprm(bprm);
1428 1428  
1429 1429 out_ret:
1430 1430 return retval;
... ... @@ -1251,6 +1251,12 @@
1251 1251  
1252 1252 EXPORT_SYMBOL(search_binary_handler);
1253 1253  
  1254 +void free_bprm(struct linux_binprm *bprm)
  1255 +{
  1256 + free_arg_pages(bprm);
  1257 + kfree(bprm);
  1258 +}
  1259 +
1254 1260 /*
1255 1261 * sys_execve() executes a new program.
1256 1262 */
1257 1263  
1258 1264  
... ... @@ -1320,17 +1326,15 @@
1320 1326 retval = search_binary_handler(bprm,regs);
1321 1327 if (retval >= 0) {
1322 1328 /* execve success */
1323   - free_arg_pages(bprm);
1324 1329 security_bprm_free(bprm);
1325 1330 acct_update_integrals(current);
1326   - kfree(bprm);
  1331 + free_bprm(bprm);
1327 1332 if (displaced)
1328 1333 put_files_struct(displaced);
1329 1334 return retval;
1330 1335 }
1331 1336  
1332 1337 out:
1333   - free_arg_pages(bprm);
1334 1338 if (bprm->security)
1335 1339 security_bprm_free(bprm);
1336 1340  
... ... @@ -1344,7 +1348,7 @@
1344 1348 fput(bprm->file);
1345 1349 }
1346 1350 out_kfree:
1347   - kfree(bprm);
  1351 + free_bprm(bprm);
1348 1352  
1349 1353 out_files:
1350 1354 if (displaced)
include/linux/binfmts.h
... ... @@ -99,6 +99,7 @@
99 99 extern void compute_creds(struct linux_binprm *binprm);
100 100 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
101 101 extern int set_binfmt(struct linux_binfmt *new);
  102 +extern void free_bprm(struct linux_binprm *);
102 103  
103 104 #endif /* __KERNEL__ */
104 105 #endif /* _LINUX_BINFMTS_H */