Bug 1180564 (CVE-2021-20226)

Summary: VUL-0: CVE-2021-20226: kernel-source,kernel-source-rt,kernel-source-azure: privilege escalation due to use after free in io_uring
Product: [Novell Products] SUSE Security Incidents Reporter: Alexandros Toptsoglou <atoptsoglou>
Component: IncidentsAssignee: Security Team bot <security-team>
Status: RESOLVED FIXED QA Contact: Security Team bot <security-team>
Severity: Major    
Priority: P2 - High CC: aherrmann, bpetkov, carlos.lopez, carnil, jack, jkosina, meissner, mhocko, smash_bz
Version: unspecified   
Target Milestone: ---   
Hardware: Other   
OS: Other   
URL: https://smash.suse.de/issue/274506/
Whiteboard:
Found By: Security Response Team Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description Alexandros Toptsoglou 2021-01-05 10:06:52 UTC
ZDI-21-001

This vulnerability allows local attackers to escalate privileges on affected
installations of Linux Kernel. An attacker must first obtain the ability to
execute low-privileged code on the target system in order to exploit this
vulnerability.

The specific flaw exists within the handling of file descriptors in io_uring.
The issue results from the lack of validating the existence of an object prior
to performing operations on the object. An attacker can leverage this
vulnerability to escalate privileges and execute code in the context of the
kernel.

Fixed in version 5.10.2

References:
https://www.zerodayinitiative.com/advisories/ZDI-21-001/
Comment 2 Jan Kara 2021-01-05 15:47:48 UTC
Hum, I've searched the web for more details but failed. Also "Fixed in version 5.10.2" may be a correct statement but almost certainly reporters were lazy to figure out when the problem got actually fixed because 5.10.2 nor 5.10.1 have any io_uring fixes AFAICT. Honestly, such vague reports are pretty useless and waste our time...

I *suspect* they talk about 0f2122045b94 "io_uring: don't rely on weak ->files references". The timing of the commit and report time roughly match and the subject area as well. But it's impossible to be sure.

If it is indeed that commit, none of our kernels is affected as the problem started in 5.5 kernel and got fixed in 5.10.
Comment 3 Jan Kara 2021-01-05 15:53:19 UTC
Hum, is ZDI the same thing as Project zero? I guess not but commit 0f2122045b94 was a result of a bug found by Project zero and already handled by us in bug 1179598.
Comment 4 Marcus Meissner 2021-01-05 16:21:05 UTC
They are not the same. 

It still might be a parallel finding though.
Comment 5 Alexandros Toptsoglou 2021-02-05 15:21:02 UTC
*** Bug 1181846 has been marked as a duplicate of this bug. ***
Comment 6 Salvatore Bonaccorso 2021-02-07 13:26:32 UTC
Hi

I tried to get more details/information here: https://www.openwall.com/lists/oss-security/2021/02/05/7 (trying to assemble more from the given timeline and the Red Hat bugreport itself).

But not sure if this is correct.

Regards,
Salvatore
Comment 8 Marcus Meissner 2021-02-08 07:07:54 UTC
The amount of io_uring syzkaller and other reports is quite high, and the fix might be hidden within this list :( 


Have you tried reaching out to the researcher Salvatore?
Comment 9 Salvatore Bonaccorso 2021-02-08 09:07:28 UTC
Hi Markus

I got a reply from Red Hat in https://bugzilla.redhat.com/show_bug.cgi?id=1873476#c16

Salvatore
Comment 10 Marcus Meissner 2021-02-08 09:21:13 UTC
Thanks! Relevant comment from RH Bugzilla:

Rohit Keshri 2021-02-08 07:20:10 UTC

Hello Salvatore

The affected source in fs/io_uring.c was last modified with 233295130e53 patch in the upstream from v5.10 onward as a "clean up code", where the affected source was removed from the later versions of this tree. (As this was reported for 5.7.0)
~~~~
static int io_grab_files(struct io_kiocb *req)
{
	int ret = -EBADF;
	struct io_ring_ctx *ctx = req->ctx;

	if (req->work.files || (req->flags & REQ_F_NO_FILE_TABLE))
		return 0;
	if (!ctx->ring_file)
		return -EBADF;

	rcu_read_lock();
	spin_lock_irq(&ctx->inflight_lock);
	/*
	 * We use the f_ops->flush() handler to ensure that we can flush
	 * out work accessing these files if the fd is closed. Check if
	 * the fd has changed since we started down this path, and disallow
	 * this operation if it has.
	 */
	if (fcheck(ctx->ring_fd) == ctx->ring_file) {
		list_add(&req->inflight_entry, &ctx->inflight_list);
		req->flags |= REQ_F_INFLIGHT;
		req->work.files = current->files;		<-- referenced but did not update reference count
		ret = 0;
	}
	spin_unlock_irq(&ctx->inflight_lock);
	rcu_read_unlock();

	return ret;
}
~~~


$ git show 233295130e53
commit 233295130e53c8dfe6dbef3f52634c3f7e44cd6a
Author: Pavel Begunkov <asml.silence@gmail.com>
Date:   Sat Oct 10 18:34:06 2020 +0100

    io_uring: clean up ->files grabbing
    
    Move work.files grabbing into io_prep_async_work() to all other work
    resources initialisation. We don't need to keep it separately now, as
    ->ring_fd/file are gone. It also allows to not grab it when a request
    is not going to io-wq.
..

$ git tag --contains 233295130e53
v5.10
v5.10-rc1
v5.10-rc2
v5.10-rc3
v5.10-rc4
v5.10-rc5
v5.10-rc6
v5.10-rc7
v5.11-rc1
v5.11-rc2
v5.11-rc3
v5.11-rc4
v5.11-rc5
v5.11-rc6
v5.11-rc7

This flaw is identified as a use-after-free problem, which may escalate privileges with good knowledge of kernel debug information.
Comment 11 Jan Kara 2021-02-08 10:56:33 UTC
OK, so commit 233295130e53 "io_uring: clean up ->files grabbing" cleans up code that already seems to be fixed (it has already get_files_struct() call instead of plain pointer assignment). Code shown directly in comment 10 was in io_uring only before commit 0f2122045b94 "io_uring: don't rely on weak ->files references" which fixed that particular problem with struct files_struct use after free. So I guess it's indeed the same culprit as already reported a handled in bug 1179598.
Comment 15 Carlos López 2022-06-09 08:37:26 UTC
Done, closing.