Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Thu, 26 Nov 2015 00:14:16 +0100
From: Salva Peiró <>
Subject: On techniques for preventing commit_creds() user-space abuse

A complete version of the technique can be found at

# Analysis

Given the typical path for kernel exploitation is the
`commit_creds(prepare_kernel_cred(0))` being called from user space as
detailed in [References].
Why is not a check placed in commit_creds() that checks the return address
of the call to ensure the call is a legit one coming from kernel space?.

This blocks direct calls to commit_creds from user space,
however, it remains vulnerable to alternative exploit routes.
The alternatives to bypass this protection are:

- *Indirect jump*
An attacker can perform an indirect jump to a kernel location that does
the commit_creds() for him, but it complicates the task of the
attacker. To prevent indirect calls check the rest of the stack trace.

- *Direct override*
Another route to bypass would be to figure out the location of the
process creds in memory, and perform the change directly in memory,
but AFAIK SMAP and its ARM equivalent would deter this route.

Therefore, I started implementing some exploits for testing it,
and implemented the `commit_cred` protection checks technique to
check if it is viable for preventing the commit_creds abuse.

The [Implementation] provides a patch that implements the discussed
The [Evaluation] provides the tests performed showing it effectively
blocks commit_creds abuse from user space.

# Threat Model

The steps involved in commit_creds() exploits:

- Prepare user code to get root:
    user_addr = commit_creds(prepare_creds(0))

- Override kernel code with:
    kernel_struct.fptr = user_addr  (1st vuln point SMAP)

- Trigger a syscall that calls kernel_struct.fptr
    - Invoke syscall from user
    - Results in kernel_struct.fptr() being called
        Calls user-space code from kernel code
            (2nd vuln point this point we're already toasted SMEP)
        Then call commit_creds (kernel_code) from user
            At this point the can detect commit_creds called from user
           (3rd vuln: fix check return address)

# Implementation

The patch implementing the commit_creds() abuse prevention:

From: Salva Peiró <speirofr AT>
Date: Wed, 25 Nov 2015 14:03:50 +0100
Subject: [PATCH] cred: Prevent commit_creds() user-space abuse

Signed-off-by: Salva Peiró <speirofr AT>

 kernel/cred.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/kernel/cred.c b/kernel/cred.c
index 71179a0..7191db3 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -428,6 +428,13 @@ int commit_creds(struct cred *new)

+ /* block attempts to use commit_creds from user space */
+ if (__builtin_return_address(0) < PAGE_OFFSET) {
+ printk(KERN_ERR "CRED: BUG commit_creds called from user space\n");
+ WARN_ON(1);
+ return -1;
+ }

# Evaluation

The `dmesg(1)` output below shows the prevention of an exploit attempt
using [References] where commit_creds is being called from user-space.

[ 1979.132453] exploit[8549]: segfault at 0 ip 08048719 sp bf8ff430 error 6
in exploit[8048000+1000]
[ 1981.658186] BUG: commit_creds called from user space
[ 1981.658201] ------------[ cut here ]------------
[ 1981.658207] WARNING: CPU: 0 PID: 8552 at kernel/cred.c:436
[ 1981.658209] Modules linked in: nullderef(O) nls_utf8 isofs udf crc_itu_

# References

- Much ado about NULL: Exploiting a kernel NULL dereference, by Nelson

Salva Peiró @

Content of type "text/html" skipped

View attachment "0001-cred-Prevent-commit_creds-user-space-abuse.patch" of type "text/x-patch" (1010 bytes)

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.