Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:30035
HistoryNov 26, 2013 - 12:00 a.m.

XADV-2013006 FreeBSD <= 10 kernel qlxge/qlxgbe Driver IOCTL Multiple Kernel Memory Leak Bugs

2013-11-2600:00:00
vulners.com
15

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. It's the
vulnerability class of the Information disclosure.

  1. 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&#40;static kmem&#41; to userspace with 
			       *     mpi_dump-&gt;size&#40;arg&#41;. 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... &#40;the kmem&#41;
                   *     kmem to userspace &#40;kmem leak occured!&#41;
                   */

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;

  1. 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 = &#40;qla_rd_fw_dump_t *&#41;data;
  •   if &#40;fw_dump-&gt;template_size &lt; ha-&gt;hw.dma_buf.minidump.size&#41;
    
  •   	return &#40;EINVAL&#41;;
    
  •   else
    
  •   	fw_dump-&gt;template_size = ha-&gt;hw.dma_buf.minidump.size;
      if &#40;&#40;rval = copyout&#40;ha-&gt;hw.dma_buf.minidump.dma_b,
      	fw_dump-&gt;md_template, fw_dump-&gt;template_size&#41;&#41;&#41;
      	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&#40;ha&#41;;
    
  •   		rval = copyout&#40; &amp;ql_mpi_coredump,
    
  •   				mpi_dump-&gt;dbuf,
    
  •   				mpi_dump-&gt;size&#41;;
    
  •   		mpi_dump-&gt;size = sizeof&#40;qls_mpi_coredump_t&#41;;
    
  •   		if &#40;qls_mpi_core_dump&#40;ha&#41; == 0&#41; {
    
  •   			rval = copyout&#40; &amp;ql_mpi_coredump,
    
  •   					mpi_dump-&gt;dbuf,
    
  •   					mpi_dump-&gt;size&#41;;
    
  •   		} else
    
  •   			rval = ENXIO;
    
      		if &#40;rval&#41; {
      			device_printf&#40;ha-&gt;pci_dev,
    

  1. 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