Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Fix apparent race.



details:   https://anonhg.NetBSD.org/src/rev/afaeb7675766
branches:  trunk
changeset: 446973:afaeb7675766
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu Dec 27 07:56:43 2018 +0000

description:
Fix apparent race.

We're doing a LIST_FOREACH, but unlock filelist_lock in the middle of the
loop and drop the reference to fp. We then read fp->...le_next, but it
may have been freed by another thread.

This is difficult to trigger and observe, probably only KASAN can see
problems of this kind.

Switch to LIST_FOREACH_SAFE, and re-fetch np after re-locking.

May fix PR/53674.

diffstat:

 sys/kern/uipc_domain.c |  9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diffs (44 lines):

diff -r 49b84f7a450d -r afaeb7675766 sys/kern/uipc_domain.c
--- a/sys/kern/uipc_domain.c    Thu Dec 27 07:56:11 2018 +0000
+++ b/sys/kern/uipc_domain.c    Thu Dec 27 07:56:43 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_domain.c,v 1.105 2018/11/24 17:16:44 maxv Exp $   */
+/*     $NetBSD: uipc_domain.c,v 1.106 2018/12/27 07:56:43 maxv Exp $   */
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.105 2018/11/24 17:16:44 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.106 2018/12/27 07:56:43 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -534,7 +534,7 @@
 static int
 sysctl_unpcblist(SYSCTLFN_ARGS)
 {
-       struct file *fp, *dfp;
+       struct file *fp, *np, *dfp;
        struct socket *so;
        struct kinfo_pcb pcb;
        char *dp;
@@ -583,7 +583,7 @@
         * to walk the file list looking for them.  :-/
         */
        mutex_enter(&filelist_lock);
-       LIST_FOREACH(fp, &filehead, f_list) {
+       LIST_FOREACH_SAFE(fp, &filehead, f_list, np) {
                if (fp->f_count == 0 || fp->f_type != DTYPE_SOCKET ||
                    fp->f_socket == NULL)
                        continue;
@@ -615,6 +615,7 @@
                        error = copyout(&pcb, dp, out_size);
                        closef(fp);
                        mutex_enter(&filelist_lock);
+                       np = LIST_NEXT(dfp, f_list);
                        LIST_REMOVE(dfp, f_list);
                        if (error)
                                break;



Home | Main Index | Thread Index | Old Index