Source-Changes-HG archive

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

[src/trunk]: src/sys PAX_SEGVGUARD doesn't seem to work properly in testing f...



details:   https://anonhg.NetBSD.org/src/rev/0c19cd435222
branches:  trunk
changeset: 1006682:0c19cd435222
user:      ad <ad%NetBSD.org@localhost>
date:      Thu Jan 23 10:21:14 2020 +0000

description:
PAX_SEGVGUARD doesn't seem to work properly in testing for me, but at least
make it not cause problems:

- Cover it with exec_lock so the updates are not racy.
- Using fileassoc is silly.  Just hang a pointer off the vnode.

diffstat:

 sys/kern/kern_pax.c  |  44 +++++++++++++++++---------------------------
 sys/kern/kern_sig.c  |   7 +++++--
 sys/kern/vfs_vnode.c |  11 +++++++++--
 sys/sys/pax.h        |   4 +++-
 sys/sys/vnode.h      |   4 +++-
 5 files changed, 37 insertions(+), 33 deletions(-)

diffs (245 lines):

diff -r 238b8712a916 -r 0c19cd435222 sys/kern/kern_pax.c
--- a/sys/kern/kern_pax.c       Thu Jan 23 10:05:44 2020 +0000
+++ b/sys/kern/kern_pax.c       Thu Jan 23 10:21:14 2020 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: kern_pax.c,v 1.60 2017/06/25 04:10:47 snj Exp $        */
+/*     $NetBSD: kern_pax.c,v 1.61 2020/01/23 10:21:14 ad Exp $ */
 
 /*
- * Copyright (c) 2015 The NetBSD Foundation, Inc.
+ * Copyright (c) 2015, 2020 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.60 2017/06/25 04:10:47 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v 1.61 2020/01/23 10:21:14 ad Exp $");
 
 #include "opt_pax.h"
 
@@ -69,7 +69,6 @@
 #include <sys/sysctl.h>
 #include <sys/kmem.h>
 #include <sys/mman.h>
-#include <sys/fileassoc.h>
 #include <sys/syslog.h>
 #include <sys/vnode.h>
 #include <sys/queue.h>
@@ -155,8 +154,6 @@
 static int pax_segvguard_suspension = PAX_SEGVGUARD_SUSPENSION;
 static int pax_segvguard_maxcrashes = PAX_SEGVGUARD_MAXCRASHES;
 
-static fileassoc_t segvguard_id;
-
 struct pax_segvguard_uid_entry {
        uid_t sue_uid;
        size_t sue_ncrashes;
@@ -170,7 +167,6 @@
 };
 
 static bool pax_segvguard_elf_flags_active(uint32_t);
-static void pax_segvguard_cleanup_cb(void *);
 #endif /* PAX_SEGVGUARD */
 
 SYSCTL_SETUP(sysctl_security_pax_setup, "sysctl security.pax setup")
@@ -338,15 +334,6 @@
 void
 pax_init(void)
 {
-#ifdef PAX_SEGVGUARD
-       int error;
-
-       error = fileassoc_register("segvguard", pax_segvguard_cleanup_cb,
-           &segvguard_id);
-       if (error) {
-               panic("pax_init: segvguard_id: error=%d\n", error);
-       }
-#endif /* PAX_SEGVGUARD */
 #ifdef PAX_ASLR
        /* Adjust maximum stack by the size we can consume for ASLR */
        extern rlim_t maxsmap;
@@ -704,13 +691,13 @@
        return true;
 }
 
