On Thu, Sep 01, 2022 at 05:59:44PM +0200, Alexander Bluhm wrote:
> On Thu, Sep 01, 2022 at 01:27:18AM +0300, Vitaliy Makkoveev wrote:
> > +int
> > +uipc_connect2(struct socket *so, struct socket *so2)
> > +{
> > +   struct unpcb *unp = sotounpcb(so), *unp2 = sotounpcb(so2);
> > +   int error;
> > +   
> > +   if ((error = unp_connect2(so, so2)))
> > +           return (error);
> > +
> > +   unp->unp_connid.uid = curproc->p_ucred->cr_uid;
> > +   unp->unp_connid.gid = curproc->p_ucred->cr_gid;
> > +   unp->unp_connid.pid = curproc->p_p->ps_pid;
> > +   unp->unp_flags |= UNP_FEIDS;
> > +   unp2->unp_connid.uid = curproc->p_ucred->cr_uid;
> > +   unp2->unp_connid.gid = curproc->p_ucred->cr_gid;
> > +   unp2->unp_connid.pid = curproc->p_p->ps_pid;
> > +   unp2->unp_flags |= UNP_FEIDS;
> >  
> >     return (0);
> >  }
> 
> You should not move the unp2 = sotounpcb(so2) before unp_connect2(so,
> so2).  There is this check in unp_connect2(), don't assume so2 has
> an unpcb too early.
> 
>         if (so2->so_type != so->so_type)
>                 return (EPROTOTYPE);
>         unp2 = sotounpcb(so2);
> 
> bluhm
> 

This is not true.

The "so2->so_type != so->so_type" check within unp_connect2() just
prevents the connection between the sockets with different types, but
not protocols. You can't connect unix(4) socket to the socket of another
protocol like inet(4), but you could try to connect SOCK_STREAM unix(4)
socket to another unix(4) socket, for example, of SOCK_DGRAM type. And
this check prevents this. This is actual for the PRU_CONNECT and
PRU_SEND requests, but not for the PRU_CONNECT2 request, which called
only from socketpair(2) ant both sockets have the same protocol and the
same type.

Also, as you can see, unp_connect2() does not check the
"so->so_pcb == NULL", because all sockets have attached PCB.

