Bug 1715459 (CVE-2019-12378)

Summary: CVE-2019-12378 kernel: unchecked kmalloc of new_ra in ip6_ra_control leads to denial of service
Product: [Other] Security Response Reporter: msiddiqu
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: acaringi, airlied, bhu, blc, brdeoliv, bskeggs, dhoward, dvlasenk, esammons, fhrbata, hdegoede, hkrzesin, iboverma, ichavero, itamar, jarodwilson, jeremy, jforbes, jglisse, jkacur, john.j5live, jonathan, josef, jross, jstancek, jwboyer, kernel-maint, kernel-mgr, labbott, lgoncalv, linville, matt, mchehab, mcressma, mjg59, mlangsdo, nmurray, pabeni, plougher, pmatouse, rt-maint, rvrbovsk, security-response-team, steved, williams, wmealing
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
A flaw was discovered in the Linux kernel's implementation of IPv6 router advertisement handling. Under low-memory-free conditions a kmalloc request may fail leaving the system to crash shortly after with a null pointer dereference. The attacker must be able to send IPv6 RA packets to this host, most routers will not forward these packets requiring the attacker to be on the local network.
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-11-20 14:13:57 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1715460, 1716777, 1716778, 1716779, 1716780, 1716781, 1716783    
Bug Blocks: 1715558    

Description msiddiqu 2019-05-30 12:24:52 UTC
A Denial Of Service (DOS) flaw was discovered in the Linux kernels implementation of IPV6 Router Advertisement handling.  Under low-memory-free conditions a kmalloc request may fail leaving the system to crash shortly after with a null pointer dereference. 

The attacker must be able to send IPV6 RA packets to this host, most routers will not foward these packets requiring the attacker to be on the local network.

Upstream patch:

https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git/commit/?id=95baa60a0da80a0143e3ddd4d3725758b4513825 

References:

https://lkml.org/lkml/2019/5/25/229

Comment 1 msiddiqu 2019-05-30 12:25:09 UTC
Created kernel tracking bugs for this issue:

Affects: fedora-all [bug 1715460]

Comment 4 Wade Mealing 2019-06-04 05:25:06 UTC
This flaw is rated as moderate as the exploit conditions required to force a system into 'low memory' externally would often results in local applications being terminated by the system out-of-memory handler (oomkiller) making this a very infeffective denial of service.

As these packets are also usually not-routed (link-local only) the attacker would need to be on the local network making them somewhat easy to trace.

Comment 7 Wade Mealing 2019-06-05 07:41:27 UTC
This looks as though suse was the reporter or at least where we got it from, Awaiting an answer from them before you should continue...

Comment 11 Wade Mealing 2019-06-19 00:55:50 UTC
Ive been involved in an email chain regarding this flaw.  The reporter was running a static code analysis software that had reported this flaw and the CVE was assigned.  He doesn't have an interest in either confirming or denying where this flaw takes place.

An email to mitre regarding retracting this CVE has been sent and no response has been made yet.

At this time Red Hat will not be consider this flaw to be valid and will not be fixing this issue.

Comment 12 Wade Mealing 2019-06-20 03:33:22 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 ):

        new_ra = (sel >= 0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
        // the "fix" adds here: 'if (sel >= 0 && !new_ra) return -ENOMEM;'

        write_lock_bh(&ip6_ra_lock);
        for (rap = &ip6_ra_chain; (ra = *rap) != NULL; rap = &ra->next) {
                if (ra->sk == sk) {
                        if (sel >= 0) {
                                write_unlock_bh(&ip6_ra_lock);
                                kfree(new_ra);
                                return -EADDRINUSE;
                        }

                        *rap = ra->next;
                        write_unlock_bh(&ip6_ra_lock);

                        sock_put(sk);
                        kfree(ra);
                        return 0;
                }
        }
        if (!new_ra) {
                write_unlock_bh(&ip6_ra_lock);
                return -ENOBUFS;
        }
        new_ra->sk = sk;
        new_ra->sel = sel;
        new_ra->next = ra;
        *rap = new_ra;
        sock_hold(sk);
        write_unlock_bh(&ip6_ra_lock);
        return 0;

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.

Thanks!