Module Name: src
Committed By: reinoud
Date: Tue Dec 20 15:39:36 UTC 2011
Modified Files:
src/lib/libc/sys: mmap.2
src/sys/sys: mman.h proc.h
src/sys/uvm: uvm_extern.h uvm_map.c uvm_mmap.c
Log Message:
Add a MAP_NOSYSCALLS flag to mmap. This flag prohibits executing of system
calls from the mapped region. This can be used for emulation perposed or for
extra security in the case of generated code.
Its implemented by adding mapping-attributes to each uvm_map_entry. These can
then be queried when needed.
Currently the MAP_NOSYSCALLS is only implemented for x86 but other
architectures are easy to adapt; see the sys/arch/x86/x86/syscall.c patch.
Port maintainers are encouraged to add them for their processor ports too.
When this feature is not yet implemented for an architecture the
MAP_NOSYSCALLS is simply ignored with virtually no cpu cost..
To generate a diff of this commit:
cvs rdiff -u -r1.44 -r1.45 src/lib/libc/sys/mmap.2
cvs rdiff -u -r1.42 -r1.43 src/sys/sys/mman.h
cvs rdiff -u -r1.311 -r1.312 src/sys/sys/proc.h
cvs rdiff -u -r1.176 -r1.177 src/sys/uvm/uvm_extern.h
cvs rdiff -u -r1.307 -r1.308 src/sys/uvm/uvm_map.c
cvs rdiff -u -r1.139 -r1.140 src/sys/uvm/uvm_mmap.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/sys/mmap.2
diff -u src/lib/libc/sys/mmap.2:1.44 src/lib/libc/sys/mmap.2:1.45
--- src/lib/libc/sys/mmap.2:1.44 Sat Oct 15 22:03:03 2011
+++ src/lib/libc/sys/mmap.2 Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-.\" $NetBSD: mmap.2,v 1.44 2011/10/15 22:03:03 rmind Exp $
+.\" $NetBSD: mmap.2,v 1.45 2011/12/20 15:39:35 reinoud Exp $
.\"
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -180,6 +180,9 @@ other processes using
will be seen.
.It Dv MAP_SHARED
Modifications are shared.
+.It Dv MAP_NOSYSCALLS
+No system calls are to be allowed from within this mapped region. They instead
+generate an illegal instruction signal.
.El
.Pp
The
Index: src/sys/sys/mman.h
diff -u src/sys/sys/mman.h:1.42 src/sys/sys/mman.h:1.43
--- src/sys/sys/mman.h:1.42 Tue Nov 18 22:13:49 2008
+++ src/sys/sys/mman.h Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: mman.h,v 1.42 2008/11/18 22:13:49 ad Exp $ */
+/* $NetBSD: mman.h,v 1.43 2011/12/20 15:39:35 reinoud Exp $ */
/*-
* Copyright (c) 1982, 1986, 1993
@@ -98,6 +98,14 @@ typedef __off_t off_t; /* file offset
#define MAP_STACK 0x2000 /* allocated from memory, swap space (stack) */
/*
+ * Map attributes 0x00010000 till 0x00ff0000
+ */
+#define MAP_ATTR(n) ((n) << MAP_ATTRIB_SHIFT)
+#define MAP_ATTRIB_SHIFT 16
+#define MAP_ATTRIB_MASK MAP_ATTR(0xff)
+#define MAP_NOSYSCALLS MAP_ATTR(0x01) /* no syscalls allowed */
+
+/*
* Alignment (expressed in log2). Must be >= log2(PAGE_SIZE) and
* < # bits in a pointer (26 (acorn26), 32 or 64).
*/
Index: src/sys/sys/proc.h
diff -u src/sys/sys/proc.h:1.311 src/sys/sys/proc.h:1.312
--- src/sys/sys/proc.h:1.311 Fri Oct 21 02:07:07 2011
+++ src/sys/sys/proc.h Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.311 2011/10/21 02:07:07 christos Exp $ */
+/* $NetBSD: proc.h,v 1.312 2011/12/20 15:39:35 reinoud Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -353,6 +353,7 @@ struct proc {
#define PK_NOCLDWAIT 0x00020000 /* No zombies if child dies */
#define PK_32 0x00040000 /* 32-bit process (used on 64-bit kernels) */
#define PK_CLDSIGIGN 0x00080000 /* Process is ignoring SIGCHLD */
+#define PK_CHKNOSYSCALL 0x00100000 /* Process needs NOSYSCALL checking */
#define PK_MARKER 0x80000000 /* Is a dummy marker process */
/*
Index: src/sys/uvm/uvm_extern.h
diff -u src/sys/uvm/uvm_extern.h:1.176 src/sys/uvm/uvm_extern.h:1.177
--- src/sys/uvm/uvm_extern.h:1.176 Thu Sep 1 06:40:28 2011
+++ src/sys/uvm/uvm_extern.h Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_extern.h,v 1.176 2011/09/01 06:40:28 matt Exp $ */
+/* $NetBSD: uvm_extern.h,v 1.177 2011/12/20 15:39:35 reinoud Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -680,6 +680,11 @@ void uvmspace_unshare(struct lwp *);
void uvm_whatis(uintptr_t, void (*)(const char *, ...));
+bool uvm_map_setattr(struct vm_map *, vaddr_t,
+ vaddr_t, uint32_t);
+bool uvm_map_checkattr(struct vm_map *, vaddr_t,
+ vaddr_t, uint32_t);
+
/* uvm_meter.c */
int uvm_sysctl(int *, u_int, void *, size_t *,
void *, size_t, struct proc *);
Index: src/sys/uvm/uvm_map.c
diff -u src/sys/uvm/uvm_map.c:1.307 src/sys/uvm/uvm_map.c:1.308
--- src/sys/uvm/uvm_map.c:1.307 Tue Dec 20 13:47:38 2011
+++ src/sys/uvm/uvm_map.c Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_map.c,v 1.307 2011/12/20 13:47:38 yamt Exp $ */
+/* $NetBSD: uvm_map.c,v 1.308 2011/12/20 15:39:35 reinoud Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.307 2011/12/20 13:47:38 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.308 2011/12/20 15:39:35 reinoud Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@@ -1672,6 +1672,7 @@ nomerge:
new_entry->protection = prot;
new_entry->max_protection = maxprot;
new_entry->inheritance = inherit;
+ new_entry->map_attrib = 0; /* XXX could be passed too */
new_entry->wired_count = 0;
new_entry->advice = advice;
if (flags & UVM_FLAG_OVERLAY) {
@@ -4121,6 +4122,83 @@ uvm_map_checkprot(struct vm_map *map, va
}
/*
+ * uvm_map_setattr: set uvm-external mapping attributes in map
+ *
+ * => map must be read or write locked by caller.
+ */
+
+bool
+uvm_map_setattr(struct vm_map *map, vaddr_t start, vaddr_t end,
+ uint32_t map_attrib)
+{
+ struct vm_map_entry *entry;
+ struct vm_map_entry *tmp_entry;
+
+ if (!uvm_map_lookup_entry(map, start, &tmp_entry)) {
+ return (false);
+ }
+ entry = tmp_entry;
+ while (start < end) {
+ if (entry == &map->header) {
+ return (false);
+ }
+
+ /*
+ * no holes allowed
+ */
+
+ if (start < entry->start) {
+ return (false);
+ }
+
+ /* set attributes associated with entry */
+
+ entry->map_attrib = map_attrib;
+
+ start = entry->end;
+ entry = entry->next;
+ }
+ return (true);
+}
+
+/*
+ * uvm_map_checkattr: check attribute bits in map
+ *
+ * => check if attribute is present in the region.
+ * => map must be read or write locked by caller.
+ */
+
+bool
+uvm_map_checkattr(struct vm_map *map, vaddr_t start, vaddr_t end,
+ uint32_t map_attrib)
+{
+ struct vm_map_entry *entry;
+ struct vm_map_entry *tmp_entry;
+
+ if (!uvm_map_lookup_entry(map, start, &tmp_entry))
+ return (false);
+
+ entry = tmp_entry;
+ while (start < end) {
+ if (entry == &map->header)
+ return (false);
+
+ /*
+ * check attribute associated with entry
+ */
+
+ if ((entry->map_attrib & map_attrib) == map_attrib) {
+ return (true);
+ }
+
+ start = entry->end;
+ entry = entry->next;
+ }
+ return (false);
+}
+
+
+/*
* uvmspace_alloc: allocate a vmspace structure.
*
* - structure includes vm_map and pmap
Index: src/sys/uvm/uvm_mmap.c
diff -u src/sys/uvm/uvm_mmap.c:1.139 src/sys/uvm/uvm_mmap.c:1.140
--- src/sys/uvm/uvm_mmap.c:1.139 Fri Oct 14 09:23:31 2011
+++ src/sys/uvm/uvm_mmap.c Tue Dec 20 15:39:35 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_mmap.c,v 1.139 2011/10/14 09:23:31 hannken Exp $ */
+/* $NetBSD: uvm_mmap.c,v 1.140 2011/12/20 15:39:35 reinoud Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v 1.139 2011/10/14 09:23:31 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_mmap.c,v 1.140 2011/12/20 15:39:35 reinoud Exp $");
#include "opt_compat_netbsd.h"
#include "opt_pax.h"
@@ -547,6 +547,23 @@ sys_mmap(struct lwp *l, const struct sys
/* remember to add offset */
*retval = (register_t)(addr + pageoff);
+ /*
+ * Support for map attributes; XXX preferably given as an
+ * extra parameter to uvm_map or merged with uvmflag.
+ * Implemented now as setting parameters after the mapping.
+ */
+ if (error == 0) {
+ if (flags & MAP_ATTRIB_MASK) {
+ if (!uvm_map_setattr(&p->p_vmspace->vm_map,
+ addr, addr + size,
+ flags & MAP_ATTRIB_MASK))
+ panic("uvm_setattr failed?");
+ }
+ /* record if we need optimization for system call checking */
+ if (flags & MAP_NOSYSCALLS)
+ p->p_flag |= PK_CHKNOSYSCALL;
+ }
+
if (fp != NULL)
fd_putfile(fd);