Skip to content

Commit

Permalink
W^X violations are no longer permitted by default. A kernel log message
Browse files Browse the repository at this point in the history
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
  • Loading branch information
deraadt committed May 27, 2016
1 parent d3b9913 commit 9f25ea0
Show file tree
Hide file tree
Showing 14 changed files with 117 additions and 22 deletions.
14 changes: 12 additions & 2 deletions lib/libc/sys/mmap.2
@@ -1,4 +1,4 @@
.\" $OpenBSD: mmap.2,v 1.51 2014/07/10 19:00:23 matthew Exp $
.\" $OpenBSD: mmap.2,v 1.52 2016/05/27 19:45:04 deraadt Exp $
.\" $NetBSD: mmap.2,v 1.5 1995/06/24 10:48:59 cgd Exp $
.\"
.\" Copyright (c) 1991, 1993
Expand Down Expand Up @@ -30,7 +30,7 @@
.\"
.\" @(#)mmap.2 8.1 (Berkeley) 6/4/93
.\"
.Dd $Mdocdate: July 10 2014 $
.Dd $Mdocdate: May 27 2016 $
.Dt MMAP 2
.Os
.Sh NAME
Expand Down Expand Up @@ -273,6 +273,16 @@ was specified and the
parameter wasn't available.
.Dv MAP_ANON
was specified and insufficient memory was available.
.It Bq Er ENOTSUP
The accesses requested in the
.Ar prot
argument are not allowed.
In particular,
.Dv PROT_WRITE | PROT_EXEC
mappings are not permitted in most binaries (see
.Dv kern.wxabort
in sysctl 3
for more information).
.El
.Sh SEE ALSO
.Xr madvise 2 ,
Expand Down
15 changes: 13 additions & 2 deletions lib/libc/sys/mount.2
@@ -1,4 +1,4 @@
.\" $OpenBSD: mount.2,v 1.45 2015/11/23 10:01:45 jmc Exp $
.\" $OpenBSD: mount.2,v 1.46 2016/05/27 19:45:04 deraadt Exp $
.\" $NetBSD: mount.2,v 1.12 1996/02/29 23:47:48 jtc Exp $
.\"
.\" Copyright (c) 1980, 1989, 1993
Expand Down Expand Up @@ -30,7 +30,7 @@
.\"
.\" @(#)mount.2 8.2 (Berkeley) 12/11/93
.\"
.Dd $Mdocdate: November 23 2015 $
.Dd $Mdocdate: May 27 2016 $
.Dt MOUNT 2
.Os
.Sh NAME
Expand Down Expand Up @@ -95,6 +95,17 @@ All I/O to the filesystem should be done asynchronously.
Use soft dependencies.
Applies to FFS filesystems only (see 'softdep' in
.Xr mount 8 ) .
.It MNT_WXALLOWED
Processes that ask for memory to be made writeable plus executable
using the
.Xr mmap 2
and
.Xr mprotect 2
system calls are killed by default.
This option allows those processes to continue operation.
The option is typically used on the
.Pa /usr/local
filesystem.
.El
.Pp
The flag
Expand Down
14 changes: 12 additions & 2 deletions lib/libc/sys/mprotect.2
@@ -1,4 +1,4 @@
.\" $OpenBSD: mprotect.2,v 1.19 2014/07/02 22:22:35 matthew Exp $
.\" $OpenBSD: mprotect.2,v 1.20 2016/05/27 19:45:04 deraadt Exp $
.\" $NetBSD: mprotect.2,v 1.6 1995/10/12 15:41:08 jtc Exp $
.\"
.\" Copyright (c) 1991, 1993
Expand Down Expand Up @@ -30,7 +30,7 @@
.\"
.\" @(#)mprotect.2 8.1 (Berkeley) 6/9/93
.\"
.Dd $Mdocdate: July 2 2014 $
.Dd $Mdocdate: May 27 2016 $
.Dt MPROTECT 2
.Os
.Sh NAME
Expand Down Expand Up @@ -96,6 +96,16 @@ The process has locked future pages with
.Fn mlockall MCL_FUTURE ,
a page being protected is not currently accessible,
and making it accessible and locked would exceed process or system limits.
.It Bq Er ENOTSUP
The accesses requested in the
.Ar prot
argument are not allowed.
In particular,
.Dv PROT_WRITE | PROT_EXEC
mappings are not permitted in most binaries (see
.Dv kern.wxabort
in sysctl 3
for more information).
.It Bq Er EINVAL
The
.Fa prot
Expand Down
3 changes: 2 additions & 1 deletion sbin/mount/mntopts.h
@@ -1,4 +1,4 @@
/* $OpenBSD: mntopts.h,v 1.16 2014/07/13 12:01:30 claudio Exp $ */
/* $OpenBSD: mntopts.h,v 1.17 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: mntopts.h,v 1.3 1995/03/18 14:56:59 cgd Exp $ */

/*-
Expand Down Expand Up @@ -58,6 +58,7 @@ union mntval {
#define MOPT_NODEV { "dev", MNT_NODEV, MFLAG_INVERSE | MFLAG_SET }
#define MOPT_NOEXEC { "exec", MNT_NOEXEC, MFLAG_INVERSE | MFLAG_SET }
#define MOPT_NOSUID { "suid", MNT_NOSUID, MFLAG_INVERSE | MFLAG_SET }
#define MOPT_WXALLOWED { "wxallowed", MNT_WXALLOWED, MFLAG_SET }
#define MOPT_RDONLY { "rdonly", MNT_RDONLY, MFLAG_SET }
#define MOPT_SYNC { "sync", MNT_SYNCHRONOUS, MFLAG_SET }
#define MOPT_USERQUOTA { "userquota", 0, MFLAG_SET | MFLAG_STRVAL \
Expand Down
15 changes: 13 additions & 2 deletions sbin/mount/mount.8
@@ -1,4 +1,4 @@
.\" $OpenBSD: mount.8,v 1.77 2014/09/08 04:40:30 doug Exp $
.\" $OpenBSD: mount.8,v 1.78 2016/05/27 19:45:04 deraadt Exp $
.\" $NetBSD: mount.8,v 1.11 1995/07/12 06:23:21 cgd Exp $
.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
Expand Down Expand Up @@ -30,7 +30,7 @@
.\"
.\" @(#)mount.8 8.7 (Berkeley) 3/27/94
.\"
.Dd $Mdocdate: September 8 2014 $
.Dd $Mdocdate: May 27 2016 $
.Dt MOUNT 8
.Os
.Sh NAME
Expand Down Expand Up @@ -234,6 +234,17 @@ are mutually exclusive.
.It sync
Regular data I/O to the file system should be done synchronously.
By default, only metadata is read/written synchronously.
.It wxallowed
Processes that ask for memory to be made writeable plus executable
using the
.Xr mmap 2
and
.Xr mprotect 2
system calls are killed by default.
This option allows those processes to continue operation.
The option is typically used on the
.Pa /usr/local
filesystem.
.It update
The same as
.Fl u ;
Expand Down
3 changes: 2 additions & 1 deletion sbin/mount/mount.c
@@ -1,4 +1,4 @@
/* $OpenBSD: mount.c,v 1.63 2016/05/25 13:56:37 deraadt Exp $ */
/* $OpenBSD: mount.c,v 1.64 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp $ */

/*
Expand Down Expand Up @@ -88,6 +88,7 @@ static struct opt {
{ MNT_NODEV, 0, "nodev", "nodev" },
{ MNT_NOEXEC, 0, "noexec", "noexec" },
{ MNT_NOSUID, 0, "nosuid", "nosuid" },
{ MNT_WXALLOWED, 0, "wxallowed", "wxallowed" },
{ MNT_QUOTA, 0, "with quotas", "" },
{ MNT_RDONLY, 0, "read-only", "ro" },
{ MNT_ROOTFS, 1, "root file system", "" },
Expand Down
3 changes: 2 additions & 1 deletion sbin/mount_ffs/mount_ffs.c
@@ -1,4 +1,4 @@
/* $OpenBSD: mount_ffs.c,v 1.22 2015/12/08 15:56:42 tedu Exp $ */
/* $OpenBSD: mount_ffs.c,v 1.23 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: mount_ffs.c,v 1.3 1996/04/13 01:31:19 jtc Exp $ */

/*-
Expand Down Expand Up @@ -47,6 +47,7 @@ void ffs_usage(void);

static const struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_WXALLOWED,
MOPT_ASYNC,
MOPT_SYNC,
MOPT_UPDATE,
Expand Down
3 changes: 2 additions & 1 deletion sbin/mount_nfs/mount_nfs.c
@@ -1,4 +1,4 @@
/* $OpenBSD: mount_nfs.c,v 1.52 2015/01/16 06:39:59 deraadt Exp $ */
/* $OpenBSD: mount_nfs.c,v 1.53 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: mount_nfs.c,v 1.12.4.1 1996/05/25 22:48:05 fvdl Exp $ */

/*
Expand Down Expand Up @@ -85,6 +85,7 @@

const struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_WXALLOWED,
MOPT_FORCE,
MOPT_UPDATE,
MOPT_SYNC,
Expand Down
5 changes: 4 additions & 1 deletion 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 $ */

/*-
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions 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 $ */

/*
Expand Down Expand Up @@ -252,10 +252,10 @@ sys_mount(struct proc *p, void *v, register_t *retval)
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);
/*
Expand Down
3 changes: 2 additions & 1 deletion 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 $ */

/*
Expand Down Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions 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 $ */

/*
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 }, \
Expand Down
42 changes: 41 additions & 1 deletion 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 $ */

/*
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
7 changes: 6 additions & 1 deletion usr.sbin/pstat/pstat.c
@@ -1,4 +1,4 @@
/* $OpenBSD: pstat.c,v 1.104 2016/05/25 13:32:29 deraadt Exp $ */
/* $OpenBSD: pstat.c,v 1.105 2016/05/27 19:45:04 deraadt Exp $ */
/* $NetBSD: pstat.c,v 1.27 1996/10/23 22:50:06 cgd Exp $ */

/*-
Expand Down Expand Up @@ -723,6 +723,11 @@ mount_print(struct mount *mp)
flags &= ~MNT_EXPORTANON;
comma = ",";
}
if (flags & MNT_WXALLOWED) {
(void)printf("%swxallowed", comma);
flags &= ~MNT_WXALLOWED;
comma = ",";
}
if (flags & MNT_LOCAL) {
(void)printf("%slocal", comma);
flags &= ~MNT_LOCAL;
Expand Down

0 comments on commit 9f25ea0

Please sign in to comment.