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 *);