Hello,

here is a short patch that fixes a race condition when doing ioctl(2).

The race condition occurs when the user-thread executing the M_COPYIN dialog between a driver/module and the stream-head goes to sleep & is awakened by a signal.

This patch was written against LiS-2.15.0 but should probably apply without problem over a 2.16.x. Only head.c is affected.

Comments welcome.

-- FiX

--
Francois-Xavier "FiX" KOWALSKI     /_ __    Tel: +33 (0)4 76 14 63 27
OpenCall Business Unit -- OCBU    / //_/    Fax: +33 (0)4 76 14 43 23
Signalling Products                 /       HP Telnet: 779-6327
http://www.hp.com/go/opencall    i n v e n t

--- /vobs/tid/Opencall/Components/OCEK/code/LiS/head/head.c@@/main/ocekgre_hp/4 Mon 
Mar 24 10:04:12 2003
+++ head.c      Thu Mar 27 17:10:27 2003
@@ -2616,7 +2616,7 @@
        {                                       /* flush read queue */
            int         msgs_before = lis_qsize(q) ;
            int         psw ;
-           mblk_t      *xp ;
+           mblk_t      *xp, *tmp = NULL ;
 
            CP(mp,0) ;
            /*
@@ -2626,8 +2626,13 @@
            LIS_QISRLOCK(q, &psw) ;
            while ((xp = lis_get_rput_q(shead)) != NULL)
            {
-               msgs_before++ ;
-               freemsg(xp) ;
+               /*
+                * All messages are temporary saved in a local list.
+                * Correct action will be taken after flush is complete.
+                * Unqueueing now will preserves q_count value.
+                */
+               xp->b_next = tmp ;
+               tmp = xp ;
            }
            LIS_QISRUNLOCK(q, &psw) ;
 
@@ -2642,6 +2647,29 @@
                || !lis_hipri(shead->sd_rq->q_first->b_datap->db_type)
               )
                CLR_SD_FLAG(shead,STRPRI);      /* no PCPROTO at head */
+
+           /*
+            * Do not discard messages corresponding to
+            * an in-progress ioctl (IOCWAIT flag).
+            * Discarding them could let the ioctl sleeping for ever
+            * (unless timeout is activated)
+            * Re-queuing now (after flush) preserves q_count value.
+            */
+           LIS_QISRLOCK(q, &psw) ;
+           while ( (xp = tmp) != NULL )
+           {
+               tmp = xp->b_next ;
+               xp->b_next = NULL ;
+               if ( F_ISSET(shead->sd_flag, IOCWAIT) )
+                   lis_put_rput_q(shead, xp) ;
+               else
+               {
+                   msgs_before++ ;
+                   freemsg(xp) ;
+               }
+           }
+           LIS_QISRUNLOCK(q, &psw) ;
+
            *mp->b_rptr &= ~FLUSHR ;            /* turn off flush read bit */
            LisDownCounter(MSGQDSTRHD, msgs_before - lis_qsize(q)) ;
        }
@@ -3033,8 +3061,12 @@
     if (tmout == 0)
        tmout = LIS_DFLT_TIM ;
 
-    //    while( hd->sd_iocblk == NULL )
-    {
+    /*
+     * while( hd->sd_iocblk == NULL ) statement is removed.
+     * All the sleep/wakeup code is based on a semaphore.
+     * Sleep is called even if Wakeup has already popped.
+     * And the semaphore count is correctly updated.
+     */
        if ( F_ISSET(hd->sd_flag,(STRDERR|STWRERR)) )
            return(-hd->sd_rerror) ;
        SET_SD_FLAG(hd,STIOCTMR);
@@ -3063,7 +3095,7 @@
                lis_untmout(&tl);
            CLR_SD_FLAG(hd,STIOCTMR);
        }
-    }
+
     return(0);                 /* got msg */
 }/*lis_wait_for_wiocing*/
 
@@ -3208,6 +3240,14 @@
      * Use RTN to return below here.
      */
     iocb->ioc_id = hd->sd_iocseq =  lis_incr(&lis_iocseq);
+    /*
+     * Reset items that could be not clean after a previous failing ioctl
+     * (ioctl returning on signal or error)
+     * - semaphore > 0
+     * - sd_iocblk != NULL
+     */
+    lis_sem_init(&hd->sd_wiocing, 0) ;
+    hd->sd_iocblk = NULL ;
 
   again:                               /* wioc lock is always held when here */
     if (err < 0)
@@ -7294,5 +7334,6 @@
 /*----------------------------------------------------------------------
 # Local Variables:      ***
 # change-log-default-name: "~/src/prj/streams/src/NOTES" ***
+# c-basic-offset: 4 ***
 # End: ***
   ----------------------------------------------------------------------*/

Reply via email to