Date: Fri, 22 Apr 2016 21:54:22 +0000 From: bugzilla-noreply@freebsd.org To: freebsd-bugs@FreeBSD.org Subject: [Bug 208985] DoS / heap overflow in bpf_stats_sysctl Message-ID: <bug-208985-8@https.bugs.freebsd.org/bugzilla/>
next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=208985 Bug ID: 208985 Summary: DoS / heap overflow in bpf_stats_sysctl Product: Base System Version: 11.0-CURRENT Hardware: Any OS: Any Status: New Severity: Affects Only Me Priority: --- Component: kern Assignee: freebsd-bugs@FreeBSD.org Reporter: cturt@hardenedbsd.org The `sysctl` handler for `net.bpf.stats`, `bpf_stats_sysctl`, calls `malloc` with an unchecked user supplied size and the `M_WAITOK` flag. sys/net/bpf.c: static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS) { static const struct xbpf_d zerostats; struct xbpf_d *xbdbuf, *xbd, tempstats; int index, error; struct bpf_if *bp; struct bpf_d *bd; /* * XXX This is not technically correct. It is possible for non * privileged users to open bpf devices. It would make sense * if the users who opened the devices were able to retrieve * the statistics for them, too. */ error = priv_check(req->td, PRIV_NET_BPF); if (error) return (error); ... xbdbuf = malloc(req->oldlen, M_BPF, M_WAITOK); BPF_LOCK(); if (req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd))) { BPF_UNLOCK(); free(xbdbuf, M_BPF); return (ENOMEM); } index = 0; LIST_FOREACH(bp, &bpf_iflist, bif_next) { BPFIF_RLOCK(bp); /* Send writers-only first */ LIST_FOREACH(bd, &bp->bif_wlist, bd_next) { xbd = &xbdbuf[index++]; BPFD_LOCK(bd); bpfstats_fill_xbpf(xbd, bd); BPFD_UNLOCK(bd); } LIST_FOREACH(bd, &bp->bif_dlist, bd_next) { xbd = &xbdbuf[index++]; BPFD_LOCK(bd); bpfstats_fill_xbpf(xbd, bd); BPFD_UNLOCK(bd); } BPFIF_RUNLOCK(bp); } BPF_UNLOCK(); error = SYSCTL_OUT(req, xbdbuf, index * sizeof(*xbd)); free(xbdbuf, M_BPF); return (error); } For the latest version of FreeBSD, the maximum impact of this is panic from supplying large enough sizes. For older releases of 64 bit FreeBSD (like 9.0) which truncate `malloc` sizes to 32 bit, a size like `0x100000004` will result in an allocation of 4 bytes, which will bypass the check for `(req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd)))` and then cause heap overflow by the `bpfstats_fill_xbpf` calls. Annoyingly, this function has a `priv_check` against `PRIV_NET_BPF`, even though it shouldn't! A comment in this function mentions that unprivileged users _should_ be able to call this function, and thus make use of the vulnerability: "This is not technically correct. It is possible for non privileged users to open bpf devices. It would make sense if the users who opened the devices were able to retrieve the statistics for them, too." Because of this the below code will only cause kernel panic when run as `root`: #include <sys/types.h> #include <sys/sysctl.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> int main(void) { int result; char *m = malloc(256); size_t l = 0x100000000; result = sysctlbyname("net.bpf.stats", m, &l, NULL, 0); printf("%d\n", result); printf("%d\n", errno); return 0; } -- You are receiving this mail because: You are the assignee for the bug.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-208985-8>
