Module Name:    src
Committed By:   ad
Date:           Thu Jan 23 10:21:14 UTC 2020

Modified Files:
        src/sys/kern: kern_pax.c kern_sig.c vfs_vnode.c
        src/sys/sys: pax.h vnode.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.60 -r1.61 src/sys/kern/kern_pax.c
cvs rdiff -u -r1.381 -r1.382 src/sys/kern/kern_sig.c
cvs rdiff -u -r1.107 -r1.108 src/sys/kern/vfs_vnode.c
cvs rdiff -u -r1.26 -r1.27 src/sys/sys/pax.h
cvs rdiff -u -r1.286 -r1.287 src/sys/sys/vnode.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_pax.c
diff -u src/sys/kern/kern_pax.c:1.60 src/sys/kern/kern_pax.c:1.61
--- src/sys/kern/kern_pax.c:1.60	Sun Jun 25 04:10:47 2017
+++ src/sys/kern/kern_pax.c	Thu Jan 23 10:21:14 2020
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: kern_pax.c,v
 #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_expiry = PAX_SE
 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 @@ struct pax_segvguard_entry {
 };
 
 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 @@ SYSCTL_SETUP(sysctl_security_pax_setup, 
 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 @@ pax_segvguard_elf_flags_active(uint32_t 
 	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 @@ pax_segvguard_cleanup_cb(void *v)
 		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 @@ pax_segvguard(struct lwp *l, struct vnod
 	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 @@ pax_segvguard(struct lwp *l, struct vnod
 	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 @@ pax_segvguard(struct lwp *l, struct vnod
 	 */
 	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);
 
 		/*

Index: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.381 src/sys/kern/kern_sig.c:1.382
--- src/sys/kern/kern_sig.c:1.381	Fri Dec  6 21:36:10 2019
+++ src/sys/kern/kern_sig.c	Thu Jan 23 10:21:14 2020
@@ -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 @@ sigexit(struct lwp *l, int signo)
 		}
 
 #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)

Index: src/sys/kern/vfs_vnode.c
diff -u src/sys/kern/vfs_vnode.c:1.107 src/sys/kern/vfs_vnode.c:1.108
--- src/sys/kern/vfs_vnode.c:1.107	Sun Jan 12 17:49:17 2020
+++ src/sys/kern/vfs_vnode.c	Thu Jan 23 10:21:14 2020
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,
 #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 @@ vcache_reclaim(vnode_t *vp)
 	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 */
 }
 
 /*

Index: src/sys/sys/pax.h
diff -u src/sys/sys/pax.h:1.26 src/sys/sys/pax.h:1.27
--- src/sys/sys/pax.h:1.26	Sat May  6 21:34:52 2017
+++ src/sys/sys/pax.h	Thu Jan 23 10:21:14 2020
@@ -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 <[email protected]>
@@ -53,6 +53,8 @@ struct vmspace;
 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 *);

Index: src/sys/sys/vnode.h
diff -u src/sys/sys/vnode.h:1.286 src/sys/sys/vnode.h:1.287
--- src/sys/sys/vnode.h:1.286	Sun Dec 22 19:47:34 2019
+++ src/sys/sys/vnode.h	Thu Jan 23 10:21:14 2020
@@ -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 @@ LIST_HEAD(buflists, buf);
  * 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 @@ struct vnode {
 	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

Reply via email to