From: Jann Horn <jann@thejh.net> To: kernel-hardening@lists.openwall.com, linux-kernel@vger.kernel.org Cc: Andrew Morton <akpm@linux-foundation.org>, HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>, Vitaly Kuznetsov <vkuznets@redhat.com>, Baoquan He <bhe@redhat.com>, Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Subject: [RFC] kernel/panic: place an upper limit on number of oopses Date: Tue, 12 Jan 2016 20:25:45 +0100 [thread overview] Message-ID: <1452626745-31708-1-git-send-email-jann@thejh.net> (raw) To prevent an attacker from turning a mostly harmless oops into an exploitable issue using a refcounter wraparound caused by repeated oopsing, limit the number of oopses. I have not experimentally verified whether the attack I describe in the comment works, but I don't see why it wouldn't. (f_count increments through fget() use atomic_long_inc_not_zero(), but get_file() just does a normal increment and is e.g. used by dup_fd().) This approach is strictly inferior to PAX_REFCOUNT, but as long as that's not upstreamed and turned on by default, it might make sense to at least use this patch. Opinions? Signed-off-by: Jann Horn <jann@thejh.net> --- kernel/panic.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/kernel/panic.c b/kernel/panic.c index 4b150bc..27a480d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -422,9 +422,37 @@ void print_oops_end_marker(void) */ void oops_exit(void) { + static atomic_t oops_counter = ATOMIC_INIT(0); + do_oops_enter_exit(); print_oops_end_marker(); kmsg_dump(KMSG_DUMP_OOPS); + + /* + * Every time the system oopses, if the oops happens while a + * reference to an object was held (e.g. in a VFS function), + * the reference leaks. If the oops doesn't also leak memory, + * repeated oopsing can cause the reference counter to wrap + * around - in particular, on 32bit systems, f_count in + * struct file is only 32 bits long and can realistically + * wrap around. + * This means that an oops, even if it's just caused by an + * unexploitable-looking NULL pointer dereference or so, + * could maybe be turned into a use-after-free through a + * counter overincrement, and a use-after-free might be + * exploitable. + * To reduce the probability that this happens, place an + * upper bound on how often the kernel may oops - after this + * limit is reached, just panic. + * The constant used as limit should be low enough to + * mitigate this kind of exploitation attempt, but high + * enough to avoid unnecessary panics. + */ + if (atomic_inc_return(&oops_counter) >= 0x100000 && + panic_on_oops == 0) { + pr_emerg("oopsed too often, setting panic_on_oops=1\n"); + panic_on_oops = 1; + } } #ifdef WANT_WARN_ON_SLOWPATH -- 2.1.4
WARNING: multiple messages have this Message-ID (diff)
From: Jann Horn <jann@thejh.net> To: kernel-hardening@lists.openwall.com, linux-kernel@vger.kernel.org Cc: Andrew Morton <akpm@linux-foundation.org>, HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>, Vitaly Kuznetsov <vkuznets@redhat.com>, Baoquan He <bhe@redhat.com>, Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Subject: [kernel-hardening] [RFC] kernel/panic: place an upper limit on number of oopses Date: Tue, 12 Jan 2016 20:25:45 +0100 [thread overview] Message-ID: <1452626745-31708-1-git-send-email-jann@thejh.net> (raw) To prevent an attacker from turning a mostly harmless oops into an exploitable issue using a refcounter wraparound caused by repeated oopsing, limit the number of oopses. I have not experimentally verified whether the attack I describe in the comment works, but I don't see why it wouldn't. (f_count increments through fget() use atomic_long_inc_not_zero(), but get_file() just does a normal increment and is e.g. used by dup_fd().) This approach is strictly inferior to PAX_REFCOUNT, but as long as that's not upstreamed and turned on by default, it might make sense to at least use this patch. Opinions? Signed-off-by: Jann Horn <jann@thejh.net> --- kernel/panic.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/kernel/panic.c b/kernel/panic.c index 4b150bc..27a480d 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -422,9 +422,37 @@ void print_oops_end_marker(void) */ void oops_exit(void) { + static atomic_t oops_counter = ATOMIC_INIT(0); + do_oops_enter_exit(); print_oops_end_marker(); kmsg_dump(KMSG_DUMP_OOPS); + + /* + * Every time the system oopses, if the oops happens while a + * reference to an object was held (e.g. in a VFS function), + * the reference leaks. If the oops doesn't also leak memory, + * repeated oopsing can cause the reference counter to wrap + * around - in particular, on 32bit systems, f_count in + * struct file is only 32 bits long and can realistically + * wrap around. + * This means that an oops, even if it's just caused by an + * unexploitable-looking NULL pointer dereference or so, + * could maybe be turned into a use-after-free through a + * counter overincrement, and a use-after-free might be + * exploitable. + * To reduce the probability that this happens, place an + * upper bound on how often the kernel may oops - after this + * limit is reached, just panic. + * The constant used as limit should be low enough to + * mitigate this kind of exploitation attempt, but high + * enough to avoid unnecessary panics. + */ + if (atomic_inc_return(&oops_counter) >= 0x100000 && + panic_on_oops == 0) { + pr_emerg("oopsed too often, setting panic_on_oops=1\n"); + panic_on_oops = 1; + } } #ifdef WANT_WARN_ON_SLOWPATH -- 2.1.4
next reply other threads:[~2016-01-12 19:25 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-01-12 19:25 Jann Horn [this message] 2016-01-12 19:25 ` [kernel-hardening] [RFC] kernel/panic: place an upper limit on number of oopses Jann Horn 2016-01-12 23:34 ` Daniel Axtens 2016-01-12 23:34 ` [kernel-hardening] " Daniel Axtens 2016-01-12 23:51 ` Jann Horn 2016-01-12 23:51 ` [kernel-hardening] " Jann Horn 2016-01-13 0:20 ` Solar Designer 2016-01-13 0:20 ` [kernel-hardening] " Solar Designer 2016-01-13 0:33 ` Daniel Axtens 2016-01-13 0:33 ` [kernel-hardening] " Daniel Axtens 2016-01-13 18:08 ` Jann Horn 2016-01-13 18:08 ` [kernel-hardening] " Jann Horn 2016-01-17 3:58 ` Jann Horn
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1452626745-31708-1-git-send-email-jann@thejh.net \ --to=jann@thejh.net \ --cc=akpm@linux-foundation.org \ --cc=bhe@redhat.com \ --cc=d.hatayama@jp.fujitsu.com \ --cc=kernel-hardening@lists.openwall.com \ --cc=linux-kernel@vger.kernel.org \ --cc=masami.hiramatsu.pt@hitachi.com \ --cc=vkuznets@redhat.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.