[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    immutable userland mappings
From:       "Theo de Raadt" <deraadt () openbsd ! org>
Date:       2022-09-01 13:13:28
Message-ID: 18801.1662038008 () cvs ! openbsd ! org
[Download RAW message or body]

In the last few years, I have been improving the strictness of userland
memory layout.

An example is the recent addition of MAP_STACK and msyscall().  The first one
marks pages that are stack, so that upon entry to the kernel we can check if
the stack-pointer is pointing in the stack range.  If it isn't, the most obvious
conclusion is that a ROP pivot has occured, and we kills the process.  The second
one marks the region which contains syscall traps, if upon entry to the kernel
the PC is not in that region, we know somone is trying to do system calls via
an unapproved method.

My next attempt is to lock memory mappings.  The current working name is
mimmutable(void *addr, size_t len).  This identifies all current mapped memory
in a region, and tags the mappings.  Such mappings can never be unmapped.
No new mmap can be done on top of the mappings.  And the permissions cannot
be changed.  Other than that, the underlying storage memory works fine, it is
just the mapping that is locked.

I'm aware of an method used at least once (not on openbsd) which managed
to mprotect a region of libc, and then place things there, for later
execution.  That makes msyscall() less useful, so I want to restore the
strenth.

In this version of the diff, the kernel manages to mark immutable most of
the main binary, and in the shared-binary case, also most of ld.so.  But it
cannot mark all of the ELF mapping -- because of two remaining problems (RELRO
in .data, and the malloc.c self-protected bookkeeping page in .bss).  I am
looking into various solutions for both of those.

So for now, crt0 self-immutables the remaining parts, and ld.so does the same
for itself.  ld.so is also responsible for immutable marking on libraries it
loads.

To my surprise, the diff is working quite well.  With kern.allowkmem=1,
"procmap -a" can see what process mappings look like, and they are quite
locked down.  This is a view of a "sed", with 'grep -v anon'.  The "I" marker
indicates mapping immutability.   A few small chunks must still be fixed.

Start            End                 Size  Offset           rwxSeIpc  RWX  I/W/A Dev  \
Inode - File 000003128621a000-000003128621cfff      12k 0000000000000000 r----Ip+ \
(rwx) 1/0/0 04:05   77840 - /usr/bin/sed [0xfffffd83e38b3640] \
000003128621d000-0000031286222fff      24k 0000000000002000 r-x--Ip+ (rwx) 1/0/0 \
04:05   77840 - /usr/bin/sed [0xfffffd83e38b3640] 000003148bbc3000-000003148bbc3fff   \
4k 0000000000000000 r----Is- (r--) 1/0/1 00:00       0 -   [ uvm_aobj ] \
00000314ea4e7000-00000314ea51dfff     220k 0000000000000000 r----Ip+ (rwx) 1/0/0 \
04:05  103688 - /usr/lib/libc.so.96.1 [0xfffffd83e0c62608] \
00000314ea51e000-00000314ea5c2fff     660k 0000000000036000 r-x-eIp+ (rwx) 1/0/0 \
04:05  103688 - /usr/lib/libc.so.96.1 [0xfffffd83e0c62608] \
00000314ea5c3000-00000314ea5c8fff      24k 00000000000da000 r----Ip- (rwx) 1/0/0 \
04:05  103688 - /usr/lib/libc.so.96.1 [0xfffffd83e0c62608] \
00000314ea5c9000-00000314ea5cbfff      12k 00000000000df000 rw---Ip- (rwx) 1/0/0 \
04:05  103688 - /usr/lib/libc.so.96.1 [0xfffffd83e0c62608] \
0000031526544000-0000031526544fff       4k 0000000000000000 r-x-eIp+ (rwx) 1/0/1 \
00:00       0 -   [ uvm_aobj ] 0000031535da7000-0000031535da9fff      12k \
0000000000000000 r----Ip+ (rwx) 1/0/0 04:05  336963 - /usr/libexec/ld.so \
[0xfffffd83e27f90e8] 0000031535eac000-0000031535eb6fff      44k 0000000000005000 \
r-x-eIp+ (rwx) 1/0/0 04:05  336963 - /usr/libexec/ld.so [0xfffffd83e27f90e8] \
0000031535fa7000-0000031535fa7fff       4k 0000000000010000 r-----p- (rwx) 1/0/0 \
04:05  336963 - /usr/libexec/ld.so [0xfffffd83e27f90e8] \
0000031535fa8000-0000031535fa8fff       4k 0000000000011000 rw----p- (rwx) 1/0/0 \
04:05  336963 - /usr/libexec/ld.so [0xfffffd83e27f90e8] \
000003154a19e000-000003154a1b1fff      80k 0000000000000000 r----Ip+ (rwx) 1/0/0 \
04:04 3654731 - /var/run/ld.so.hints [0xfffffd83e1098960] \
00007f7ffdebd000-00007f7fffbbcfff   29696k 0000000000000000 ------p+ (rwx) 1/0/0 \
00:00       0 -   [ stack ]  total                               5724k


I wanted to show it a bit early.  To try the diff:
  - apply patch
  - cd /usr/src/sys/kern; make syscalls
  - build and boot new kernel
  - cd /usr/src; make includes
  - cd lib/libc; make && make install
  - cd /usr/src/*/ld.so; make && make install
  - cd /usr/src/lib/csu; make && make install
  - then other binaries can be built, including procmap



Index: lib/csu/boot.h
===================================================================
RCS file: /cvs/src/lib/csu/boot.h,v
retrieving revision 1.33
diff -u -p -u -r1.33 boot.h
--- lib/csu/boot.h	12 Jan 2022 21:41:06 -0000	1.33
+++ lib/csu/boot.h	31 Aug 2022 05:14:09 -0000
@@ -35,7 +35,6 @@
 #define	_DYN_LOADER
 
 #include <sys/exec_elf.h>
-#include <sys/mman.h>
 
 #include <machine/reloc.h>
 
@@ -50,6 +49,7 @@ void _dl_exit(int);
  */
 #define REDIRECT_SYSCALL(x)	typeof(x) x asm("_libc_"#x) __dso_hidden
 REDIRECT_SYSCALL(mprotect);
+REDIRECT_SYSCALL(mimmutable);
 
 #if RELOC_TAG == DT_RELA
 typedef	Elf_RelA	RELOC_TYPE;
Index: lib/csu/crt0.c
===================================================================
RCS file: /cvs/src/lib/csu/crt0.c,v
retrieving revision 1.17
diff -u -p -u -r1.17 crt0.c
--- lib/csu/crt0.c	12 Jan 2022 21:41:06 -0000	1.17
+++ lib/csu/crt0.c	31 Aug 2022 05:13:46 -0000
@@ -32,6 +32,7 @@
  */
 
 #include <sys/syscall.h>
+#include <sys/mman.h>
 #include <stdlib.h>
 #include <limits.h>
 
@@ -83,6 +84,7 @@ ___start(MD_START_ARGS)
 {
 	size_t size, i;
 	char ***environp;
+	extern char __data_start[], __bss_start[];
 #ifdef MD_START_SETUP
 	MD_START_SETUP
 #endif
@@ -96,6 +98,9 @@ ___start(MD_START_ARGS)
 		for (i = 0; i < size; i++)
 			__preinit_array_start[i](argc, argv, envp, NULL);
 		RCRT0_RELRO();
+		/* Kernel does not mark writeable segments immutable */
+		mimmutable(&__data_start,
+		    (size_t)&__bss_start - (size_t)&__data_start);
 		size = __init_array_end - __init_array_start;
 		for (i = 0; i < size; i++)
 			__init_array_start[i](argc, argv, envp, NULL);
Index: lib/libc/Symbols.list
===================================================================
RCS file: /cvs/src/lib/libc/Symbols.list,v
retrieving revision 1.75
diff -u -p -u -r1.75 Symbols.list
--- lib/libc/Symbols.list	2 Aug 2022 16:45:00 -0000	1.75
+++ lib/libc/Symbols.list	24 Aug 2022 00:39:15 -0000
@@ -131,6 +131,7 @@ _thread_sys_lseek
 _thread_sys_lstat
 _thread_sys_madvise
 _thread_sys_minherit
+_thread_sys_mimmutable
 _thread_sys_mkdir
 _thread_sys_mkdirat
 _thread_sys_mkfifo
@@ -325,6 +326,7 @@ listen
 lseek
 lstat
 madvise
+mimmutable
 minherit
 mkdir
 mkdirat
Index: lib/libc/hidden/sys/mman.h
===================================================================
RCS file: /cvs/src/lib/libc/hidden/sys/mman.h,v
retrieving revision 1.4
diff -u -p -u -r1.4 mman.h
--- lib/libc/hidden/sys/mman.h	11 Jan 2019 18:46:30 -0000	1.4
+++ lib/libc/hidden/sys/mman.h	30 Aug 2022 23:54:47 -0000
@@ -26,6 +26,7 @@ PROTO_NORMAL(mlock);
 PROTO_NORMAL(mlockall);
 PROTO_NORMAL(mmap);
 PROTO_NORMAL(mprotect);
+PROTO_NORMAL(mimmutable);
 PROTO_NORMAL(mquery);
 PROTO_CANCEL(msync);
 PROTO_NORMAL(munlock);
Index: lib/libc/stdlib/malloc.c
===================================================================
RCS file: /cvs/src/lib/libc/stdlib/malloc.c,v
retrieving revision 1.274
diff -u -p -u -r1.274 malloc.c
--- lib/libc/stdlib/malloc.c	30 Jun 2022 17:15:48 -0000	1.274
+++ lib/libc/stdlib/malloc.c	31 Aug 2022 07:39:36 -0000
@@ -229,6 +229,7 @@ static union {
 	struct malloc_readonly mopts;
 	u_char _pad[MALLOC_PAGESIZE];
 } malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)));
