lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Thu, 24 Feb 2022 08:17:52 +0900 From: Levi Yun <ppbuk5246@...il.com> To: keescook@...omium.org, ebiederm@...ssion.com, viro@...iv.linux.org.uk Cc: linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org, Levi Yun <ppbuk5246@...il.com> Subject: [PATCH] fs/exec.c: Avoid a race in formats Suppose a module registers its own binfmt (custom) and formats is like: +---------+ +----------+ +---------+ | custom | -> | format1 | -> | format2 | +---------+ +----------+ +---------+ and try to call unregister_binfmt with custom NOT in __exit stage. In that situation, below race scenario can happen. CPU 0 CPU1 search_binary_handler ... read_lock unregister_binfmt(custom) list_for_each_entry < wait > (get custom binfmt) ... read_unlock ... ... list_del custom binfmt return -ENOEXEC get next fmt entry (LIST_POISON1) Because CPU1 set the fmt->lh.next as LIST_POISON1, CPU 0 get next binfmt as LIST_POISON1. In that situation, CPU0 try to dereference LIST_POISON1 address and makes PANIC. To avoid this situation, check the fmt is valid. And if it isn't valid, return -EAGAIN. Signed-off-by: Levi Yun <ppbuk5246@...il.com> --- fs/exec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index 79f2c9483302..2042a1232656 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1720,6 +1720,12 @@ static int search_binary_handler(struct linux_binprm *bprm) retry: read_lock(&binfmt_lock); list_for_each_entry(fmt, &formats, lh) { + if (fmt == LIST_POISON1) { + read_unlock(&binfmt_lock); + retval = -EAGAIN; + break; + } + if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); -- 2.34.1
Powered by blists - more mailing lists