diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-09-11 17:24:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-11 18:59:05 -0400 |
commit | cb7b6b1cbc20a970c7124efae1c2478155604b54 (patch) | |
tree | ef0e867017f0a6fea23ebdcd87753174a4c75a25 | |
parent | 92eaa565add62d56b90987f58ea9feafc5a7c183 (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.c | 68 |
1 files changed, 31 insertions, 37 deletions
@@ -1367,13 +1367,15 @@ out: | |||
1367 | } | 1367 | } |
1368 | EXPORT_SYMBOL(remove_arg_zero); | 1368 | EXPORT_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 | */ |
1373 | int search_binary_handler(struct linux_binprm *bprm) | 1374 | int 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 | } |
1434 | EXPORT_SYMBOL(search_binary_handler); | 1428 | EXPORT_SYMBOL(search_binary_handler); |