+//	__attribute__((section("mutable")));
 #define mopts	malloc_readonly.mopts
 
 char		*malloc_options;	/* compile-time options */
Index: lib/libc/sys/Makefile.inc
===================================================================
RCS file: /cvs/src/lib/libc/sys/Makefile.inc,v
retrieving revision 1.163
diff -u -p -u -r1.163 Makefile.inc
--- lib/libc/sys/Makefile.inc	17 Jul 2022 03:04:27 -0000	1.163
+++ lib/libc/sys/Makefile.inc	24 Aug 2022 00:33:59 -0000
@@ -58,7 +58,7 @@ ASM=	__semctl.o __syscall.o __thrsigdive
 	getsockopt.o ioctl.o \
 	kevent.o kill.o kqueue.o ktrace.o lchown.o \
 	link.o linkat.o listen.o lseek.o lstat.o \
-	madvise.o minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
+	madvise.o mimmutable.o minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \
 	mknod.o mknodat.o mlock.o mlockall.o mmap.o mount.o mprotect.o \
 	mquery.o msgctl.o msgget.o munlock.o munlockall.o munmap.o \
 	nfssvc.o \
Index: libexec/ld.so/Makefile
===================================================================
RCS file: /cvs/src/libexec/ld.so/Makefile,v
retrieving revision 1.82
diff -u -p -u -r1.82 Makefile
--- libexec/ld.so/Makefile	23 Dec 2021 18:50:32 -0000	1.82
+++ libexec/ld.so/Makefile	31 Aug 2022 13:49:31 -0000
@@ -28,8 +28,8 @@ SRCS+=	dl_uname.c dl_dirname.c strlcat.c
 SRCS+=	malloc.c reallocarray.c tib.c ffs.c
 
 syscall=close exit fstat getdents getentropy getthrid issetugid kbind \
-	mmap mprotect munmap msyscall open pledge read __realpath sendsyslog \
-	__set_tcb sysctl thrkill utrace write
+	mimmutable mmap mprotect munmap msyscall open pledge read \
+	__realpath sendsyslog __set_tcb sysctl thrkill utrace write
 
 .if (${MACHINE_ARCH} == "i386")
 syscall+=mquery
Index: libexec/ld.so/library.c
===================================================================
RCS file: /cvs/src/libexec/ld.so/library.c,v
retrieving revision 1.87
diff -u -p -u -r1.87 library.c
--- libexec/ld.so/library.c	20 Aug 2022 14:11:31 -0000	1.87
+++ libexec/ld.so/library.c	31 Aug 2022 13:55:22 -0000
@@ -95,6 +95,35 @@ unload:
 	}
 }
 
