Re: sosetstate/soclrstate

2018-01-09 Thread Alexander Bluhm
On Tue, Jan 09, 2018 at 11:23:32AM +0100, Martin Pieuchot wrote:
> --- netinet6/ip6_output.c 1 Sep 2017 15:05:31 -   1.232
> +++ netinet6/ip6_output.c 9 Jan 2018 10:16:10 -
> @@ -1033,12 +1033,12 @@ int
>  ip6_ctloutput(int op, struct socket *so, int level, int optname,
>  struct mbuf *m)
>  {
> - int privileged, optdatalen, uproto;
> + int optdatalen, uproto;
>   void *optdata;
>   struct inpcb *inp = sotoinpcb(so);
>   int error, optval;
>   struct proc *p = curproc; /* For IPSec and rdomain */
> - u_int rtid = 0;
> + u_int privileged, rtid = 0;
>  
>   error = optval = 0;
>  

"privileged" is passed down as an boolean signed int.  So it does
not matter where it is converted.

anyway OK bluhm@



Re: sosetstate/soclrstate

2018-01-09 Thread Martin Pieuchot
On 09/01/18(Tue) 00:42, Alexander Bluhm wrote:
> On Mon, Jan 08, 2018 at 03:50:14PM +0100, Martin Pieuchot wrote:
> > ok?
> 
> OK bluhm@ with a few remarks.

visa@ pointed out that since all the writes are done under the socket
lock it is enough to use an aligned int32 variable.  So here's an
updated diff that address your comments.

Index: kern/kern_pledge.c
===
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.227
diff -u -p -r1.227 kern_pledge.c
--- kern/kern_pledge.c  8 Jan 2018 11:54:28 -   1.227
+++ kern/kern_pledge.c  9 Jan 2018 10:17:28 -
@@ -1337,7 +1337,7 @@ pledge_sockopt(struct proc *p, int set, 
 }
 
 int
-pledge_socket(struct proc *p, int domain, int state)
+pledge_socket(struct proc *p, int domain, unsigned int state)
 {
if (! ISSET(p->p_p->ps_flags, PS_PLEDGE))
return 0;
Index: kern/uipc_socket.c
===
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.213
diff -u -p -r1.213 uipc_socket.c
--- kern/uipc_socket.c  2 Jan 2018 12:54:07 -   1.213
+++ kern/uipc_socket.c  9 Jan 2018 10:14:21 -
@@ -1248,7 +1248,7 @@ somove(struct socket *so, int wait)
u_long   len, off, oobmark;
long space;
int  error = 0, maxreached = 0;
-   shortstate;
+   unsigned int state;
 
soassertlocked(so);
 
Index: kern/uipc_syscalls.c
===
RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.161
diff -u -p -r1.161 uipc_syscalls.c
--- kern/uipc_syscalls.c2 Jan 2018 06:38:45 -   1.161
+++ kern/uipc_syscalls.c9 Jan 2018 10:17:39 -
@@ -83,7 +83,8 @@ sys_socket(struct proc *p, void *v, regi
struct file *fp;
int type = SCARG(uap, type);
int domain = SCARG(uap, domain);
-   int fd, error, ss = 0;
+   int fd, error;
+   unsigned int ss = 0;
 
if ((type & SOCK_DNS) && !(domain == AF_INET || domain == AF_INET6))
return (EINVAL);
Index: netinet/tcp_usrreq.c
===
RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.162
diff -u -p -r1.162 tcp_usrreq.c
--- netinet/tcp_usrreq.c1 Dec 2017 10:33:33 -   1.162
+++ netinet/tcp_usrreq.c9 Jan 2018 10:15:30 -
@@ -583,7 +583,7 @@ tcp_attach(struct socket *so, int proto)
inp = sotoinpcb(so);
tp = tcp_newtcpcb(inp);
if (tp == NULL) {
-   int nofd = so->so_state & SS_NOFDREF;   /* XXX */
+   unsigned int nofd = so->so_state & SS_NOFDREF;  /* XXX */
 
so->so_state &= ~SS_NOFDREF;/* don't free the socket yet */
in_pcbdetach(inp);
Index: netinet6/ip6_output.c
===
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.232
diff -u -p -r1.232 ip6_output.c
--- netinet6/ip6_output.c   1 Sep 2017 15:05:31 -   1.232
+++ netinet6/ip6_output.c   9 Jan 2018 10:16:10 -
@@ -1033,12 +1033,12 @@ int
 ip6_ctloutput(int op, struct socket *so, int level, int optname,
 struct mbuf *m)
 {
-   int privileged, optdatalen, uproto;
+   int optdatalen, uproto;
void *optdata;
struct inpcb *inp = sotoinpcb(so);
int error, optval;
struct proc *p = curproc; /* For IPSec and rdomain */
-   u_int rtid = 0;
+   u_int privileged, rtid = 0;
 
error = optval = 0;
 
Index: sys/pledge.h
===
RCS file: /cvs/src/sys/sys/pledge.h,v
retrieving revision 1.33
diff -u -p -r1.33 pledge.h
--- sys/pledge.h12 Dec 2017 01:12:34 -  1.33
+++ sys/pledge.h9 Jan 2018 10:17:45 -
@@ -126,7 +126,7 @@ int pledge_chown(struct proc *p, uid_t, 
 intpledge_adjtime(struct proc *p, const void *v);
 intpledge_sendit(struct proc *p, const void *to);
 intpledge_sockopt(struct proc *p, int set, int level, int optname);
-intpledge_socket(struct proc *p, int domain, int state);
+intpledge_socket(struct proc *p, int domain, unsigned int state);
 intpledge_ioctl(struct proc *p, long com, struct file *);
 intpledge_ioctl_drm(struct proc *p, long com, dev_t device);
 intpledge_ioctl_vmm(struct proc *p, long com);
Index: sys/socketvar.h
===
RCS file: /cvs/src/sys/sys/socketvar.h,v
retrieving revision 1.81
diff -u -p -r1.81 socketvar.h
--- sys/socketvar.h 2 Jan 2018 12:54:07 -   1.81
+++ sys/socketvar.h 9 Jan 2018 10:08:53 -
@@ -51,12 +51,12 @@ TAILQ_HEAD(soqhead, socket);
  * private data and error information.
  */
 struct socket {
+   const struct protosw *so_proto; /* pro

Re: sosetstate/soclrstate

2018-01-08 Thread Alexander Bluhm
On Mon, Jan 08, 2018 at 03:50:14PM +0100, Martin Pieuchot wrote:
> ok?

OK bluhm@ with a few remarks.

> @@ -1422,12 +1422,12 @@ somove(struct socket *so, int wait)
>  
>   /* Receive buffer did shrink by len bytes, adjust oob. */
>   state = so->so_state;
> - so->so_state &= ~SS_RCVATMARK;
> + soclrstate(so, SS_RCVATMARK);
>   oobmark = so->so_oobmark;
>   so->so_oobmark = oobmark > len ? oobmark - len : 0;
>   if (oobmark) {

Can we make the "state" also u_int?

> @@ -198,7 +198,7 @@ sonewconn(struct socket *head, int conns
>   if (connstatus) {
>   sorwakeup(head);
>   wakeup(&head->so_timeo);
> - so->so_state |= connstatus;
> + sosetstate(so, connstatus);
>   }
>   return (so);
>  }

"connstatus" should be u_int.

> @@ -112,8 +112,8 @@ sys_socket(struct proc *p, void *v, regi
>   fdpunlock(fdp);
>   } else {
>   if (type & SOCK_NONBLOCK)
> - so->so_state |= SS_NBIO;
> - so->so_state |= ss;
> + sosetstate(so, SS_NBIO);
> + sosetstate(so, ss);
>   fp->f_data = so;
>   FILE_SET_MATURE(fp, p);
>   *retval = fd;

"ss" should be u_int for consistency.  And pledge_socket() still
takes the state as signed int.

> @@ -181,7 +181,7 @@ fifo_open(void *v)
>   goto bad;
>   }
>   if (fip->fi_writers == 1) {
> - rso->so_state &= ~(SS_CANTRCVMORE|SS_ISDISCONNECTED);
> + soclrstate(rso, (SS_CANTRCVMORE|SS_ISDISCONNECTED));
>   if (fip->fi_readers > 0)
>   wakeup(&fip->fi_readers);
>   }

There are more () than needed.

> @@ -585,9 +585,9 @@ tcp_attach(struct socket *so, int proto)
>   if (tp == NULL) {
>   int nofd = so->so_state & SS_NOFDREF;   /* XXX */
>  
> - so->so_state &= ~SS_NOFDREF;/* don't free the socket yet */
> + soclrstate(so, SS_NOFDREF); /* don't free the socket yet */
>   in_pcbdetach(inp);
> - so->so_state |= nofd;
> + sosetstate(so, nofd);
>   return (ENOBUFS);
>   }
>   tp->t_state = TCPS_CLOSED;

nofd should be u_int.



sosetstate/soclrstate

2018-01-08 Thread Martin Pieuchot
Diff below changes the type of `so_state' and `so_error' to int.  It
also introduces two new wrappers to set & clear state bits atomically.

My goal is to prevent a second CPU from reading garbage when looking
at these two fields in filt_soread() and filt_sowrite().  The values
might be outdated though.

This should be the last requirement before unlocking the receiving path.

ok?

Index: kern/uipc_socket.c
===
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.213
diff -u -p -r1.213 uipc_socket.c
--- kern/uipc_socket.c  2 Jan 2018 12:54:07 -   1.213
+++ kern/uipc_socket.c  8 Jan 2018 14:32:33 -
@@ -139,7 +139,7 @@ socreate(int dom, struct socket **aso, i
s = solock(so);
error = (*prp->pr_attach)(so, proto);
if (error) {
-   so->so_state |= SS_NOFDREF;
+   sosetstate(so, SS_NOFDREF);
sofree(so);
sounlock(s);
return (error);
@@ -275,7 +275,7 @@ drop:
 discard:
if (so->so_state & SS_NOFDREF)
panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type);
-   so->so_state |= SS_NOFDREF;
+   sosetstate(so, SS_NOFDREF);
sofree(so);
sounlock(s);
return (error);
@@ -299,7 +299,7 @@ soaccept(struct socket *so, struct mbuf 
 
if ((so->so_state & SS_NOFDREF) == 0)
panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type);
-   so->so_state &= ~SS_NOFDREF;
+   soclrstate(so, SS_NOFDREF);
if ((so->so_state & SS_ISDISCONNECTED) == 0 ||
(so->so_proto->pr_flags & PR_ABRTACPTDIS) == 0)
error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT, NULL,
@@ -425,7 +425,7 @@ sosend(struct socket *so, struct mbuf *a
 restart:
if ((error = sblock(so, &so->so_snd, SBLOCKWAIT(flags))) != 0)
goto out;
-   so->so_state |= SS_ISSENDING;
+   sosetstate(so, SS_ISSENDING);
do {
if (so->so_state & SS_CANTSENDMORE)
snderr(EPIPE);
@@ -455,7 +455,7 @@ restart:
snderr(EWOULDBLOCK);
sbunlock(so, &so->so_snd);
error = sbwait(so, &so->so_snd);
-   so->so_state &= ~SS_ISSENDING;
+   soclrstate(so, SS_ISSENDING);
if (error)
goto out;
goto restart;
@@ -481,7 +481,7 @@ restart:
top->m_flags |= M_EOR;
}
if (resid == 0)
-   so->so_state &= ~SS_ISSENDING;
+   soclrstate(so, SS_ISSENDING);
if (top && so->so_options & SO_ZEROIZE)
top->m_flags |= M_ZEROIZE;
error = (*so->so_proto->pr_usrreq)(so,
@@ -496,7 +496,7 @@ restart:
} while (resid);
 
 release:
-   so->so_state &= ~SS_ISSENDING;
+   soclrstate(so, SS_ISSENDING);
sbunlock(so, &so->so_snd);
 out:
sounlock(s);
@@ -857,7 +857,7 @@ dontblock:
panic("receive 3: so %p, so_type %d, m %p, m_type %d",
so, so->so_type, m, m->m_type);
 #endif
-   so->so_state &= ~SS_RCVATMARK;
+   soclrstate(so, SS_RCVATMARK);
len = uio->uio_resid;
if (so->so_oobmark && len > so->so_oobmark - offset)
len = so->so_oobmark - offset;
@@ -932,7 +932,7 @@ dontblock:
if ((flags & MSG_PEEK) == 0) {
so->so_oobmark -= len;
if (so->so_oobmark == 0) {
-   so->so_state |= SS_RCVATMARK;
+   sosetstate(so, SS_RCVATMARK);
break;
}
} else {
@@ -1292,7 +1292,7 @@ somove(struct socket *so, int wait)
goto release;
len = space;
}
-   sosp->so_state |= SS_ISSENDING;
+   sosetstate(sosp, SS_ISSENDING);
 
SBLASTRECORDCHK(&so->so_rcv, "somove 1");
SBLASTMBUFCHK(&so->so_rcv, "somove 1");
@@ -1422,12 +1422,12 @@ somove(struct socket *so, int wait)
 
/* Receive buffer did shrink by len bytes, adjust oob. */
state = so->so_state;
-   so->so_state &= ~SS_RCVATMARK;
+   soclrstate(so, SS_RCVATMARK);
oobmark = so->so_oobmark;
so->so_oobmark = oobmark > len ? oobmark - len : 0;
if (oobmark) {
if (oobmark == len)
-   so->so_state |= SS_RCVATMARK;
+   sosetstate(so, SS_RCVATMARK);
if (oobmark >= len)
oobmark = 0;
}
@@ -1485,7 +1485,7