On Mon, Feb 06, 2017 at 01:16:45PM +0100, Martin Pieuchot wrote:
> On 03/02/17(Fri) 11:02, David Hill wrote:
> > On Fri, Feb 03, 2017 at 09:50:40AM +0100, Martin Pieuchot wrote:
> > > On 02/02/17(Thu) 12:12, David Hill wrote:
> > > > On Thu, Feb 02, 2017 at 09:34:07AM +0100, Martin Pieuchot wrote:
> > > > > On 01/02/17(Wed) 19:27, David Hill wrote:
> > > > > > Hello -
> > > > > > 
> > > > > > This diff makes sosetopt responsible for m_free which is much 
> > > > > > simpler.
> > > > > > Requested by bluhm@ 
> > > > > 
> > > > > I'd suggest to move the m_free(9) calls to sys_setsockopt().  This
> > > > > simplifies the existing code even more and will make it easier to use
> > > > > the stack for this temporary storage.
> > > > > 
> > > > 
> > > > New diff with mpi@'s suggestion. 
> > > 
> > > You forgot NFS and BFD that should now call m_free(9) after sosetopt(9). 
> > >
> > 
> > Indeed!  Now with BFD and NFS...
> 
> You're introducing a use after-free in ip_pcbopts().  You need to
> allocate/copy the mbuf there.
> 
> I must say I'm a bit afraid of this change because the amount of code it
> touches.  There might be another use after free somewhere that I missed.
> 
> Maybe we should first split our huge *ctloutput functions.  
> 
> One easy move is to split setopt/getopt.
> 
> Then introduce more per-protocol functions instead of having everything
> in ip{,6}_ctloutput().
> 
> For example move all the IPSEC craziness out of these functions.  Same
> thing with ICMP6...  This might sound superfluous but it will help
> if/when we decide to have a fine graining for different subsystems.
> 
> I'd also suggest to change the 'struct protosw' declaration to use C99
> initializer.  So we can have:
> 
>       .pr_ctloutput = ipsec_ctloutput
> 
> This would allow us to grep for "pr_ctloutput" (or pr_setopt) and know
> directly which functions to review.
>

If you are OK with first splitting each *ctloutput into *getopt/*setopt,
I will send each diff individually to make review easier.

Here is the first split, route_ctloutput.

Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.222
diff -u -p -r1.222 rtsock.c
--- net/rtsock.c        1 Feb 2017 20:59:47 -0000       1.222
+++ net/rtsock.c        21 Feb 2017 15:52:07 -0000
@@ -98,6 +98,8 @@ struct walkarg {
        caddr_t w_where, w_tmem;
 };
 
+int    route_getopt(struct socket *, int, int, struct mbuf *);
+int    route_setopt(struct socket *, int, int, struct mbuf *);
 int    route_ctloutput(int, struct socket *, int, int, struct mbuf *);
 void   route_input(struct mbuf *m0, sa_family_t);
 int    route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
@@ -233,62 +235,86 @@ route_usrreq(struct socket *so, int req,
 }
 
 int
-route_ctloutput(int op, struct socket *so, int level, int optname,
-    struct mbuf *m)
+route_getopt(struct socket *so, int level, int optname, struct mbuf *m)
+{
+       struct routecb *rop = sotoroutecb(so);
+       int error = 0;
+
+       if (level != AF_ROUTE)
+               return EINVAL;
+
+       switch (optname) {
+       case ROUTE_MSGFILTER:
+               m->m_len = sizeof(unsigned int);
+               *mtod(m, unsigned int *) = rop->msgfilter;
+               break;
+       case ROUTE_TABLEFILTER:
+               m->m_len = sizeof(unsigned int);
+               *mtod(m, unsigned int *) = rop->rtableid;
+               break;
+       default:
+               error = ENOPROTOOPT;
+               break;
+       }
+       return error;
+}
+
+int
+route_setopt(struct socket *so, int level, int optname, struct mbuf *m)
 {
        struct routecb *rop = sotoroutecb(so);
        int error = 0;
        unsigned int tid;
 
        if (level != AF_ROUTE) {
-               error = EINVAL;
-               if (op == PRCO_SETOPT && m)
-                       m_free(m);
-               return (error);
+               m_free(m);
+               return EINVAL;
        }
 
-       switch (op) {
-       case PRCO_SETOPT:
-               switch (optname) {
-               case ROUTE_MSGFILTER:
-                       if (m == NULL || m->m_len != sizeof(unsigned int))
-                               error = EINVAL;
-                       else
-                               rop->msgfilter = *mtod(m, unsigned int *);
-                       break;
-               case ROUTE_TABLEFILTER:
-                       if (m == NULL || m->m_len != sizeof(unsigned int)) {
-                               error = EINVAL;
-                               break;
-                       }
-                       tid = *mtod(m, unsigned int *);
-                       if (tid != RTABLE_ANY && !rtable_exists(tid))
-                               error = ENOENT;
-                       else
-                               rop->rtableid = tid;
-                       break;
-               default:
-                       error = ENOPROTOOPT;
+       switch (optname) {
+       case ROUTE_MSGFILTER:
+               if (m == NULL || m->m_len != sizeof(unsigned int))
+                       error = EINVAL;
+               else
+                       rop->msgfilter = *mtod(m, unsigned int *);
+               break;
+       case ROUTE_TABLEFILTER:
+               if (m == NULL || m->m_len != sizeof(unsigned int)) {
+                       error = EINVAL;
                        break;
                }
-               m_free(m);
+               tid = *mtod(m, unsigned int *);
+               if (tid != RTABLE_ANY && !rtable_exists(tid))
+                       error = ENOENT;
+               else
+                       rop->rtableid = tid;
+               break;
+       default:
+               error = ENOPROTOOPT;
                break;
+       }
+       m_free(m);
+       return error;
+}
+
+int
+route_ctloutput(int op, struct socket *so, int level, int optname,
+    struct mbuf *m)
+{
+       int error;
+
+       switch (op) {
        case PRCO_GETOPT:
-               switch (optname) {
-               case ROUTE_MSGFILTER:
-                       m->m_len = sizeof(unsigned int);
-                       *mtod(m, unsigned int *) = rop->msgfilter;
-                       break;
-               case ROUTE_TABLEFILTER:
-                       m->m_len = sizeof(unsigned int);
-                       *mtod(m, unsigned int *) = rop->rtableid;
-                       break;
-               default:
-                       error = ENOPROTOOPT;
-                       break;
-               }
+               error = route_getopt(so, level, optname, m);
+               break;
+       case PRCO_SETOPT:
+               error = route_setopt(so, level, optname, m);
+               break;
+       default:
+               error = EINVAL;
+               break;
        }
-       return (error);
+       return error;
 }
 
 void

Reply via email to