Where soo_ioctl() modifies `so_state', `so_rcv' or `so_snd' it needs the
socket lock.

More fields might need the lock in the future but for the moment I'm
concentrating on fields accessed in the TCP input path.

ok?

Index: kern/sys_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_socket.c,v
retrieving revision 1.30
diff -u -p -r1.30 sys_socket.c
--- kern/sys_socket.c   22 Feb 2017 10:20:21 -0000      1.30
+++ kern/sys_socket.c   18 Jul 2017 06:26:15 -0000
@@ -78,13 +78,16 @@ soo_ioctl(struct file *fp, u_long cmd, c
        switch (cmd) {
 
        case FIONBIO:
+               s = solock(so);
                if (*(int *)data)
                        so->so_state |= SS_NBIO;
                else
                        so->so_state &= ~SS_NBIO;
-               return (0);
+               sounlock(s);
+               break;
 
        case FIOASYNC:
+               s = solock(so);
                if (*(int *)data) {
                        so->so_state |= SS_ASYNC;
                        so->so_rcv.sb_flags |= SB_ASYNC;
@@ -94,43 +97,47 @@ soo_ioctl(struct file *fp, u_long cmd, c
                        so->so_rcv.sb_flags &= ~SB_ASYNC;
                        so->so_snd.sb_flags &= ~SB_ASYNC;
                }
-               return (0);
+               sounlock(s);
+               break;
 
        case FIONREAD:
                *(int *)data = so->so_rcv.sb_datacc;
-               return (0);
+               break;
 
        case SIOCSPGRP:
                so->so_pgid = *(int *)data;
                so->so_siguid = p->p_ucred->cr_ruid;
                so->so_sigeuid = p->p_ucred->cr_uid;
-               return (0);
+               break;
 
        case SIOCGPGRP:
                *(int *)data = so->so_pgid;
-               return (0);
+               break;
 
        case SIOCATMARK:
                *(int *)data = (so->so_state&SS_RCVATMARK) != 0;
-               return (0);
-       }
-       /*
-        * Interface/routing/protocol specific ioctls:
-        * interface and routing ioctls should have a
-        * different entry since a socket's unnecessary
-        */
-       if (IOCGROUP(cmd) == 'i') {
-               NET_LOCK(s);
-               error = ifioctl(so, cmd, data, p);
-               NET_UNLOCK(s);
-               return (error);
+               break;
+
+       default:
+               /*
+                * Interface/routing/protocol specific ioctls:
+                * interface and routing ioctls should have a
+                * different entry since a socket's unnecessary
+                */
+               if (IOCGROUP(cmd) == 'i') {
+                       NET_LOCK(s);
+                       error = ifioctl(so, cmd, data, p);
+                       NET_UNLOCK(s);
+                       return (error);
+               }
+               if (IOCGROUP(cmd) == 'r')
+                       return (EOPNOTSUPP);
+               s = solock(so);
+               error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
+                   (struct mbuf *)cmd, (struct mbuf *)data, NULL, p));
+               sounlock(s);
+               break;
        }
-       if (IOCGROUP(cmd) == 'r')
-               return (EOPNOTSUPP);
-       s = solock(so);
-       error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 
-           (struct mbuf *)cmd, (struct mbuf *)data, (struct mbuf *)NULL, p));
-       sounlock(s);
 
        return (error);
 }

Reply via email to