aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-09-11 17:24:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-11 18:59:05 -0400
commitcb7b6b1cbc20a970c7124efae1c2478155604b54 (patch)
treeef0e867017f0a6fea23ebdcd87753174a4c75a25
parent92eaa565add62d56b90987f58ea9feafc5a7c183 (diff)
exec: cleanup the CONFIG_MODULES logic
search_binary_handler() uses "for (try=0; try<2; try++)" to avoid "goto" but the code looks too complicated and horrible imho. We still need to check "try == 0" before request_module() and add the additional "break" for !CONFIG_MODULES case. Kill this loop and use a simple "bool need_retry" + "goto retry". The code looks much simpler and we do not even need ifdef's, gcc can optimize out the "if (need_retry)" block if !IS_ENABLED(). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Kees Cook <keescook@chromium.org> Cc: Al Viro <viro@ZenIV.linux.org.uk> Cc: Evgeniy Polyakov <zbr@ioremap.net> Cc: Zach Levis <zml@linux.vnet.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/exec.c68
1 files changed, 31 insertions, 37 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 7b92fbfa63aa..ba357e6aea98 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1367,13 +1367,15 @@ out:
1367} 1367}
1368EXPORT_SYMBOL(remove_arg_zero); 1368EXPORT_SYMBOL(remove_arg_zero);
1369 1369
1370#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e))
1370/* 1371/*
1371 * cycle the list of binary formats handler, until one recognizes the image 1372 * cycle the list of binary formats handler, until one recognizes the image
1372 */ 1373 */
1373int search_binary_handler(struct linux_binprm *bprm) 1374int search_binary_handler(struct linux_binprm *bprm)
1374{ 1375{
1375 int try, retval; 1376 bool need_retry = IS_ENABLED(CONFIG_MODULES);
1376 struct linux_binfmt *fmt; 1377 struct linux_binfmt *fmt;
1378 int retval;
1377 1379
1378 /* This allows 4 levels of binfmt rewrites before failing hard. */ 1380 /* This allows 4 levels of binfmt rewrites before failing hard. */
1379 if (bprm->recursion_depth > 5) 1381 if (bprm->recursion_depth > 5)
@@ -1388,47 +1390,39 @@ int search_binary_handler(struct linux_binprm *bprm)
1388 return retval; 1390 return retval;
1389 1391
1390 retval = -ENOENT; 1392 retval = -ENOENT;
1391 for (try=0; try<2; try++) { 1393 retry:
1392 read_lock(&binfmt_lock); 1394 read_lock(&binfmt_lock);
1393 list_for_each_entry(fmt, &formats, lh) { 1395 list_for_each_entry(fmt, &formats, lh) {
1394 if (!try_module_get(fmt->module)) 1396 if (!try_module_get(fmt->module))
1395 continue; 1397 continue;
1396 read_unlock(&binfmt_lock); 1398 read_unlock(&binfmt_lock);
1397 bprm->recursion_depth++; 1399 bprm->recursion_depth++;
1398 retval = fmt->load_binary(bprm); 1400 retval = fmt->load_binary(bprm);
1399 bprm->recursion_depth--; 1401 bprm->recursion_depth--;
1400 if (retval >= 0) { 1402 if (retval >= 0) {
1401 put_binfmt(fmt);
1402 return retval;
1403 }
1404 read_lock(&binfmt_lock);
1405 put_binfmt(fmt); 1403 put_binfmt(fmt);
1406 if (retval != -ENOEXEC || bprm->mm == NULL) 1404 return retval;
1407 break;
1408 if (!bprm->file) {
1409 read_unlock(&binfmt_lock);
1410 return retval;
1411 }
1412 } 1405 }
1413 read_unlock(&binfmt_lock); 1406 read_lock(&binfmt_lock);
1414#ifdef CONFIG_MODULES 1407 put_binfmt(fmt);
1415 if (retval != -ENOEXEC || bprm->mm == NULL) { 1408 if (retval != -ENOEXEC || bprm->mm == NULL)
1416 break; 1409 break;
1417 } else { 1410 if (!bprm->file) {
1418#define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e)) 1411 read_unlock(&binfmt_lock);
1419 if (printable(bprm->buf[0]) && 1412 return retval;
1420 printable(bprm->buf[1]) &&
1421 printable(bprm->buf[2]) &&
1422 printable(bprm->buf[3]))
1423 break; /* -ENOEXEC */
1424 if (try)
1425 break; /* -ENOEXEC */
1426 request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2]));
1427 } 1413 }
1428#else
1429 break;
1430#endif
1431 } 1414 }
1415 read_unlock(&binfmt_lock);
1416
1417 if (need_retry && retval == -ENOEXEC && bprm->mm) {
1418 if (printable(bprm->buf[0]) && printable(bprm->buf[1]) &&
1419 printable(bprm->buf[2]) && printable(bprm->buf[3]))
1420 return retval;
1421 request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2));
1422 need_retry = false;
1423 goto retry;
1424 }
1425
1432 return retval; 1426 return retval;
1433} 1427}
1434EXPORT_SYMBOL(search_binary_handler); 1428EXPORT_SYMBOL(search_binary_handler);