summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2016-05-27 19:45:05 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2016-05-27 19:45:05 +0000
commit78b5afaf3f7a760112fbfce28204da6440738775 (patch)
tree0a7f3cad12fe378e14e0b60deee9ab6a5bcd3e7d /sys
parent7460ea7c8796fa4a440ed3fc75c19fe120c96c5d (diff)
W^X violations are no longer permitted by default. A kernel log message
is generated, and mprotect/mmap return ENOTSUP. If the sysctl(8) flag kern.wxabort is set then a SIGABRT occurs instead, for gdb use or coredump creation. W^X violating programs can be permitted on a ffs/nfs filesystem-basis, using the "wxallowed" mount option. One day far in the future upstream software developers will understand that W^X violations are a tremendously risky practice and that style of programming will be banished outright. Until then, we recommend most users need to use the wxallowed option on their /usr/local filesystem. At least your other filesystems don't permit such programs. ok jca kettenis mlarkin natano
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_sysctl.c5
-rw-r--r--sys/kern/vfs_syscalls.c6
-rw-r--r--sys/sys/mount.h3
-rw-r--r--sys/sys/sysctl.h6
-rw-r--r--sys/uvm/uvm_mmap.c42
5 files changed, 53 insertions, 9 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index b3c854376fe..24c783637e2 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.304 2016/05/23 15:59:19 deraadt Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.305 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -278,6 +278,7 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
extern int usermount, nosuidcoredump;
extern int maxlocksperuid;
extern int pool_debug;
+ extern int uvm_wxabort;
/* all sysctl names at this level are terminal except a ton of them */
if (namelen != 1) {
@@ -590,6 +591,8 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
}
return(0);
}
+ case KERN_WXABORT:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &uvm_wxabort));
case KERN_CONSDEV:
if (cn_tab != NULL)
dev = cn_tab->cn_dev;
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 7a0aa126a59..6798f32f8a5 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.254 2016/05/15 05:04:28 semarie Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.255 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -252,10 +252,10 @@ update:
mp->mnt_flag |= MNT_RDONLY;
else if (mp->mnt_flag & MNT_RDONLY)
mp->mnt_flag |= MNT_WANTRDWR;
- mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
+ mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED | MNT_NODEV |
MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP | MNT_NOATIME |
MNT_FORCE);
- mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC |
+ mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED |
MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP |
MNT_NOATIME | MNT_FORCE);
/*
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 7e55c0e8162..2ab1cc7821a 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mount.h,v 1.125 2016/05/25 13:31:44 deraadt Exp $ */
+/* $OpenBSD: mount.h,v 1.126 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: mount.h,v 1.48 1996/02/18 11:55:47 fvdl Exp $ */
/*
@@ -369,6 +369,7 @@ struct mount {
#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */
#define MNT_NODEV 0x00000010 /* don't interpret special files */
#define MNT_ASYNC 0x00000040 /* file system written asynchronously */
+#define MNT_WXALLOWED 0x00000800 /* filesystem allows W|X mappings */
/*
* exported mount flags.
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 9f01bc20c50..04ec9e8fcbd 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.h,v 1.162 2016/05/23 15:48:57 deraadt Exp $ */
+/* $OpenBSD: sysctl.h,v 1.163 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */
/*
@@ -174,7 +174,7 @@ struct ctlname {
#define KERN_CPTIME2 71 /* array: cp_time2 */
#define KERN_CACHEPCT 72 /* buffer cache % of physmem */
#define KERN_FILE 73 /* struct: file entries */
-/* was KERN_RTHREADS 74 */
+#define KERN_WXABORT 74 /* int: w^x sigabrt & core */
#define KERN_CONSDEV 75 /* dev_t: console terminal device */
#define KERN_NETLIVELOCKS 76 /* int: number of network livelocks */
#define KERN_POOL_DEBUG 77 /* int: enable pool_debug */
@@ -261,7 +261,7 @@ struct ctlname {
{ "cp_time2", CTLTYPE_STRUCT }, \
{ "bufcachepercent", CTLTYPE_INT }, \
{ "file", CTLTYPE_STRUCT }, \
- { "gap", 0 }, \
+ { "wxabort", CTLTYPE_INT }, \
{ "consdev", CTLTYPE_STRUCT }, \
{ "netlivelocks", CTLTYPE_INT }, \
{ "pool_debug", CTLTYPE_INT }, \
diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c
index e5651310afc..0ac5a9ea325 100644
--- a/sys/uvm/uvm_mmap.c
+++ b/sys/uvm/uvm_mmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_mmap.c,v 1.125 2016/05/11 21:52:51 deraadt Exp $ */
+/* $OpenBSD: uvm_mmap.c,v 1.126 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */
/*
@@ -62,6 +62,7 @@
#include <sys/vnode.h>
#include <sys/conf.h>
#include <sys/signalvar.h>
+#include <sys/syslog.h>
#include <sys/stat.h>
#include <sys/specdev.h>
#include <sys/stdint.h>
@@ -305,6 +306,38 @@ sys_mincore(struct proc *p, void *v, register_t *retval)
return (error);
}
+int uvm_wxabort;
+
+/*
+ * W^X violations are only allowed on permitted filesystems.
+ */
+static inline int
+uvm_wxcheck(struct proc *p)
+{
+#if (defined(__mips64__) || defined(__hppa))
+ /* XXX got/plt repairs still needed */
+ return 0;
+#endif
+ int mpwx = (p->p_p->ps_textvp->v_mount &&
+ (p->p_p->ps_textvp->v_mount->mnt_flag & MNT_WXALLOWED));
+
+ if (!mpwx) {
+ struct sigaction sa;
+
+ log(LOG_NOTICE, "%s(%d): mmap W^X violation\n",
+ p->p_comm, p->p_pid);
+ if (uvm_wxabort) {
+ /* Send uncatchable SIGABRT for coredump */
+ memset(&sa, 0, sizeof sa);
+ sa.sa_handler = SIG_DFL;
+ setsigvec(p, SIGABRT, &sa);
+ psignal(p, SIGABRT);
+ }
+ return (ENOTSUP);
+ }
+ return (0);
+}
+
/*
* sys_mmap: mmap system call.
*
@@ -351,6 +384,10 @@ sys_mmap(struct proc *p, void *v, register_t *retval)
*/
if ((prot & PROT_MASK) != prot)
return (EINVAL);
+ if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC) &&
+ (error = uvm_wxcheck(p)))
+ return (error);
+
if ((flags & MAP_FLAGMASK) != flags)
return (EINVAL);
if (flags & MAP_OLDCOPY)
@@ -664,6 +701,9 @@ sys_mprotect(struct proc *p, void *v, register_t *retval)
if ((prot & PROT_MASK) != prot)
return (EINVAL);
+ if ((prot & (PROT_WRITE | PROT_EXEC)) == (PROT_WRITE | PROT_EXEC) &&
+ (error = uvm_wxcheck(p)))
+ return (error);
error = pledge_protexec(p, prot);
if (error)