-static void
-pax_segvguard_cleanup_cb(void *v)
+void
+pax_segvguard_cleanup(struct vnode *vp)
 {
-       struct pax_segvguard_entry *p = v;
+       struct pax_segvguard_entry *p = vp->v_segvguard;
        struct pax_segvguard_uid_entry *up;
 
-       if (p == NULL) {
+       if (__predict_true(p == NULL)) {
                return;
        }
        while ((up = LIST_FIRST(&p->segv_uids)) != NULL) {
@@ -718,14 +705,17 @@
                kmem_free(up, sizeof(*up));
        }
        kmem_free(p, sizeof(*p));
+       vp->v_segvguard = NULL;
 }
 
 /*
  * Called when a process of image vp generated a segfault.
+ *
+ * => exec_lock must be held by the caller
+ * => if "crashed" is true, exec_lock must be held for write
  */
 int
-pax_segvguard(struct lwp *l, struct vnode *vp, const char *name,
-    bool crashed)
+pax_segvguard(struct lwp *l, struct vnode *vp, const char *name, bool crashed)
 {
        struct pax_segvguard_entry *p;
        struct pax_segvguard_uid_entry *up;
@@ -734,6 +724,9 @@
        uint32_t flags;
        bool have_uid;
 
+       KASSERT(rw_lock_held(&exec_lock));
+       KASSERT(!crashed || rw_write_held(&exec_lock));
+
        flags = l->l_proc->p_pax;
        if (!pax_flags_active(flags, P_PAX_GUARD))
                return 0;
@@ -741,11 +734,8 @@
        if (vp == NULL)
                return EFAULT;  
 
-       /* Check if we already monitor the file. */
-       p = fileassoc_lookup(vp, segvguard_id);
-
        /* Fast-path if starting a program we don't know. */
-       if (p == NULL && !crashed)
+       if ((p = vp->v_segvguard) == NULL && !crashed)
                return 0;
 
        microtime(&tv);
@@ -756,7 +746,7 @@
         */
        if (p == NULL) {
                p = kmem_alloc(sizeof(*p), KM_SLEEP);
-               fileassoc_add(vp, segvguard_id, p);
+               vp->v_segvguard = p;
                LIST_INIT(&p->segv_uids);
 
                /*
diff -r 238b8712a916 -r 0c19cd435222 sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c       Thu Jan 23 10:05:44 2020 +0000
+++ b/sys/kern/kern_sig.c       Thu Jan 23 10:21:14 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sig.c,v 1.381 2019/12/06 21:36:10 ad Exp $        */
+/*     $NetBSD: kern_sig.c,v 1.382 2020/01/23 10:21:14 ad Exp $        */
 
 /*-
  * Copyright (c) 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.381 2019/12/06 21:36:10 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.382 2020/01/23 10:21:14 ad Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -2304,8 +2304,11 @@
                }
 
 #ifdef PAX_SEGVGUARD
+               rw_enter(&exec_lock, RW_WRITER);
                pax_segvguard(l, p->p_textvp, p->p_comm, true);
+               rw_exit(&exec_lock);
 #endif /* PAX_SEGVGUARD */
+
                /* Acquire the sched state mutex.  exit1() will release it. */
                mutex_enter(p->p_lock);
                if (error == 0)
diff -r 238b8712a916 -r 0c19cd435222 sys/kern/vfs_vnode.c
--- a/sys/kern/vfs_vnode.c      Thu Jan 23 10:05:44 2020 +0000
+++ b/sys/kern/vfs_vnode.c      Thu Jan 23 10:21:14 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_vnode.c,v 1.107 2020/01/12 17:49:17 ad Exp $       */
+/*     $NetBSD: vfs_vnode.c,v 1.108 2020/01/23 10:21:14 ad Exp $       */
 
 /*-
  * Copyright (c) 1997-2011, 2019 The NetBSD Foundation, Inc.
@@ -146,7 +146,9 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.107 2020/01/12 17:49:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.108 2020/01/23 10:21:14 ad Exp $");
+
+#include "opt_pax.h"
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -162,6 +164,7 @@
 #include <sys/module.h>
 #include <sys/mount.h>
 #include <sys/namei.h>
+#include <sys/pax.h>
 #include <sys/syscallargs.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
@@ -1675,6 +1678,10 @@
        mutex_enter(vp->v_interlock);
        fstrans_done(mp);
        KASSERT((vp->v_iflag & VI_ONWORKLST) == 0);
+
+#ifdef PAX_SEGVGUARD
+       pax_segvguard_cleanup(vp);
+#endif /* PAX_SEGVGUARD */
 }
 
 /*
diff -r 238b8712a916 -r 0c19cd435222 sys/sys/pax.h
--- a/sys/sys/pax.h     Thu Jan 23 10:05:44 2020 +0000
+++ b/sys/sys/pax.h     Thu Jan 23 10:21:14 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pax.h,v 1.26 2017/05/06 21:34:52 joerg Exp $ */
+/* $NetBSD: pax.h,v 1.27 2020/01/23 10:21:14 ad Exp $ */
 
 /*-
  * Copyright (c) 2006 Elad Efrat <elad%NetBSD.org@localhost>
@@ -53,6 +53,8 @@
 extern int pax_aslr_debug;
 #endif
 
+void   pax_segvguard_cleanup(struct vnode *);
+
 #if defined(PAX_MPROTECT) || defined(PAX_SEGVGUARD) || defined(PAX_ASLR)
 void pax_init(void);
 void pax_set_flags(struct exec_package *, struct proc *);
diff -r 238b8712a916 -r 0c19cd435222 sys/sys/vnode.h
--- a/sys/sys/vnode.h   Thu Jan 23 10:05:44 2020 +0000
+++ b/sys/sys/vnode.h   Thu Jan 23 10:21:14 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vnode.h,v 1.286 2019/12/22 19:47:34 ad Exp $   */
+/*     $NetBSD: vnode.h,v 1.287 2020/01/23 10:21:14 ad Exp $   */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -124,6 +124,7 @@
  * lock.  Field markings and the corresponding locks:
  *
  *     :       stable, reference to the vnode is required
+ *     e       exec_lock
  *     f       vnode_free_list_lock, or vrele_lock for vrele_list
  *     i       v_interlock
  *     u       locked by underlying filesystem
@@ -159,6 +160,7 @@
        enum vtagtype   v_tag;                  /* :: type of underlying data */
        void            *v_data;                /* :: private data for fs */
        struct klist    v_klist;                /* i: notes attached to vnode */
+       void            *v_segvguard;           /* e: for PAX_SEGVGUARD */
 };
 #define        v_usecount      v_uobj.uo_refs
 #define        v_interlock     v_uobj.vmobjlock



Home | Main Index | Thread Index | Old Index