int
unp_connect2(struct socket *so, struct socket *so2)
{
        struct unpcb *unp = sotounpcb(so);
        struct unpcb *unp2;

        soassertlocked(so);
        soassertlocked(so2);

        if (so2->so_type != so->so_type)
                return (EPROTOTYPE);
        unp2 = sotounpcb(so2);
        unp->unp_conn = unp2;

Actually, unp_connect2() can't fail in the PRU_CONNECT2, and the check
after unp_connect2() could be skipped.

Well, let's be conservative. The `unp2' assignment restored to it's
original place.

Index: sys/kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.181
diff -u -p -r1.181 uipc_usrreq.c
--- sys/kern/uipc_usrreq.c      31 Aug 2022 21:23:02 -0000      1.181
+++ sys/kern/uipc_usrreq.c      1 Sep 2022 17:20:32 -0000
@@ -140,6 +140,7 @@ const struct pr_usrreqs uipc_usrreqs = {
        .pru_send       = uipc_send,
        .pru_abort      = uipc_abort,
        .pru_sense      = uipc_sense,
+       .pru_connect2   = uipc_connect2,
 };
 
 void
@@ -215,7 +216,6 @@ uipc_usrreq(struct socket *so, int req, 
     struct mbuf *control, struct proc *p)
 {
        struct unpcb *unp = sotounpcb(so);
-       struct unpcb *unp2;
        struct socket *so2;
        int error = 0;
 
@@ -232,21 +232,6 @@ uipc_usrreq(struct socket *so, int req, 
 
        switch (req) {
 
-       case PRU_CONNECT2:
-               error = unp_connect2(so, (struct socket *)nam);
-               if (!error) {
-                       unp->unp_connid.uid = p->p_ucred->cr_uid;
-                       unp->unp_connid.gid = p->p_ucred->cr_gid;
-                       unp->unp_connid.pid = p->p_p->ps_pid;
-                       unp->unp_flags |= UNP_FEIDS;
-                       unp2 = sotounpcb((struct socket *)nam);
-                       unp2->unp_connid.uid = p->p_ucred->cr_uid;
-                       unp2->unp_connid.gid = p->p_ucred->cr_gid;
-                       unp2->unp_connid.pid = p->p_p->ps_pid;
-                       unp2->unp_flags |= UNP_FEIDS;
-               }
-               break;
-
        case PRU_SOCKADDR:
                uipc_setaddr(unp, nam);
                break;
@@ -592,6 +577,28 @@ uipc_sense(struct socket *so, struct sta
            sb->st_mtim.tv_nsec =
            sb->st_ctim.tv_nsec = unp->unp_ctime.tv_nsec;
        sb->st_ino = unp->unp_ino;
+
+       return (0);
+}
+
+int
+uipc_connect2(struct socket *so, struct socket *so2)
+{
+       struct unpcb *unp = sotounpcb(so), *unp2;
+       int error;
+       
+       if ((error = unp_connect2(so, so2)))
+               return (error);
+
+       unp->unp_connid.uid = curproc->p_ucred->cr_uid;
+       unp->unp_connid.gid = curproc->p_ucred->cr_gid;
+       unp->unp_connid.pid = curproc->p_p->ps_pid;
+       unp->unp_flags |= UNP_FEIDS;
+       unp2 = sotounpcb(so2);
+       unp2->unp_connid.uid = curproc->p_ucred->cr_uid;
+       unp2->unp_connid.gid = curproc->p_ucred->cr_gid;
+       unp2->unp_connid.pid = curproc->p_p->ps_pid;
+       unp2->unp_flags |= UNP_FEIDS;
 
        return (0);
 }
Index: sys/net/pfkeyv2.c
===================================================================
RCS file: /cvs/src/sys/net/pfkeyv2.c,v
retrieving revision 1.248
diff -u -p -r1.248 pfkeyv2.c
--- sys/net/pfkeyv2.c   31 Aug 2022 21:23:02 -0000      1.248
+++ sys/net/pfkeyv2.c   1 Sep 2022 17:20:33 -0000
@@ -412,11 +412,6 @@ pfkeyv2_usrreq(struct socket *so, int re
        }
 
        switch (req) {
-       /* no connect, bind, accept. Socket is connected from the start */
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        /* minimal support, just implement a fake peer address */
        case PRU_SOCKADDR:
                error = EINVAL;
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.349
diff -u -p -r1.349 rtsock.c
--- sys/net/rtsock.c    31 Aug 2022 21:23:02 -0000      1.349
+++ sys/net/rtsock.c    1 Sep 2022 17:20:33 -0000
@@ -237,11 +237,6 @@ route_usrreq(struct socket *so, int req,
        }
 
        switch (req) {
-       /* no connect, bind, accept. Socket is connected from the start */
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        /* minimal support, just implement a fake peer address */
        case PRU_SOCKADDR:
                error = EINVAL;
Index: sys/netinet/ip_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.82
diff -u -p -r1.82 ip_divert.c
--- sys/netinet/ip_divert.c     31 Aug 2022 21:23:02 -0000      1.82
+++ sys/netinet/ip_divert.c     1 Sep 2022 17:20:33 -0000
@@ -279,7 +279,6 @@ divert_usrreq(struct socket *so, int req
                in_setpeeraddr(inp, addr);
                break;
 
-       case PRU_CONNECT2:
        case PRU_FASTTIMO:
        case PRU_SLOWTIMO:
        case PRU_PROTORCV:
Index: sys/netinet/raw_ip.c
===================================================================
RCS file: /cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.143
diff -u -p -r1.143 raw_ip.c
--- sys/netinet/raw_ip.c        31 Aug 2022 21:23:02 -0000      1.143
+++ sys/netinet/raw_ip.c        1 Sep 2022 17:20:33 -0000
@@ -478,10 +478,6 @@ rip_usrreq(struct socket *so, int req, s
 
        switch (req) {
 
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        case PRU_SOCKADDR:
                in_setsockaddr(inp, nam);
                break;
Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.202
diff -u -p -r1.202 tcp_usrreq.c
--- sys/netinet/tcp_usrreq.c    31 Aug 2022 21:23:02 -0000      1.202
+++ sys/netinet/tcp_usrreq.c    1 Sep 2022 17:20:34 -0000
@@ -223,13 +223,6 @@ tcp_usrreq(struct socket *so, int req, s
 
        switch (req) {
 
-       /*
-        * Create a TCP connection between two sockets.
-        */
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        case PRU_SOCKADDR:
 #ifdef INET6
                if (inp->inp_flags & INP_IPV6)
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.297
diff -u -p -r1.297 udp_usrreq.c
--- sys/netinet/udp_usrreq.c    31 Aug 2022 21:23:02 -0000      1.297
+++ sys/netinet/udp_usrreq.c    1 Sep 2022 17:20:34 -0000
@@ -1089,10 +1089,6 @@ udp_usrreq(struct socket *so, int req, s
         */
        switch (req) {
 
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        case PRU_SOCKADDR:
 #ifdef INET6
                if (inp->inp_flags & INP_IPV6)
Index: sys/netinet6/ip6_divert.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
retrieving revision 1.81
diff -u -p -r1.81 ip6_divert.c
--- sys/netinet6/ip6_divert.c   31 Aug 2022 21:23:02 -0000      1.81
+++ sys/netinet6/ip6_divert.c   1 Sep 2022 17:20:34 -0000
@@ -285,7 +285,6 @@ divert6_usrreq(struct socket *so, int re
                in6_setpeeraddr(inp, addr);
                break;
 
-       case PRU_CONNECT2:
        case PRU_FASTTIMO:
        case PRU_SLOWTIMO:
        case PRU_PROTORCV:
Index: sys/netinet6/raw_ip6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.164
diff -u -p -r1.164 raw_ip6.c
--- sys/netinet6/raw_ip6.c      31 Aug 2022 21:23:02 -0000      1.164
+++ sys/netinet6/raw_ip6.c      1 Sep 2022 17:20:36 -0000
@@ -593,10 +593,6 @@ rip6_usrreq(struct socket *so, int req, 
        }
 
        switch (req) {
-       case PRU_CONNECT2:
-               error = EOPNOTSUPP;
-               break;
-
        case PRU_SOCKADDR:
                in6_setsockaddr(in6p, nam);
                break;
Index: sys/sys/protosw.h
===================================================================
RCS file: /cvs/src/sys/sys/protosw.h,v
retrieving revision 1.50
diff -u -p -r1.50 protosw.h
--- sys/sys/protosw.h   31 Aug 2022 21:23:02 -0000      1.50
+++ sys/sys/protosw.h   1 Sep 2022 17:20:36 -0000
@@ -81,6 +81,7 @@ struct pr_usrreqs {
        int     (*pru_rcvoob)(struct socket *, struct mbuf *, int);
        int     (*pru_sendoob)(struct socket *, struct mbuf *, struct mbuf *,
                    struct mbuf *);
+       int     (*pru_connect2)(struct socket *, struct socket *);
 };
 
 struct protosw {
@@ -395,8 +396,9 @@ pru_peeraddr(struct socket *so, struct m
 static inline int
 pru_connect2(struct socket *so1, struct socket *so2)
 {
-       return (*so1->so_proto->pr_usrreqs->pru_usrreq)(so1,
-           PRU_CONNECT2, NULL, (struct mbuf *)so2, NULL, curproc);
+       if (so1->so_proto->pr_usrreqs->pru_connect2)
+               return (*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2);
+       return (EOPNOTSUPP);
 }
 
 #endif
Index: sys/sys/unpcb.h
===================================================================
RCS file: /cvs/src/sys/sys/unpcb.h,v
retrieving revision 1.37
diff -u -p -r1.37 unpcb.h
--- sys/sys/unpcb.h     28 Aug 2022 21:35:12 -0000      1.37
+++ sys/sys/unpcb.h     1 Sep 2022 17:20:36 -0000
@@ -127,6 +127,7 @@ int uipc_send(struct socket *, struct mb
            struct mbuf *);
 int    uipc_abort(struct socket *);
 int    uipc_sense(struct socket *, struct stat *);
+int    uipc_connect2(struct socket *, struct socket *);
 
 void   unp_init(void);
 int    unp_bind(struct unpcb *, struct mbuf *, struct proc *);

Reply via email to