+void
+_dl_defer_mimmutable(elf_object_t *object, void *start, size_t len)
+{
+	int i;
+
+	for (i = 0; i < sizeof(object->wloads)/sizeof(object->wloads[0]); i++)
+		if (object->wloads[i].start == NULL) {
+			object->wloads[i].start = start;
+			object->wloads[i].len = len;
+			break;
+		}
+}
+
+void
+_dl_apply_defer_mimmutable(void)
+{
+	struct elf_object *object;
+	int i;
+
+	for (object = _dl_objects; object; object = object->next) {
+		for (i = 0;
+		    i < sizeof(object->wloads)/sizeof(object->wloads[0]); i++) {
+			if (object->wloads[i].start)
+				_dl_mimmutable(object->wloads[i].start,
+				    object->wloads[i].len);
+		}
+	}
+}
+
 elf_object_t *
 _dl_tryload_shlib(const char *libname, int type, int flags)
 {
@@ -327,6 +356,34 @@ _dl_tryload_shlib(const char *libname, i
 			if (_dl_msyscall(exec_start, exec_size) == -1)
 				_dl_printf("msyscall %lx %lx error\n",
 				    exec_start, exec_size);
+		}
+
+		if (type == OBJTYPE_LIB &&
+		    ((object->obj_flags & (DF_1_INITFIRST | DF_1_NODELETE)))) {
+			phdp = (Elf_Phdr *)(hbuf + ehdr->e_phoff);
+			for (i = 0; i < ehdr->e_phnum; i++, phdp++) {
+				char *start;
+				Elf_Addr off;
+				Elf_Addr size;
+				
+				switch (phdp->p_type) {
+				case PT_LOAD:
+					start = (char *)(TRUNC_PG(phdp->p_vaddr)) + loff;
+					off = (phdp->p_vaddr & align);
+					size = off + phdp->p_filesz;
+
+					if (size == 0)
+						break;
+					if ((phdp->p_flags & PF_W) == 0)
+						_dl_mimmutable(start, ROUND_PG(size));
+					else
+						_dl_defer_mimmutable(object,
+						    start, ROUND_PG(size));
+					break;
+				}
+			}
+		} else {
+	//		_dl_printf("- %s: %x %x\n", soname, object->obj_flags, flags);
 		}
 	} else {
 		_dl_munmap((void *)libaddr, maxva - minva);
Index: libexec/ld.so/loader.c
===================================================================
RCS file: /cvs/src/libexec/ld.so/loader.c,v
retrieving revision 1.195
diff -u -p -u -r1.195 loader.c
--- libexec/ld.so/loader.c	8 Jan 2022 06:49:41 -0000	1.195
+++ libexec/ld.so/loader.c	31 Aug 2022 13:27:27 -0000
@@ -218,11 +218,15 @@ _dl_clean_boot(void)
 #if 0	/* XXX breaks boehm-gc?!? */
 	extern char boot_data_start[], boot_data_end[];
 #endif
+	extern char __data_start[], _end[];
 
 	_dl_munmap(boot_text_start, boot_text_end - boot_text_start);
 #if 0	/* XXX breaks boehm-gc?!? */
 	_dl_munmap(boot_data_start, boot_data_end - boot_data_start);
 #endif
+//	_dl_printf("%llx %llx len %llx\n", _ldso_data, _ldso_edata,
+//	    _ldso_end - _ldso_data);
+	_dl_mimmutable(__data_start, _end - __data_start);
 }
 #endif /* DO_CLEAN_BOOT */
 
@@ -375,7 +379,7 @@ _dl_load_dep_libs(elf_object_t *object, 
 				DL_DEB(("loading: %s required by %s\n", libname,
 				    dynobj->load_name));
 				depobj = _dl_load_shlib(libname, dynobj,
-				    OBJTYPE_LIB, depflags);
+				    OBJTYPE_LIB, depflags | DF_1_NODELETE);
 				if (depobj == 0) {
 					if (booting) {
 						_dl_die(
@@ -437,7 +441,6 @@ _dl_self_relro(long loff)
 	}
 }
 
-
 #define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \
 		   (((X) & PF_W) ? PROT_WRITE : 0) | \
 		   (((X) & PF_X) ? PROT_EXEC : 0))
@@ -696,6 +699,8 @@ _dl_boot(const char **argv, char **envp,
 		_dl_call_preinit(_dl_objects);
 		_dl_call_init(_dl_objects);
 	}
+
+	_dl_apply_defer_mimmutable();
 
 	DL_DEB(("entry point: 0x%lx\n", dl_data[AUX_entry]));
 
Index: libexec/ld.so/resolve.h
===================================================================
RCS file: /cvs/src/libexec/ld.so/resolve.h,v
retrieving revision 1.101
diff -u -p -u -r1.101 resolve.h
--- libexec/ld.so/resolve.h	20 Aug 2022 14:11:31 -0000	1.101
+++ libexec/ld.so/resolve.h	30 Aug 2022 13:58:50 -0000
@@ -77,6 +77,11 @@ struct object_vector {
 };
 void	object_vec_grow(struct object_vector *_vec, int _more);
 
+struct dregion {
+	char *start;
+	size_t len;
+};
+
 /*
  *  Structure describing a loaded object.
  *  The head of this struct must be compatible
@@ -231,6 +236,8 @@ struct elf_object {
 
 	/* nonzero if trace enabled for this object */
 	int traced;
