XADV-2013006
FreeBSD <= 10 kernel qlxge/qlxgbe Driver IOCTL Multiple Kernel Memory Leak Bugs
1. Overview
The qlxge Driver is Qlogic 10Gb Ethernet Driver for Qlogic 8100
Series CNA Adapter [1]. The qlxgbe for the QLogic 8300 series
of the same ethernet driver.
The qlxge/qlxgbe Driver in freebsd <= 10 has vulnerabilities to leak
arbitrary kernel memory to the userspace. It's occured at qls_eioctl()
/ ql_eioctl() kernel function and because no sanity check.
* Vulnerable Source Code:
- qlxge: http://fxr.watson.org/fxr/source/dev/qlxge/qls_ioctl.c?v=FREEBSD10
- qlxgbe: http://fxr.watson.org/fxr/source/dev/qlxgbe/ql_ioctl.c?v=FREEBSD10
* Credit:
- x90c <[email protected]>
(site: http://www.x90c.org)
* References:
[1] http://fxr.watson.org/fxr/source/dev/qlxge/README.txt?v=FREEBSD10
[2] http://fxr.watson.org/fxr/source/dev/ath/if_ath.c?v=FREEBSD10#L5881
2. Details
2.1 The vulerability for the qlxge driver
[/dev/qlxge/qls_ioctl.c?v=FREEBSD10#L80]
----
...
40 #include "qls_ioctl.h"
41 #include "qls_dump.h"
42 extern qls_mpi_coredump_t ql_mpi_coredump; // XXX The leak kmem!
43
44 static int qls_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
45 struct thread *td);
46
47 static struct cdevsw qla_cdevsw = {
48 .d_version = D_VERSION,
49 .d_ioctl = qls_eioctl, // XXX qls_eioctl.
50 .d_name = "qlxge",
51 };
52
...
80 static int
81 qls_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
82 struct thread *td)
83 {
84 qla_host_t *ha;
85 int rval = 0;
86 device_t pci_dev;
87
88 qls_mpi_dump_t *mpi_dump;
89
90 if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
91 return ENXIO;
92
93 pci_dev= ha->pci_dev;
94
95 switch(cmd) {
96
97 case QLA_MPI_DUMP:
98 mpi_dump = (qls_mpi_dump_t *)data; // mpi_dump = data(arg).
99
100 if (mpi_dump->size == 0) {
101 mpi_dump->size = sizeof (qls_mpi_coredump_t);
102 } else { // XXX mpi_dump->size > 0?
103 if (mpi_dump->size < sizeof (qls_mpi_coredump_t))
104 rval = EINVAL;
105 else { // XXX mpi_dump_size > qls_mpi_coredump_t struct size?
106 qls_mpi_core_dump(ha);
/* XXX copy ql_mpi_coredump(static kmem) to userspace with
* mpi_dump->size(arg). Kernel memory leak occured!
*/
107 rval = copyout( &ql_mpi_coredump,
108 mpi_dump->dbuf,
109 mpi_dump->size);
----
2.2 The vulerability for the qlxgbe driver
[/dev/qlxgbe/ql_ioctl.c?v=FREEBSD10#L79]
----
46 static struct cdevsw qla_cdevsw = {
47 .d_version = D_VERSION,
48 .d_ioctl = ql_eioctl, /* XXX ql_eioctl! */
49 .d_name = "qlcnic",
50 };
...
79 static int
80 ql_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
81 struct thread *td)
82 {
83 qla_host_t *ha;
...
90 qla_rd_fw_dump_t *fw_dump;
91 union {
92 qla_reg_val_t *rv;
93 qla_rd_flash_t *rdf;
94 qla_wr_flash_t *wrf;
95 qla_erase_flash_t *erf;
96 qla_offchip_mem_val_t *mem;
97 } u;
98
99
100 if ((ha = (qla_host_t *)dev->si_drv1) == NULL) /* XXX ha = dev->si_drv1. */
101 return ENXIO;
102
...
105 switch(cmd) {
106
...
218 case QLA_RD_FW_DUMP: /* XXX QLA_RD_FW_DUMP ioctl cmd */
219
220 if (ha->hw.mdump_init == 0) {
221 rval = EINVAL;
222 break;
223 }
224
225 fw_dump = (qla_rd_fw_dump_t *)data; // XXX fw_dump = data(arg)
/* XXX no sanity check and copy arbitrary ha... (the kmem)
* kmem to userspace (kmem leak occured!)
*/
226 if ((rval = copyout(ha->hw.dma_buf.minidump.dma_b,
227 fw_dump->md_template, fw_dump->template_size)))
228 rval = ENXIO;
229 break;
----
3. Patch code
[freebsd_qlxge_kmem_leak.patch]
----
+ if(mpi_dump->size > sizeof(qls_mpi_coredump_t))
+ return EINVAL;
rval = copyout( &ql_mpi_coredump,
mpi_dump->dbuf,
mpi_dump->size);
----
[freebsd_qlxgbe_kmem_leak.patch]
----
+ if(fw_dump->template_size > sizeof(qla_host_t))
+ return EINVAL;
if ((rval = copyout(ha->hw.dma_buf.minidump.dma_b,
fw_dump->md_template, fw_dump->template_size)))
----
There's the vendor patch code.
[qlxg.diff]
----
Index: sys/dev/qlxgbe/ql_ioctl.c
===================================================================
--- sys/dev/qlxgbe/ql_ioctl.c (revision 258154)
+++ sys/dev/qlxgbe/ql_ioctl.c (working copy)
@@ -223,6 +223,10 @@ ql_eioctl(struct cdev *dev, u_long cmd, caddr_t da
}
fw_dump = (qla_rd_fw_dump_t *)data;
+ if (fw_dump->template_size < ha->hw.dma_buf.minidump.size)
+ return (EINVAL);
+ else
+ fw_dump->template_size = ha->hw.dma_buf.minidump.size;
if ((rval = copyout(ha->hw.dma_buf.minidump.dma_b,
fw_dump->md_template, fw_dump->template_size)))
rval = ENXIO;
Index: sys/dev/qlxge/qls_ioctl.c
===================================================================
--- sys/dev/qlxge/qls_ioctl.c (revision 258154)
+++ sys/dev/qlxge/qls_ioctl.c (working copy)
@@ -103,10 +103,13 @@ qls_eioctl(struct cdev *dev, u_long cmd, caddr_t d
if (mpi_dump->size < sizeof (qls_mpi_coredump_t))
rval = EINVAL;
else {
- qls_mpi_core_dump(ha);
- rval = copyout( &ql_mpi_coredump,
- mpi_dump->dbuf,
- mpi_dump->size);
+ mpi_dump->size = sizeof(qls_mpi_coredump_t);
+ if (qls_mpi_core_dump(ha) == 0) {
+ rval = copyout( &ql_mpi_coredump,
+ mpi_dump->dbuf,
+ mpi_dump->size);
+ } else
+ rval = ENXIO;
if (rval) {
device_printf(ha->pci_dev,
----
4. Vendor Status
- 2013/11/12 I discovered two kernel memory leaks.
- 2013/11/14 Report to the vendor of [email protected]
- 2013/11/15 The vendor response with the coordination
with the vendor patch code. (will be freebsd's advisory)
- 2013/11/16 Cve-id for each bug request to the [email protected]
- 2013/11/16 The original advisory released on full-disclosure, bugtraq.
EOF
# 0day.today [2018-04-08] #Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation