Merge from NetBSD r1.54 from Matthias Drochner:
authormpi <mpi@openbsd.org>
Thu, 18 Dec 2014 10:51:35 +0000 (10:51 +0000)
committermpi <mpi@openbsd.org>
Thu, 18 Dec 2014 10:51:35 +0000 (10:51 +0000)
--
kick out the error-prone handcrafted single-linked list of cardbus
functions; replace by a simple *array[8]
--

In other words, prevent a use after free when removing a cardbus
function.

ok deraadt@, miod@

sys/dev/cardbus/cardbus.c
sys/dev/cardbus/cardbusvar.h

index f7fb7b0..fad7ef7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cardbus.c,v 1.48 2014/09/14 14:17:24 jsg Exp $        */
+/*     $OpenBSD: cardbus.c,v 1.49 2014/12/18 10:51:35 mpi Exp $        */
 /*     $NetBSD: cardbus.c,v 1.24 2000/04/02 19:11:37 mycroft Exp $     */
 
 /*
@@ -130,8 +130,6 @@ cardbusattach(struct device *parent, struct device *self, void *aux)
        sc->sc_rbus_iot = cba->cba_rbus_iot;
        sc->sc_rbus_memt = cba->cba_rbus_memt;
 
-       sc->sc_funcs = NULL;
-
        cdstatus = 0;
 }
 
@@ -378,7 +376,6 @@ cardbus_attach_card(struct cardbus_softc *sc)
        pcireg_t bhlc;
        u_int8_t *tuple;
        int function, nfunction;
-       struct cardbus_devfunc **previous_next = &(sc->sc_funcs);
        struct device *csc;
        int no_work_funcs = 0;
        cardbus_devfunc_t ct;
@@ -496,8 +493,7 @@ cardbus_attach_card(struct cardbus_softc *sc)
                ct->ct_dev = sc->sc_device;
                ct->ct_func = function;
                ct->ct_sc = sc;
-               ct->ct_next = NULL;
-               *previous_next = ct;
+               sc->sc_funcs[function] = ct;
 
                memset(&ca, 0, sizeof(ca));
 
@@ -536,11 +532,10 @@ cardbus_attach_card(struct cardbus_softc *sc)
                    cardbussubmatch)) == NULL) {
                        /* do not match */
                        disable_function(sc, function);
+                       sc->sc_funcs[function] = NULL;
                        free(ct, M_DEVBUF, 0);
-                       *previous_next = NULL;
                } else {
                        /* found */
-                       previous_next = &(ct->ct_next);
                        ct->ct_device = csc;
                        ++no_work_funcs;
                }
@@ -605,25 +600,24 @@ cardbusprint(void *aux, const char *pnp)
 void
 cardbus_detach_card(struct cardbus_softc *sc)
 {
-       struct cardbus_devfunc *ct, *ct_next, **prev_next;
-
-       prev_next = &(sc->sc_funcs->ct_next);
+       struct cardbus_devfunc *ct;
+       int f;
 
-       for (ct = sc->sc_funcs; ct != NULL; ct = ct_next) {
-               struct device *fndev = ct->ct_device;
-               ct_next = ct->ct_next;
+       for (f = 0; f < 8; f++) {
+               ct = sc->sc_funcs[f];
+               if (ct == NULL)
+                       continue;
 
                DPRINTF(("%s: detaching %s\n", sc->sc_dev.dv_xname,
-                   fndev->dv_xname));
-               /* call device detach function */
+                   ct->ct_device->dv_xname));
 
-               if (config_detach(fndev, 0) != 0) {
+               if (config_detach(ct->ct_device, 0) != 0) {
                        printf("%s: cannot detach dev %s, function %d\n",
-                           sc->sc_dev.dv_xname, fndev->dv_xname, ct->ct_func);
-                       prev_next = &(ct->ct_next);
+                           sc->sc_dev.dv_xname, ct->ct_device->dv_xname,
+                           ct->ct_func);
                } else {
                        sc->sc_poweron_func &= ~(1 << ct->ct_func);
-                       *prev_next = ct->ct_next;
+                       sc->sc_funcs[ct->ct_func] = NULL;
                        free(ct, M_DEVBUF, 0);
                }
        }
index e6650d6..aa4f9e4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cardbusvar.h,v 1.19 2010/03/27 23:36:36 jsg Exp $     */
+/*     $OpenBSD: cardbusvar.h,v 1.20 2014/12/18 10:51:35 mpi Exp $     */
 /*     $NetBSD: cardbusvar.h,v 1.17 2000/04/02 19:11:37 mycroft Exp $  */
 
 /*
@@ -136,8 +136,7 @@ struct cardbus_softc {
 #define PCCARD_XXV  0x04
 #define PCCARD_YYV  0x08
        int sc_poweron_func;
-       struct cardbus_devfunc *sc_funcs;
-                                       /* list of cardbus device functions */
+       struct cardbus_devfunc *sc_funcs[8];    /* cardbus device functions */
 };