+
+	struct dregion wloads[2];
 };
 
 struct dep_node {
Index: libexec/ld.so/sod.c
===================================================================
RCS file: /cvs/src/libexec/ld.so/sod.c,v
retrieving revision 1.36
diff -u -p -u -r1.36 sod.c
--- libexec/ld.so/sod.c	8 Jan 2022 06:49:41 -0000	1.36
+++ libexec/ld.so/sod.c	31 Aug 2022 06:56:02 -0000
@@ -186,6 +186,8 @@ _dl_maphints(void)
 	if (hheader->hh_version >= LD_HINTS_VERSION_2)
 		_dl_hint_search_path = _dl_split_path(hstrtab + hheader->hh_dirlist);
 
+	_dl_mimmutable(addr, hsize);
+
 	/* close the file descriptor, leaving the hints mapped */
 	_dl_close(hfd);
 
Index: libexec/ld.so/sod.h
===================================================================
RCS file: /cvs/src/libexec/ld.so/sod.h,v
retrieving revision 1.4
diff -u -p -u -r1.4 sod.h
--- libexec/ld.so/sod.h	23 Jan 2017 11:04:19 -0000	1.4
+++ libexec/ld.so/sod.h	31 Aug 2022 13:27:23 -0000
@@ -36,4 +36,5 @@ void _dl_build_sod(const char *name, str
 void _dl_set_sod(const char *, struct sod *);
 char *_dl_findhint(char *name, int major, int minor, char *prefered_path);
 extern char **_dl_hint_search_path;
+void _dl_apply_defer_mimmutable(void);
 __END_HIDDEN_DECLS
Index: libexec/ld.so/syscall.h
===================================================================
RCS file: /cvs/src/libexec/ld.so/syscall.h,v
retrieving revision 1.2
diff -u -p -u -r1.2 syscall.h
--- libexec/ld.so/syscall.h	8 Jan 2022 06:49:41 -0000	1.2
+++ libexec/ld.so/syscall.h	30 Aug 2022 08:10:24 -0000
@@ -52,6 +52,7 @@ int	_dl_mprotect(const void *, size_t, i
 void   *_dl_mquery(void *, size_t, int, int, int, off_t);
 int	_dl_msyscall(void *addr, size_t len);
 int	_dl_munmap(const void *, size_t);
+int	_dl_mimmutable(const void *, size_t);
 int	_dl_open(const char *, int);
 int	_dl_pledge(const char *, const char **);
 ssize_t	_dl_read(int, const char *, size_t);
Index: libexec/ld.so/aarch64/ld.script
===================================================================
RCS file: /cvs/src/libexec/ld.so/aarch64/ld.script,v
retrieving revision 1.1
diff -u -p -u -r1.1 ld.script
--- libexec/ld.so/aarch64/ld.script	10 May 2019 13:29:21 -0000	1.1
+++ libexec/ld.so/aarch64/ld.script	1 Sep 2022 03:09:14 -0000
@@ -2,6 +2,7 @@ PHDRS
 {
 	rodata	PT_LOAD FILEHDR PHDRS FLAGS (4);
 	text	PT_LOAD;
+	btext	PT_LOAD FLAGS (0x08000005);
 	data	PT_LOAD;
 	random	PT_OPENBSD_RANDOMIZE;
 	relro	PT_GNU_RELRO;
@@ -28,7 +29,7 @@ SECTIONS
 	boot_text_start = .;
 	*(.boot.text)
 	boot_text_end = .;
-    } :text
+    } :btext
 
     /* RELRO DATA */
     . = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
@@ -61,9 +62,12 @@ SECTIONS
 
     /* DATA */
     . = ALIGN(0x1000);
+    __data_start = .;
     .data	: { *(.data .data.*) } :data
+    . = ALIGN(0x1000);
     .bss	: { *(.dynbss) *(.bss .bss.*) *(COMMON) } :data
     . = DATA_SEGMENT_END (.);
+    _end = .;
 
     /DISCARD/	: { *(.note.GNU-stack) }
 }
Index: libexec/ld.so/amd64/ld.script
===================================================================
RCS file: /cvs/src/libexec/ld.so/amd64/ld.script,v
retrieving revision 1.1
diff -u -p -u -r1.1 ld.script
--- libexec/ld.so/amd64/ld.script	10 May 2019 13:29:21 -0000	1.1
+++ libexec/ld.so/amd64/ld.script	1 Sep 2022 03:07:38 -0000
@@ -2,6 +2,7 @@ PHDRS
 {
 	rodata	PT_LOAD FILEHDR PHDRS FLAGS (4);
 	text	PT_LOAD;
+	btext	PT_LOAD FLAGS (0x08000005);
 	data	PT_LOAD;
 	random	PT_OPENBSD_RANDOMIZE;
 	relro	PT_GNU_RELRO;
@@ -26,7 +27,7 @@ SECTIONS
 	boot_text_start = .;
 	*(.boot.text)
 	boot_text_end = .;
-    } :text =0xcccccccc
+    } :btext =0xcccccccc
     . = ALIGN(0x1000);
     .text	: { *(.text .text.*) } :text =0xcccccccc
 
@@ -61,9 +62,12 @@ SECTIONS
 
     /* DATA */
     . = ALIGN(0x1000);
+    __data_start = .;
     .data	: { *(.data .data.*) } :data
+    . = ALIGN(0x1000);
     .bss	: { *(.dynbss) *(.bss .bss.*) *(COMMON) } :data
     . = DATA_SEGMENT_END (.);
+    _end = .;
 
     /DISCARD/	: { *(.note.GNU-stack) }
 }
Index: sys/kern/exec_elf.c
===================================================================
RCS file: /cvs/src/sys/kern/exec_elf.c,v
retrieving revision 1.168
diff -u -p -u -r1.168 exec_elf.c
--- sys/kern/exec_elf.c	29 Aug 2022 16:53:46 -0000	1.168
+++ sys/kern/exec_elf.c	31 Aug 2022 14:06:23 -0000
@@ -189,11 +189,17 @@ elf_load_psection(struct exec_vmcmd_set 
 	 * initially.  The dynamic linker will make these read-only
 	 * and add back X permission after relocation processing.
 	 * Static executables with W|X segments will probably crash.
+	 * Apply immutability to as many segments as possible; sadly
+	 * immutability must be applied to some writeable segments
+	 * by crt0 and ld.so after making adjustments.
 	 */
 	*prot |= (ph->p_flags & PF_R) ? PROT_READ : 0;
 	*prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0;
-	if ((ph->p_flags & PF_W) == 0)
+	if ((ph->p_flags & PF_W) == 0) {
 		*prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0;
+		if ((ph->p_flags & PF_MUTABLE) == 0)
+			flags |= VMCMD_IMMUTABLE;
+	}
 
 	msize = ph->p_memsz + diff;
 	offset = ph->p_offset - bdiff;
Index: sys/kern/exec_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/exec_subr.c,v
retrieving revision 1.57
diff -u -p -u -r1.57 exec_subr.c
--- sys/kern/exec_subr.c	29 Nov 2019 06:34:45 -0000	1.57
+++ sys/kern/exec_subr.c	30 Aug 2022 07:33:47 -0000
@@ -211,6 +211,10 @@ vmcmd_map_pagedvn(struct proc *p, struct
 		 * error: detach from object
 		 */
 		uobj->pgops->pgo_detach(uobj);
+	} else {
+		if (cmd->ev_flags & VMCMD_IMMUTABLE)
+			uvm_map_immutable(&p->p_vmspace->vm_map, cmd->ev_addr,
+			    cmd->ev_addr + cmd->ev_len);
 	}
 
 	return (error);
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.231
diff -u -p -u -r1.231 kern_exec.c
--- sys/kern/kern_exec.c	14 Aug 2022 01:58:27 -0000	1.231
+++ sys/kern/kern_exec.c	24 Aug 2022 01:28:45 -0000
@@ -863,6 +863,8 @@ exec_sigcode_map(struct process *pr)
 		uao_detach(sigobject);
 		return (ENOMEM);
 	}
