NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/44470: opencrypto kernel implementation may pass outdated argument to worker



>Number:         44470
>Category:       kern
>Synopsis:       opencrypto kernel implementation may pass outdated argument to 
>worker
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Jan 26 16:20:01 +0000 2011
>Originator:     Dr. Wolfgang Stukenbrock
>Release:        NetBSD 5.1
>Organization:
Dr. Nagler & Company GmbH
>Environment:
        
        
System: NetBSD test-s0 4.0 NetBSD 4.0 (NSW-WS) #0: Tue Aug 17 17:28:09 CEST 
2010 wgstuken@test-s0:/usr/src/sys/arch/amd64/compile/NSW-WS amd64
Architecture: x86_64
Machine: amd64
>Description:
        In /usr/src/sys/opencrypto/crypto.c the crypto-requests are scheduled 
to the different
        sessions (for e.g. the software implementation in cryptosoft.c).
        This is done in crypto_kinvoke() without the crypto_mtx and in 
crypto_invoke() only
        with parts of the access to the common structures with crypto_mtx 
locked.
        If another call modifies the list of drivers while a request is 
scheduled, the data in
        the selected entry may get invalid and so either garbage is passes in 
crypto_invoke() to the
        process routine or garbage may be called and/or passed in 
crypto_kinvoke().
>How-To-Repeat:
        Found by a look into the sources.
>Fix:
        The following patch will fix this problem.
        For crypto_kinvoke() the mutex is allocated while the driver list is 
searched and the
        required pointers are transfered into local variables prior releasing 
the mutex again.
        For crypto_invoke() also the args pointer is copied into a local 
variable.

        For performance reason someone should think about an other strategie 
for calling the invoke routines
        as it is at the moment. Currently the crypto_mtx is released prio 
calling the routine and
        the routine gets it back after only a few security checks. Perhaps it 
would be faster to hold
        the mutex when calling the invoke() routine and return with mutex 
released.
        I'm not shure if this may conflict with the "crypto_timing" part in 
crypto_invoke(), so I do not change
        this.

--- crypto.c    2011/01/26 15:47:51     1.1
+++ crypto.c    2011/01/26 16:05:52
@@ -833,6 +833,8 @@
 {
        u_int32_t hid;
        int error;
+       int (*process)(void*, struct cryptkop *, int);
+       void *arg;
 
        /* Sanity checks. */
        if (krp == NULL)
@@ -843,6 +845,7 @@
                return EINVAL;
        }
 
+       mutex_spin_enter(&crypto_mtx);
        for (hid = 0; hid < crypto_drivers_num; hid++) {
                if ((crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE) &&
                    crypto_devallowsoft == 0)
@@ -855,10 +858,13 @@
                break;
        }
        if (hid < crypto_drivers_num) {
+               process = crypto_drivers[hid].cc_kprocess;
+               arg = crypto_drivers[hid].cc_karg;
+               mutex_spin_exit(&crypto_mtx);
                krp->krp_hid = hid;
-               error = crypto_drivers[hid].cc_kprocess(
-                               crypto_drivers[hid].cc_karg, krp, hint);
+               error = (*process)(arg, krp, hint);
        } else {
+               mutex_spin_exit(&crypto_mtx);
                error = ENODEV;
        }
 
@@ -901,6 +907,7 @@
 {
        u_int32_t hid;
        int (*process)(void*, struct cryptop *, int);
+       void *arg;
 
 #ifdef CRYPTO_TIMING
        if (crypto_timing)
@@ -924,6 +931,7 @@
                if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_CLEANUP)
                        crypto_freesession(crp->crp_sid);
                process = crypto_drivers[hid].cc_process;
+               arg = crypto_drivers[hid].cc_arg;
                mutex_spin_exit(&crypto_mtx);
        } else {
                process = NULL;
@@ -954,7 +962,7 @@
                 * Invoke the driver to process the request.
                 */
                DPRINTF(("calling process for %08x\n", (uint32_t)crp));
-               return (*process)(crypto_drivers[hid].cc_arg, crp, hint);
+               return (*process)(arg, crp, hint);
        }
 }

>Unformatted:
        
        


Home | Main Index | Thread Index | Old Index