Bug 1715501 (CVE-2019-12381) - CVE-2019-12381 kernel: unchecked kmalloc of new_ra in ip_ra_control leads to denial of service
Summary: CVE-2019-12381 kernel: unchecked kmalloc of new_ra in ip_ra_control leads to ...
Alias: CVE-2019-12381
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
Target Milestone: ---
Assignee: Red Hat Product Security
QA Contact:
Depends On: 1715502
Blocks: 1715562
TreeView+ depends on / blocked
Reported: 2019-05-30 13:57 UTC by msiddiqu
Modified: 2021-02-16 21:53 UTC (History)
44 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
A flaw was discovered in the Linux kernel that allows an attacker to crash a system under low-memory free conditions in the ipv4 router advertisement code. The attacker must be able to send 'router advertisements' which limits the attack vector to be on the same physical segment.
Clone Of:
Last Closed: 2019-11-20 14:12:35 UTC

Attachments (Terms of Use)

Description msiddiqu 2019-05-30 13:57:46 UTC
An issue was discovered in ip_ra_control in net/ipv4/ip_sockglue.c in the Linux kernel.  During low memory conditions a memory allocation may fail which could allow an attacker to cause a denial of service (NULL pointer dereference and possibly a system crash).

Upstream patch: 




Comment 1 msiddiqu 2019-05-30 13:58:04 UTC
Created kernel tracking bugs for this issue:

Affects: fedora-all [bug 1715502]

Comment 5 Wade Mealing 2019-06-20 06:27:50 UTC
Investigation (Paraphrased):

The declared NULL ptr dereference within this function can not happen.

Reporting below the relevant code (pretty much unchanged since Red Hat Enterprise Linux 5  at its introduction):

        new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
	/* ^^^^ this is where it apparently can fail */

        for (rap = &net->ipv4.ra_chain;
             (ra = rcu_dereference_protected(*rap,
                        lockdep_is_held(&net->ipv4.ra_mutex))) != NULL;
             rap = &ra->next) {
                if (ra->sk == sk) {
                        if (on) {
                                kfree(new_ra); /* *************** kfree() would deal with a null here */
                                return -EADDRINUSE;
                        /* dont let ip_call_ra_chain() use sk again */
                        ra->sk = NULL;
                        RCU_INIT_POINTER(*rap, ra->next);

                        if (ra->destructor)
                         * Delay sock_put(sk) and kfree(ra) after one rcu grace
                         * period. This guarantee ip_call_ra_chain() dont need
                         * to mess with socket refcounts.
                        ra->saved_sk = sk;
                        call_rcu(&ra->rcu, ip_ra_destroy_rcu);
                        return 0;
        if (!new_ra) { /* ******* this is the null check that was believed to be missing, it bails here if null*/
                return -ENOBUFS;
        new_ra->sk = sk; /* THis part will never be executed/run if new_ra is null */
        new_ra->destructor = destructor; /* this part will never be dereferenced if new_ra is null */

Since kfree() is designed to handle correctly even NULL ptr, the above derefences of new_ra can not happen as they are protected by the immediate check above them.

Red Hat is open to discussion on this flaw if you have an an additional vector within the code please dont hesitate to put a discussion here and set NEEDINFO on wmealing.


Comment 6 dongyang626 2019-07-23 06:02:02 UTC
Hi Wade,

I have the same question with you. I can't find the risk from the new_ra as a C developer, if the 'new_ra = NULL', it will be checked before it is used. 
But I saw the linux-stable had merged this patch. The kernel maintainers may have a reason to do this. 
I'm not familiar about the 'NULL pointer dereference', maybe the attacker can use this?  

I really want to know the risk of this CVE. 
Anyone can help to explain?  Thanks a lot!

Best Regards,

Note You need to log in before you can comment on or make changes to this bug.