+	uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_sigcode,
+	    pr->ps_sigcode + round_page(sz));
 
 	/* Calculate PC at point of sigreturn entry */
 	pr->ps_sigcoderet = pr->ps_sigcode + (sigcoderet - sigcode);
@@ -911,6 +913,8 @@ exec_timekeep_map(struct process *pr)
 		uao_detach(timekeep_object);
 		return (ENOMEM);
 	}
+	uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_timekeep,
+	    pr->ps_timekeep + timekeep_sz);
 
 	return (0);
 }
Index: sys/kern/kern_pledge.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.294
diff -u -p -u -r1.294 kern_pledge.c
--- sys/kern/kern_pledge.c	14 Aug 2022 01:58:27 -0000	1.294
+++ sys/kern/kern_pledge.c	30 Aug 2022 10:23:02 -0000
@@ -150,6 +150,7 @@ const uint64_t pledge_syscalls[SYS_MAXSY
 	[SYS_minherit] = PLEDGE_STDIO,
 	[SYS_mmap] = PLEDGE_STDIO,
 	[SYS_mprotect] = PLEDGE_STDIO,
+	[SYS_mimmutable] = PLEDGE_STDIO,
 	[SYS_mquery] = PLEDGE_STDIO,
 	[SYS_munmap] = PLEDGE_STDIO,
 	[SYS_msync] = PLEDGE_STDIO,
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.229
diff -u -p -u -r1.229 syscalls.master
--- sys/kern/syscalls.master	1 Aug 2022 14:56:59 -0000	1.229
+++ sys/kern/syscalls.master	24 Aug 2022 00:32:40 -0000
@@ -304,7 +304,7 @@
 156	OBSOL		ogetdirentries
 157	OBSOL		statfs25
 158	OBSOL		fstatfs25
-159	UNIMPL
+159	STD		{ int sys_mimmutable(void *addr, size_t len); }
 160	UNIMPL
 161	STD		{ int sys_getfh(const char *fname, fhandle_t *fhp); }
 162	OBSOL		ogetdomainname
Index: sys/sys/exec.h
===================================================================
RCS file: /cvs/src/sys/sys/exec.h,v
retrieving revision 1.47
diff -u -p -u -r1.47 exec.h
--- sys/sys/exec.h	7 Feb 2022 19:30:48 -0000	1.47
+++ sys/sys/exec.h	24 Aug 2022 17:07:32 -0000
@@ -93,6 +93,7 @@ struct exec_vmcmd {
 #define VMCMD_BASE      0x0002  /* marks a base entry */
 #define VMCMD_STACK     0x0004  /* create with UVM_FLAG_STACK */
 #define VMCMD_SYSCALL   0x0008  /* create with UVM_FLAG_SYSCALL */
+#define VMCMD_IMMUTABLE	0x0010  /* make immutable */
 };
 
 #define	EXEC_DEFAULT_VMCMD_SETSIZE	8	/* # of cmds in set to start */
Index: sys/sys/exec_elf.h
===================================================================
RCS file: /cvs/src/sys/sys/exec_elf.h,v
retrieving revision 1.94
diff -u -p -u -r1.94 exec_elf.h
--- sys/sys/exec_elf.h	25 Dec 2021 01:25:51 -0000	1.94
+++ sys/sys/exec_elf.h	30 Aug 2022 05:31:18 -0000
@@ -484,6 +484,7 @@ typedef struct {
 #define PF_X		0x1		/* Executable */
 #define PF_W		0x2		/* Writable */
 #define PF_R		0x4		/* Readable */
+#define PF_MUTABLE	0x08000000	/* Mutable */
 #define PF_MASKPROC	0xf0000000	/* reserved bits for processor */
 					/*  specific segment flags */
 
Index: sys/sys/mman.h
===================================================================
RCS file: /cvs/src/sys/sys/mman.h,v
retrieving revision 1.34
diff -u -p -u -r1.34 mman.h
--- sys/sys/mman.h	1 Mar 2019 01:46:18 -0000	1.34
+++ sys/sys/mman.h	31 Aug 2022 05:11:09 -0000
@@ -154,6 +154,7 @@ int	munlockall(void);
 #if __BSD_VISIBLE
 int	madvise(void *, size_t, int);
 int	minherit(void *, size_t, int);
+int	mimmutable(void *, size_t);
 void *	mquery(void *, size_t, int, int, int, off_t);
 #endif
 int	posix_madvise(void *, size_t, int);
Index: sys/uvm/uvm.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm.h,v
retrieving revision 1.69
diff -u -p -u -r1.69 uvm.h
--- sys/uvm/uvm.h	4 May 2022 14:58:26 -0000	1.69
+++ sys/uvm/uvm.h	24 Aug 2022 00:58:32 -0000
@@ -81,8 +81,6 @@ struct uvm {
 
 /*
  * vm_map_entry etype bits:
- *
- * keep in sync with KVM_ET_*
  */
 #define UVM_ET_OBJ		0x0001	/* it is a uvm_object */
 #define UVM_ET_SUBMAP		0x0002	/* it is a vm_map submap */
@@ -94,6 +92,7 @@ struct uvm {
 #define UVM_ET_WC		0x0080	/* write combining */
 #define UVM_ET_CONCEAL		0x0100	/* omit from dumps */
 #define UVM_ET_SYSCALL		0x0200	/* syscall text segment */
+#define UVM_ET_IMMUTABLE	0x0400	/* entry may not be changed */
 #define UVM_ET_FREEMAPPED	0x8000	/* map entry is on free list (DEBUG) */
 
 #define UVM_ET_ISOBJ(E)		(((E)->etype & UVM_ET_OBJ) != 0)
Index: sys/uvm/uvm_io.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_io.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 uvm_io.c
--- sys/uvm/uvm_io.c	12 Mar 2022 08:11:07 -0000	1.29
+++ sys/uvm/uvm_io.c	24 Aug 2022 00:32:40 -0000
@@ -127,7 +127,7 @@ uvm_io(vm_map_t map, struct uio *uio, in
 		vm_map_lock(kernel_map);
 		TAILQ_INIT(&dead_entries);
 		uvm_unmap_remove(kernel_map, kva, kva+chunksz,
-		    &dead_entries, FALSE, TRUE);
+		    &dead_entries, FALSE, TRUE, FALSE);
 		vm_map_unlock(kernel_map);
 		uvm_unmap_detach(&dead_entries, AMAP_REFALL);
 
Index: sys/uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.294
diff -u -p -u -r1.294 uvm_map.c
--- sys/uvm/uvm_map.c	15 Aug 2022 15:53:45 -0000	1.294
+++ sys/uvm/uvm_map.c	30 Aug 2022 19:11:11 -0000
@@ -797,7 +797,13 @@ uvm_mapanon(struct vm_map *map, vaddr_t 
 				error = EINVAL;
 				goto unlock;
 			}
-			uvm_unmap_remove(map, *addr, *addr + sz, &dead, FALSE, TRUE);
+			if (uvm_unmap_remove(map, *addr, *addr + sz, &dead,
+			    FALSE, TRUE, TRUE) != 0) {
+				printf("uvm_mapanon: %s\n", curproc->p_p->ps_comm);
+				// XXX immutable must fail
+				error = ENOMEM;
+				goto unlock;
+			}
 		}
 		if (!uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) {
 			error = ENOMEM;
@@ -1038,8 +1044,15 @@ uvm_map(struct vm_map *map, vaddr_t *add
 		}
 
 		/* Check that the space is available. */
-		if (flags & UVM_FLAG_UNMAP)
-			uvm_unmap_remove(map, *addr, *addr + sz, &dead, FALSE, TRUE);
+		if (flags & UVM_FLAG_UNMAP) {
+			if (uvm_unmap_remove(map, *addr, *addr + sz, &dead,
+			    FALSE, TRUE, TRUE) != 0) {
+				printf("uvm_map: %s\n", curproc->p_p->ps_comm);
+				// XXX immutable must fail
+				error = ENOMEM;
+				goto unlock;
+			}
+		}
 		if (!uvm_map_isavail(map, NULL, &first, &last, *addr, sz)) {
 			error = ENOMEM;
 			goto unlock;
@@ -1817,7 +1830,7 @@ uvm_unmap(struct vm_map *map, vaddr_t st
 	    (end & (vaddr_t)PAGE_MASK) == 0);
 	TAILQ_INIT(&dead);
 	vm_map_lock(map);
-	uvm_unmap_remove(map, start, end, &dead, FALSE, TRUE);
+	uvm_unmap_remove(map, start, end, &dead, FALSE, TRUE, FALSE);
 	vm_map_unlock(map);
 
 	if (map->flags & VM_MAP_INTRSAFE)
@@ -1959,17 +1972,17 @@ uvm_unmap_kill_entry(struct vm_map *map,
  * If markfree, entry will be properly marked free, otherwise, no replacement
  * entry will be put in the tree (corrupting the tree).
  */
-void
+int
 uvm_unmap_remove(struct vm_map *map, vaddr_t start, vaddr_t end,
     struct uvm_map_deadq *dead, boolean_t remove_holes,
-    boolean_t markfree)
+    boolean_t markfree, boolean_t checkimmutable)
 {
 	struct vm_map_entry *prev_hint, *next, *entry;
 
 	start = MAX(start, map->min_offset);
 	end = MIN(end, map->max_offset);
 	if (start >= end)
-		return;
+		return 0;
 
 	if ((map->flags & VM_MAP_INTRSAFE) == 0)
 		splassert(IPL_NONE);
@@ -1984,6 +1997,23 @@ uvm_unmap_remove(struct vm_map *map, vad
 	else
 		UVM_MAP_CLIP_START(map, entry, start);
 
+	if (checkimmutable) {
+		struct vm_map_entry *entry1 = entry;
+
+		/* Refuse to unmap if any entries are immutable */
+		for (; entry1 != NULL && entry1->start < end; entry1 = next) {
+			KDASSERT(entry1->start >= start);
+			if (entry1->end > end || !markfree)
+				UVM_MAP_CLIP_END(map, entry1, end);
+			KDASSERT(entry1->start >= start && entry1->end <= end);
+			next = RBT_NEXT(uvm_map_addr, entry1);
+			if (entry1->etype & UVM_ET_IMMUTABLE) {
+				printf("uvm_unmap: %s\n", curproc->p_p->ps_comm);
+				return EPERM;
+			}
+		}
+	}
+
 	/*
 	 * Iterate entries until we reach end address.
 	 * prev_hint hints where the freed space can be appended to.
@@ -2043,6 +2073,7 @@ uvm_unmap_remove(struct vm_map *map, vad
 			KDASSERT(uvm_map_entrybyaddr(&map->addr, a) == NULL);
 	}
 #endif
+	return 0;
 }
 
 /*
@@ -3098,6 +3129,11 @@ uvm_map_protect(struct vm_map *map, vadd
 		if (iter->start == iter->end || UVM_ET_ISHOLE(iter))
 			continue;
 
+		if (iter->etype & UVM_ET_IMMUTABLE) {
+			printf("uvm_map_mprotect: %s\n", curproc->p_p->ps_comm);
+			error = EPERM;
+			goto out;
+		}
 		old_prot = iter->protection;
 		if (old_prot == PROT_NONE && new_prot != old_prot) {
 			dused += uvmspace_dused(
@@ -3356,7 +3392,7 @@ uvmspace_exec(struct proc *p, vaddr_t st
 		 * (as in, not replace them with free-memory entries).
 		 */
 		uvm_unmap_remove(map, map->min_offset, map->max_offset,
-		    &dead_entries, TRUE, FALSE);
+		    &dead_entries, TRUE, FALSE, FALSE);
 
 		KDASSERT(RBT_EMPTY(uvm_map_addr, &map->addr));
 
@@ -3529,7 +3565,7 @@ uvm_share(struct vm_map *dstmap, vaddr_t
 	}
 
 	ret = EINVAL;
-	uvm_unmap_remove(dstmap, dstaddr, unmap_end, &dead, FALSE, TRUE);
+	uvm_unmap_remove(dstmap, dstaddr, unmap_end, &dead, FALSE, TRUE, FALSE);
 
 exit_unlock:
 	vm_map_unlock_read(srcmap);
@@ -4088,7 +4124,7 @@ uvm_map_deallocate(vm_map_t map)
 	TAILQ_INIT(&dead);
 	uvm_tree_sanity(map, __FILE__, __LINE__);
 	uvm_unmap_remove(map, map->min_offset, map->max_offset, &dead,
-	    TRUE, FALSE);
+	    TRUE, FALSE, FALSE);
 	pmap_destroy(map->pmap);
 	KASSERT(RBT_EMPTY(uvm_map_addr, &map->addr));
 	free(map, M_VMMAP, sizeof *map);
@@ -4183,6 +4219,42 @@ uvm_map_syscall(struct vm_map *map, vadd
 	return (0);
 }
 
+/* 
+ * uvm_map_immutable: block mapping/mprotect for range of addrs in map.
+ *
+ * => map must be unlocked
+ */
+int
+uvm_map_immutable(struct vm_map *map, vaddr_t start, vaddr_t end)
+{
+	struct vm_map_entry *entry;
+
+	if (start > end)
+		return EINVAL;
+	start = MAX(start, map->min_offset);
+	end = MIN(end, map->max_offset);
+	if (start >= end)
+		return 0;
+
+	vm_map_lock(map);
+
+	entry = uvm_map_entrybyaddr(&map->addr, start);
+	if (entry->end > start)
+		UVM_MAP_CLIP_START(map, entry, start);
+	else
+		entry = RBT_NEXT(uvm_map_addr, entry);
+
+	while (entry != NULL && entry->start < end) {
+		UVM_MAP_CLIP_END(map, entry, end);
+		entry->etype |= UVM_ET_IMMUTABLE;
+		entry = RBT_NEXT(uvm_map_addr, entry);
+	}
+
+	map->wserial++;
+	vm_map_unlock(map);
+	return (0);
+}
+
 /*
  * uvm_map_advice: set advice code for range of addrs in map.
  *
@@ -4367,7 +4439,7 @@ uvm_map_extract(struct vm_map *srcmap, v
 fail2_unmap:
 	if (error) {
 		uvm_unmap_remove(kernel_map, dstaddr, dstaddr + len, &dead,
-		    FALSE, TRUE);
+		    FALSE, TRUE, FALSE);
 	}
 
 	/* Release maps, release dead entries. */
Index: sys/uvm/uvm_map.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.h,v
retrieving revision 1.75
diff -u -p -u -r1.75 uvm_map.h
--- sys/uvm/uvm_map.h	12 Mar 2022 08:11:07 -0000	1.75
+++ sys/uvm/uvm_map.h	24 Aug 2022 00:32:40 -0000
@@ -350,6 +350,7 @@ struct vm_map *	uvm_map_create(pmap_t, v
 vaddr_t		uvm_map_pie(vaddr_t);
 vaddr_t		uvm_map_hint(struct vmspace *, vm_prot_t, vaddr_t, vaddr_t);
 int		uvm_map_syscall(struct vm_map *, vaddr_t, vaddr_t);
+int		uvm_map_immutable(struct vm_map *, vaddr_t, vaddr_t);
 int		uvm_map_inherit(struct vm_map *, vaddr_t, vaddr_t, vm_inherit_t);
 int		uvm_map_advice(struct vm_map *, vaddr_t, vaddr_t, int);
 void		uvm_map_init(void);
@@ -365,8 +366,8 @@ int		uvm_map_submap(struct vm_map *, vad
 		    struct vm_map *);
 void		uvm_unmap(struct vm_map *, vaddr_t, vaddr_t);
 void		uvm_unmap_detach(struct uvm_map_deadq *, int);
-void		uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t,
-		    struct uvm_map_deadq *, boolean_t, boolean_t);
+int		uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t,
+		    struct uvm_map_deadq *, boolean_t, boolean_t, boolean_t);
 void		uvm_map_set_uaddr(struct vm_map*, struct uvm_addr_state**,
 		    struct uvm_addr_state*);
 int		uvm_map_mquery(struct vm_map*, vaddr_t*, vsize_t, voff_t, int);
Index: sys/uvm/uvm_mmap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_mmap.c,v
retrieving revision 1.172
diff -u -p -u -r1.172 uvm_mmap.c
--- sys/uvm/uvm_mmap.c	1 Aug 2022 14:56:59 -0000	1.172
+++ sys/uvm/uvm_mmap.c	24 Aug 2022 00:32:40 -0000
@@ -569,7 +569,11 @@ sys_munmap(struct proc *p, void *v, regi
 	}
 
 	TAILQ_INIT(&dead_entries);
-	uvm_unmap_remove(map, addr, addr + size, &dead_entries, FALSE, TRUE);
+	if (uvm_unmap_remove(map, addr, addr + size, &dead_entries,
+	    FALSE, TRUE, TRUE) != 0) {
+		vm_map_unlock(map);
+		return EPERM;
+	}
 	vm_map_unlock(map);	/* and unlock */
 
 	uvm_unmap_detach(&dead_entries, 0);
@@ -649,6 +653,32 @@ sys_msyscall(struct proc *p, void *v, re
 }
 
 /*
+ * sys_mimmutable: the mimmutable system call
+ */
+int
+sys_mimmutable(struct proc *p, void *v, register_t *retval)
+{
+	struct sys_mimmutable_args /* {
+		immutablearg(void *) addr;
+		immutablearg(size_t) len;
+	} */ *uap = v;
+	vaddr_t addr;
+	vsize_t size, pageoff;
+
+	addr = (vaddr_t)SCARG(uap, addr);
+	size = (vsize_t)SCARG(uap, len);
+
+	/*
+	 * align the address to a page boundary, and adjust the size accordingly
+	 */
+	ALIGN_ADDR(addr, size, pageoff);
+	if (addr > SIZE_MAX - size)
+		return EINVAL;		/* disallow wrap-around. */
+
+	return uvm_map_immutable(&p->p_vmspace->vm_map, addr, addr+size);
+}
+
+/*
  * sys_minherit: the minherit system call
  */
 int
@@ -1228,7 +1258,8 @@ redo:
 			if (kva != 0) {
 				vm_map_lock(kernel_map);
 				uvm_unmap_remove(kernel_map, kva,
-				    kva+PAGE_SIZE, &dead_entries, FALSE, TRUE);
+				    kva+PAGE_SIZE, &dead_entries,
+				    FALSE, TRUE, FALSE);	/* XXX */
 				vm_map_unlock(kernel_map);
 				kva = 0;
 			}
@@ -1255,7 +1286,7 @@ redo:
 	if (kva != 0) {
 		vm_map_lock(kernel_map);
 		uvm_unmap_remove(kernel_map, kva, kva+PAGE_SIZE,
-		    &dead_entries, FALSE, TRUE);
+		    &dead_entries, FALSE, TRUE, FALSE);		/* XXX */
 		vm_map_unlock(kernel_map);
 	}
 	uvm_unmap_detach(&dead_entries, AMAP_REFALL);
Index: usr.sbin/procmap/procmap.c
===================================================================
RCS file: /cvs/src/usr.sbin/procmap/procmap.c,v
retrieving revision 1.69
diff -u -p -u -r1.69 procmap.c
--- usr.sbin/procmap/procmap.c	22 Feb 2022 17:35:01 -0000	1.69
+++ usr.sbin/procmap/procmap.c	24 Aug 2022 02:09:17 -0000
@@ -497,7 +497,7 @@ process_map(kvm_t *kd, pid_t pid, struct
 		    (int)sizeof(int) * 2 - 1,  "Size ");
 #endif
 	if (print_all)
-		printf("%-*s %-*s %*s %-*s rwxSepc  RWX  I/W/A Dev  %*s - File\n",
+		printf("%-*s %-*s %*s %-*s rwxSeIpc  RWX  I/W/A Dev  %*s - File\n",
 		    (int)sizeof(long) * 2, "Start",
 		    (int)sizeof(long) * 2, "End",
 		    (int)sizeof(int)  * 2, "Size ",
@@ -719,7 +719,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 	name = findname(kd, vmspace, vme, vp, vfs, uvm_obj);
 
 	if (print_map) {
-		printf("0x%-*lx 0x%-*lx %c%c%c%c%c %c%c%c %s %s %d %d %d",
+		printf("0x%-*lx 0x%-*lx %c%c%c%c%c%c %c%c%c %s %s %d %d %d",
 		    (int)sizeof(long) * 2 + 0, vme->start,
 		    (int)sizeof(long) * 2 + 0, vme->end,
 		    (vme->protection & PROT_READ) ? 'r' : '-',
@@ -727,6 +727,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 		    (vme->protection & PROT_EXEC) ? 'x' : '-',
 		    (vme->etype & UVM_ET_STACK) ? 'S' : '-',
 		    (vme->etype & UVM_ET_SYSCALL) ? 'e' : '-',
+		    (vme->etype & UVM_ET_IMMUTABLE) ? 'I' : '-',
 		    (vme->max_protection & PROT_READ) ? 'r' : '-',
 		    (vme->max_protection & PROT_WRITE) ? 'w' : '-',
 		    (vme->max_protection & PROT_EXEC) ? 'x' : '-',
@@ -746,7 +747,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 	}
 
 	if (print_maps)
-		printf("0x%-*lx 0x%-*lx %c%c%c%c%c%c %0*lx %02x:%02x %llu     %s\n",
+		printf("0x%-*lx 0x%-*lx %c%c%c%c%c%c%c %0*lx %02x:%02x %llu     %s\n",
 		    (int)sizeof(void *) * 2, vme->start,
 		    (int)sizeof(void *) * 2, vme->end,
 		    (vme->protection & PROT_READ) ? 'r' : '-',
@@ -754,6 +755,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 		    (vme->protection & PROT_EXEC) ? 'x' : '-',
 		    (vme->etype & UVM_ET_STACK) ? 'S' : '-',
 		    (vme->etype & UVM_ET_SYSCALL) ? 'e' : '-',
+		    (vme->etype & UVM_ET_IMMUTABLE) ? 'I' : '-',
 		    (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's',
 		    (int)sizeof(void *) * 2,
 		    (unsigned long)vme->offset,
@@ -767,13 +769,14 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 		    vme->object.uvm_obj, (unsigned long)vme->offset,
 		    vme->aref.ar_amap, vme->aref.ar_pageoff);
 		printf("\tsubmap=%c, cow=%c, nc=%c, stack=%c, "
-		    "syscall=%c, prot(max)=%d/%d, inh=%d, "
+		    "syscall=%c, immutable=%c, prot(max)=%d/%d, inh=%d, "
 		    "wc=%d, adv=%d\n",
 		    (vme->etype & UVM_ET_SUBMAP) ? 'T' : 'F',
 		    (vme->etype & UVM_ET_COPYONWRITE) ? 'T' : 'F',
 		    (vme->etype & UVM_ET_NEEDSCOPY) ? 'T' : 'F',
 		    (vme->etype & UVM_ET_STACK) ? 'T' : 'F',
 		    (vme->etype & UVM_ET_SYSCALL) ? 'T' : 'F',
+		    (vme->etype & UVM_ET_IMMUTABLE) ? 'T' : 'F',
 		    vme->protection, vme->max_protection,
 		    vme->inheritance, vme->wired_count, vme->advice);
 		if (inode && verbose)
@@ -813,7 +816,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 		}
 
 		sz = (size_t)((vme->end - vme->start) / 1024);
-		printf("%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c%c%c (%c%c%c) %d/%d/%d %02u:%02u %7llu - \
%s", +		printf("%0*lx-%0*lx %7luk %0*lx %c%c%c%c%c%c%c%c (%c%c%c) %d/%d/%d %02u:%02u \
%7llu - %s",  (int)sizeof(void *) * 2, vme->start, (int)sizeof(void *) * 2,
 		    vme->end - (vme->start != vme->end ? 1 : 0), (unsigned long)sz,
 		    (int)sizeof(void *) * 2, (unsigned long)vme->offset,
@@ -822,6 +825,7 @@ dump_vm_map_entry(kvm_t *kd, struct kbit
 		    (vme->protection & PROT_EXEC) ? 'x' : '-',
 		    (vme->etype & UVM_ET_STACK) ? 'S' : '-',
 		    (vme->etype & UVM_ET_SYSCALL) ? 'e' : '-',
+		    (vme->etype & UVM_ET_IMMUTABLE) ? 'I' : '-',
 		    (vme->etype & UVM_ET_COPYONWRITE) ? 'p' : 's',
 		    (vme->etype & UVM_ET_NEEDSCOPY) ? '+' : '-',
 		    (vme->max_protection & PROT_READ) ? 'r' : '-',


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic