On Sun, Mar 26, 2017 at 05:00:12PM +0200, Mateusz Guzik wrote:
> The patch is somewhat incorrect, although from what I checked it happens
> to generate the expected outcome in terms of assembly (the global pointer
> read only once and then a local copy accessed several times). You either
> need a linux-like READ_ONCE macros which casts through a volatile pointer
> or mark the global as volatile to prevent the compiler from issuing
> multiple reads in the future.

Note that our OpenBSD kernel is still implemented with a big kernel
lock in most places.  So multi processor thinking and locking is
not necessary.  The execution order can only be interrupted by
hardware interrups or explicitly rescheduling with tsleep(9).  Here
the sleep is hidden in copyin(), mallocarray(), sosend(), malloc(),
ktrgenio().

Interrupts are not relevant, they never change syslogf.  As tsleep()
is a function call, it automatically acts as compiler barrier.  So
volatile is not needed.

> Remaining ses sof syslogf are also super fishy:
> 1. logclose
> 2. logioctl -> LIOCSFD
>                 FRELE(syslogf, p);

A few months ago I would have said FRELE() does not sleep.  I think
this is currently still the case as we do not grab the netlock for
socketpairs.  But we did for a while.

As we are heading towards multi processor in kernel, I would suggest
this diff.  It orders FREF() and FRELE() in a way that we only
operate on refcounted global variables.  Although not necessary
with the current sleeping points, I think it results in more robust
code.

ok?

bluhm

Index: kern/subr_log.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/subr_log.c,v
retrieving revision 1.49
diff -u -p -r1.49 subr_log.c
--- kern/subr_log.c     24 Mar 2017 16:42:38 -0000      1.49
+++ kern/subr_log.c     26 Mar 2017 19:37:05 -0000
@@ -172,10 +172,12 @@ logopen(dev_t dev, int flags, int mode, 
 int
 logclose(dev_t dev, int flag, int mode, struct proc *p)
 {
+       struct file *fp;
 
-       if (syslogf)
-               FRELE(syslogf, p);
+       fp = syslogf;
        syslogf = NULL;
+       if (fp)
+               FRELE(fp, p);
        log_open = 0;
        logsoftc.sc_state = 0;
        return (0);
@@ -355,11 +357,11 @@ logioctl(dev_t dev, u_long com, caddr_t 
        case LIOCSFD:
                if ((error = suser(p, 0)) != 0)
                        return (error);
-               if ((error = getsock(p, *(int *)data, &fp)) != 0)
+               fp = syslogf;
+               if ((error = getsock(p, *(int *)data, &syslogf)) != 0)
                        return (error);
-               if (syslogf)
-                       FRELE(syslogf, p);
-               syslogf = fp;
+               if (fp)
+                       FRELE(fp, p);
                break;
 
        default:
Index: kern/uipc_syscalls.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.150
diff -u -p -r1.150 uipc_syscalls.c
--- kern/uipc_syscalls.c        14 Feb 2017 09:46:21 -0000      1.150
+++ kern/uipc_syscalls.c        26 Mar 2017 19:37:05 -0000
@@ -1146,8 +1146,8 @@ getsock(struct proc *p, int fdes, struct
                return (EBADF);
        if (fp->f_type != DTYPE_SOCKET)
                return (ENOTSOCK);
-       *fpp = fp;
        FREF(fp);
+       *fpp = fp;
 
        return (0);
 }

Reply via email to