Theo de Raadt <[email protected]> wrote:
> 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.
I have mostly succeeded at changing this to a better model. The
previous version had a real difficult time finding the specific objects
which cannot become immutable, so I found a way to describe them to the
kernel.
The ELF program headers now contain a new PHDR for section
".openbsd.mutable", aka OPENBSD_MUTABLE. This is placed on the malloc
self-protected bookkeeping page.
When the main binary & ld.so are loaded the kernel can make all LOAD
regions immutable, and then in a later pass the kernel is permitted to
undo the immutable on the OPENBSD_MUTABLE and GNU_RELRO regions. Only
the kernel can undo immutability, in these specific cases.
When crt0 finishes RELRO adjustment and mprotects PROT_READ, it also
marks the region immutable. ld.so does the same for it's RELRO.
The libc malloc self-protection scheme can mprotect RW and R back and
forth when it wants, and it will never make this region immutable.
When ld.so loads a library, it creates a queue of immutable and mutable
work actions to do after the library is done. ld.so cannot reverse an
immutable, so it must clip the mutable regions out of the immutables.
This clip piece of the diff is embarrassingly poor. It is very forgiving,
which is why I can run multiuser. I do know that the system libraries are
clean, and anyways the big problems were with the malloc, relro, main
programs, and ld.so, not the other libraries....
This version is harder to cross compile through, but I wanted to show in
case someone is interested. There are numberous gaps (binutils lacks
support, other architectures, but the worst part is the immutuble
clipping code.
Index: gnu/llvm/lld/ELF/ScriptParser.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/lld/ELF/ScriptParser.cpp,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 ScriptParser.cpp
--- gnu/llvm/lld/ELF/ScriptParser.cpp 17 Dec 2021 12:25:02 -0000 1.1.1.4
+++ gnu/llvm/lld/ELF/ScriptParser.cpp 2 Sep 2022 15:23:20 -0000
@@ -1478,6 +1478,7 @@
.Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME)
.Case("PT_GNU_STACK", PT_GNU_STACK)
.Case("PT_GNU_RELRO", PT_GNU_RELRO)
+ .Case("PT_OPENBSD_MUTABLE", PT_OPENBSD_MUTABLE)
.Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE)
.Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED)
.Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
Index: gnu/llvm/lld/ELF/Writer.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/lld/ELF/Writer.cpp,v
retrieving revision 1.3
diff -u -r1.3 Writer.cpp
--- gnu/llvm/lld/ELF/Writer.cpp 17 Dec 2021 14:46:47 -0000 1.3
+++ gnu/llvm/lld/ELF/Writer.cpp 2 Sep 2022 21:53:22 -0000
@@ -146,7 +146,7 @@
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.",
".tbss.",
".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab.",
- ".openbsd.randomdata."})
+ ".openbsd.randomdata.", ".openbsd.mutable." })
if (isSectionPrefix(v, s->name))
return v.drop_back();
@@ -2469,6 +2469,12 @@
part.ehFrame->getParent() && part.ehFrameHdr->getParent())
addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags())
->add(part.ehFrameHdr->getParent());
+
+ // PT_OPENBSD_MUTABLE is an OpenBSD-specific feature. That makes
+ // the dynamic linker fill the segment with zero data, like bss, but
+ // it can be treated differently.
+ if (OutputSection *cmd = findSection(".openbsd.mutable", partNo))
+ addHdr(PT_OPENBSD_MUTABLE, cmd->getPhdrFlags())->add(cmd);
// PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
// the dynamic linker fill the segment with random data.
Index: gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h
===================================================================
RCS file: /cvs/src/gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 ELF.h
--- gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h 17 Dec 2021 12:23:22
-0000 1.1.1.3
+++ gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h 2 Sep 2022 12:12:47
-0000
@@ -1303,6 +1303,7 @@
PT_GNU_RELRO = 0x6474e552, // Read-only after relocation.
PT_GNU_PROPERTY = 0x6474e553, // .note.gnu.property notes sections.
+ PT_OPENBSD_MUTABLE = 0x65a3dbe5, // Like bss, but not immutable
PT_OPENBSD_RANDOMIZE = 0x65a3dbe6, // Fill with random data.
PT_OPENBSD_WXNEEDED = 0x65a3dbe7, // Program does W^X violations.
PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments.
Index: gnu/llvm/llvm/tools/llvm-objdump/ELFDump.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/llvm/tools/llvm-objdump/ELFDump.cpp,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 ELFDump.cpp
--- gnu/llvm/llvm/tools/llvm-objdump/ELFDump.cpp 17 Dec 2021 12:23:42
-0000 1.1.1.3
+++ gnu/llvm/llvm/tools/llvm-objdump/ELFDump.cpp 2 Sep 2022 15:24:09
-0000
@@ -246,6 +246,9 @@
case ELF::PT_OPENBSD_BOOTDATA:
outs() << " OPENBSD_BOOTDATA ";
break;
+ case ELF::PT_OPENBSD_MUTABLE:
+ outs() << " OPENBSD_MUTABLE ";
+ break;
case ELF::PT_OPENBSD_RANDOMIZE:
outs() << " OPENBSD_RANDOMIZE ";
break;
Index: gnu/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp
===================================================================
RCS file: /cvs/src/gnu/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 ELFDumper.cpp
--- gnu/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp 17 Dec 2021 12:23:42
-0000 1.1.1.3
+++ gnu/llvm/llvm/tools/llvm-readobj/ELFDumper.cpp 2 Sep 2022 15:17:26
-0000
@@ -1369,6 +1369,7 @@
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);
LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY);
+ LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);
LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);
Index: lib/csu/boot.h
===================================================================
RCS file: /cvs/src/lib/csu/boot.h,v
retrieving revision 1.33
diff -u -r1.33 boot.h
--- lib/csu/boot.h 12 Jan 2022 21:41:06 -0000 1.33
+++ lib/csu/boot.h 3 Sep 2022 14:04:00 -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 @@
*/
#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;
@@ -63,8 +63,10 @@
static size_t relro_size;
#define RCRT0_RELRO() \
do { \
- if (relro_addr != NULL && relro_size != 0) \
+ if (relro_addr != NULL && relro_size != 0) { \
mprotect(relro_addr, relro_size, PROT_READ); \
+ mimmutable(relro_addr, relro_size); \
+ } \
} while (0)
/*
Index: lib/csu/crt0.c
===================================================================
RCS file: /cvs/src/lib/csu/crt0.c,v
retrieving revision 1.17
diff -u -r1.17 crt0.c
--- lib/csu/crt0.c 12 Jan 2022 21:41:06 -0000 1.17
+++ lib/csu/crt0.c 3 Sep 2022 14:03:43 -0000
@@ -32,6 +32,7 @@
*/
#include <sys/syscall.h>
+#include <sys/mman.h>
#include <stdlib.h>
#include <limits.h>
Index: lib/libc/Symbols.list
===================================================================
RCS file: /cvs/src/lib/libc/Symbols.list,v
retrieving revision 1.75
diff -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_lstat
_thread_sys_madvise
_thread_sys_minherit
+_thread_sys_mimmutable
_thread_sys_mkdir
_thread_sys_mkdirat
_thread_sys_mkfifo
@@ -325,6 +326,7 @@
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 -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(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 -r1.274 malloc.c
--- lib/libc/stdlib/malloc.c 30 Jun 2022 17:15:48 -0000 1.274
+++ lib/libc/stdlib/malloc.c 3 Sep 2022 14:01:22 -0000
@@ -228,7 +228,8 @@
static union {
struct malloc_readonly mopts;
u_char _pad[MALLOC_PAGESIZE];
-} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)));
+} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)))
+ __attribute__((section(".openbsd.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 -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 @@
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 -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+= 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 -r1.87 library.c
--- libexec/ld.so/library.c 20 Aug 2022 14:11:31 -0000 1.87
+++ libexec/ld.so/library.c 3 Sep 2022 13:11:33 -0000
@@ -95,6 +95,102 @@
}
}
+void
+_dl_defer_immutable(elf_object_t *object, void *start, size_t len)
+{
+ struct mutate *m;
+ int i;
+
+ for (i = 0;
+ i < sizeof(object->immutable)/sizeof(object->immutable[0]);
+ i++) {
+ m = &object->immutable[i];
+ if (m->start == 0) {
+ // _dl_printf("imut %x %x\n", start, start + len);
+ m->start = (vaddr_t)start;
+ m->end = (vaddr_t)start + len;
+ break;
+ }
+ }
+}
+
+void
+_dl_defer_mutable(elf_object_t *object, void *start, size_t len)
+{
+ struct mutate *m;
+ int i;
+
+ for (i = 0;
+ i < sizeof(object->mutable)/sizeof(object->mutable[0]);
+ i++) {
+ m = &object->mutable[i];
+ if (m->start == 0) {
+ // _dl_printf(" mut %x %x\n", start, start + len);
+ m->start = (vaddr_t)start;
+ m->end = (vaddr_t)start + len;
+ break;
+ }
+ }
+}
+
+void
+_dl_apply_mutable(elf_object_t *object, Elf_Addr loff)
+{
+ struct mutate *m, *im;
+ int i, j;
+
+ /* remove mutables from the list */
+ for (i = 0;
+ i < sizeof(object->mutable)/sizeof(object->mutable[0]);
+ i++) {
+ m = &object->mutable[i];
+ if (m->start == 0)
+ break;
+
+ /* remove mutable from any immutables */
+ for (j = 0;
+ j < sizeof(object->immutable)/sizeof(object->immutable[0]);
+ j++) {
+ im = &object->immutable[j];
+ if (im->start == 0)
+ break;
+ // _dl_printf("mut %x-%x, checking in mut %x-%x\n",
+ // (long)m->start, m->end, (long)im->start, im->end);
+ if (m->start < im->start && m->end > im->start) {
+ im->start = m->end;
+ // _dl_printf("start %x-%x\n", (long)im->start,
im->end);
+ }
+ if (m->start >= im->start && m->start < im->end &&
+ m->end > im->end) {
+ im->start = m->start;
+ // _dl_printf("end %x-%x\n", (long)im->start,
im->end);
+ }
+ if (m->start >= im->start && m->end < im->end) {
+ im->start = m->start;
+ im->end = m->end; /* fail on tail */
+ // _dl_printf("mid %x-%x\n", (long)im->start,
im->end);
+ }
+ if (m->start <= im->start && m->end >= im->end) {
+ im->start = 0;
+ im->end = 0;
+ // _dl_printf("whole %x-%x\n", (long)im->start,
im->end);
+ }
+
+ }
+ }
+
+ /* install immutability */
+ for (j = 0;
+ j < sizeof(object->immutable)/sizeof(object->immutable[0]);
+ j++) {
+ im = &object->immutable[j];
+ if (im->start == 0 && im->end == 0)
+ break;
+ // _dl_printf("ldso %x %x\n", im->start, im->end);
+ _dl_mimmutable((void *)im->start + loff, im->end - im->start);
+ }
+}
+
elf_object_t *
_dl_tryload_shlib(const char *libname, int type, int flags)
{
@@ -328,9 +424,35 @@
_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 = (char
*)(TRUNC_PG(phdp->p_vaddr));
+ Elf_Addr size = phdp->p_filesz;
+
+ if (size == 0)
+ continue;
+ switch (phdp->p_type) {
+ case PT_LOAD:
+ _dl_defer_immutable(object,
+ start, ROUND_PG(size));
+ break;
+ case PT_GNU_RELRO:
+ case PT_OPENBSD_MUTABLE:
+ _dl_defer_mutable(object,
+ start, ROUND_PG(size));
+ break;
+ }
+ }
+ }
} else {
_dl_munmap((void *)libaddr, maxva - minva);
_dl_load_list_free(load_list);
}
+
+ _dl_apply_mutable(object, loff);
+
return(object);
}
Index: libexec/ld.so/loader.c
===================================================================
RCS file: /cvs/src/libexec/ld.so/loader.c,v
retrieving revision 1.195
diff -u -r1.195 loader.c
--- libexec/ld.so/loader.c 8 Jan 2022 06:49:41 -0000 1.195
+++ libexec/ld.so/loader.c 3 Sep 2022 14:06:30 -0000
@@ -218,11 +218,15 @@
#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_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(
@@ -432,11 +436,12 @@
case PT_GNU_RELRO:
_dl_mprotect((void *)(phdp->p_vaddr + loff),
phdp->p_memsz, PROT_READ);
+ _dl_mimmutable((void *)(phdp->p_vaddr + loff),
+ phdp->p_memsz);
break;
}
}
}
-
#define PFLAGS(X) ((((X) & PF_R) ? PROT_READ : 0) | \
(((X) & PF_W) ? PROT_WRITE : 0) | \
Index: libexec/ld.so/resolve.h
===================================================================
RCS file: /cvs/src/libexec/ld.so/resolve.h,v
retrieving revision 1.101
diff -u -r1.101 resolve.h
--- libexec/ld.so/resolve.h 20 Aug 2022 14:11:31 -0000 1.101
+++ libexec/ld.so/resolve.h 3 Sep 2022 12:31:34 -0000
@@ -77,6 +77,11 @@
};
void object_vec_grow(struct object_vector *_vec, int _more);
+struct mutate {
+ vaddr_t start;
+ vaddr_t end;
+};
+
/*
* Structure describing a loaded object.
* The head of this struct must be compatible
@@ -231,6 +236,9 @@
/* nonzero if trace enabled for this object */
int traced;
+
+ struct mutate immutable[10];
+ struct mutate mutable[10];
};
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 -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 @@
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/syscall.h
===================================================================
RCS file: /cvs/src/libexec/ld.so/syscall.h,v
retrieving revision 1.2
diff -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 @@
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 -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 @@
{
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 @@
boot_text_start = .;
*(.boot.text)
boot_text_end = .;
- } :text
+ } :btext
/* RELRO DATA */
. = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
@@ -61,9 +62,12 @@
/* 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 -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 @@
{
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 @@
boot_text_start = .;
*(.boot.text)
boot_text_end = .;
- } :text =0xcccccccc
+ } :btext =0xcccccccc
. = ALIGN(0x1000);
.text : { *(.text .text.*) } :text =0xcccccccc
@@ -61,9 +62,12 @@
/* 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 -r1.168 exec_elf.c
--- sys/kern/exec_elf.c 29 Aug 2022 16:53:46 -0000 1.168
+++ sys/kern/exec_elf.c 3 Sep 2022 07:25:23 -0000
@@ -189,11 +189,16 @@
* 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)
*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;
@@ -432,6 +437,12 @@
ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0);
break;
+ case PT_GNU_RELRO:
+ case PT_OPENBSD_MUTABLE:
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable,
+ ph[i].p_memsz, ph[i].p_vaddr + pos, NULLVP, 0, 0);
+ break;
+
default:
break;
}
@@ -652,6 +663,12 @@
}
randomizequota -= ph[i].p_memsz;
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_randomize,
+ ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0,
0);
+ break;
+
+ case PT_GNU_RELRO:
+ case PT_OPENBSD_MUTABLE:
+ NEW_VMCMD(&epp->ep_vmcmds, vmcmd_mutable,
ph[i].p_memsz, ph[i].p_vaddr + exe_base, NULLVP, 0,
0);
break;
Index: sys/kern/exec_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/exec_subr.c,v
retrieving revision 1.57
diff -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 3 Sep 2022 13:51:09 -0000
@@ -211,6 +211,10 @@
* 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, 1, "pagedvm");
}
return (error);
@@ -281,6 +285,23 @@
UVM_MAPFLAG(cmd->ev_prot, PROT_MASK, MAP_INHERIT_COPY,
MADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_COPYONW |
(cmd->ev_flags & VMCMD_STACK ? UVM_FLAG_STACK : 0))));
+}
+
+/*
+ * vmcmd_mutable():
+ * handle vmcmd which changes an address space region.back to mutable
+ */
+
+int
+vmcmd_mutable(struct proc *p, struct exec_vmcmd *cmd)
+{
+ if (cmd->ev_len == 0)
+ return (0);
+
+ cmd->ev_addr = trunc_page(cmd->ev_addr);
+ uvm_map_immutable(&p->p_vmspace->vm_map, cmd->ev_addr,
+ cmd->ev_addr + round_page(cmd->ev_len), 0, "mutable");
+ return 0;
}
/*
Index: sys/kern/init_sysent.c
===================================================================
RCS file: /cvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.243
diff -u -r1.243 init_sysent.c
--- sys/kern/init_sysent.c 1 Aug 2022 14:57:19 -0000 1.243
+++ sys/kern/init_sysent.c 24 Aug 2022 00:32:47 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: init_sysent.c,v 1.243 2022/08/01 14:57:19 deraadt Exp $
*/
+/* $OpenBSD$ */
/*
* System call switch table.
@@ -355,8 +355,8 @@
sys_nosys }, /* 157 = obsolete statfs25 */
{ 0, 0, 0,
sys_nosys }, /* 158 = obsolete fstatfs25 */
- { 0, 0, 0,
- sys_nosys }, /* 159 = unimplemented */
+ { 2, s(struct sys_mimmutable_args), 0,
+ sys_mimmutable }, /* 159 = mimmutable */
{ 0, 0, 0,
sys_nosys }, /* 160 = unimplemented */
{ 2, s(struct sys_getfh_args), 0,
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.231
diff -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 3 Sep 2022 06:45:22 -0000
@@ -863,6 +863,8 @@
uao_detach(sigobject);
return (ENOMEM);
}
+ uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_sigcode,
+ pr->ps_sigcode + round_page(sz), 1, "sig");
/* Calculate PC at point of sigreturn entry */
pr->ps_sigcoderet = pr->ps_sigcode + (sigcoderet - sigcode);
@@ -911,6 +913,8 @@
uao_detach(timekeep_object);
return (ENOMEM);
}
+ uvm_map_immutable(&pr->ps_vmspace->vm_map, pr->ps_timekeep,
+ pr->ps_timekeep + timekeep_sz, 1, "time");
return (0);
}
Index: sys/kern/kern_pledge.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.294
diff -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 @@
[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.c
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.c,v
retrieving revision 1.241
diff -u -r1.241 syscalls.c
--- sys/kern/syscalls.c 1 Aug 2022 14:57:19 -0000 1.241
+++ sys/kern/syscalls.c 24 Aug 2022 00:32:47 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscalls.c,v 1.241 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD$ */
/*
* System call names.
@@ -183,7 +183,7 @@
"#156 (obsolete ogetdirentries)", /* 156 = obsolete
ogetdirentries */
"#157 (obsolete statfs25)", /* 157 = obsolete statfs25 */
"#158 (obsolete fstatfs25)", /* 158 = obsolete fstatfs25 */
- "#159 (unimplemented)", /* 159 = unimplemented */
+ "mimmutable", /* 159 = mimmutable */
"#160 (unimplemented)", /* 160 = unimplemented */
"getfh", /* 161 = getfh */
"#162 (obsolete ogetdomainname)", /* 162 = obsolete
ogetdomainname */
Index: sys/kern/syscalls.master
===================================================================
RCS file: /cvs/src/sys/kern/syscalls.master,v
retrieving revision 1.229
diff -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.48
diff -u -r1.48 exec.h
--- sys/sys/exec.h 1 Sep 2022 07:26:56 -0000 1.48
+++ sys/sys/exec.h 2 Sep 2022 20:06:23 -0000
@@ -93,6 +93,7 @@
#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 */
@@ -148,6 +149,7 @@
int vmcmd_map_readvn(struct proc *, struct exec_vmcmd *);
int vmcmd_map_zero(struct proc *, struct exec_vmcmd *);
int vmcmd_randomize(struct proc *, struct exec_vmcmd *);
+int vmcmd_mutable(struct proc *, struct exec_vmcmd *);
int copyargs(struct exec_package *, struct ps_strings *, void *, void *);
void setregs(struct proc *, struct exec_package *, u_long, register_t *);
int check_exec(struct proc *, struct exec_package *);
Index: sys/sys/exec_elf.h
===================================================================
RCS file: /cvs/src/sys/sys/exec_elf.h,v
retrieving revision 1.94
diff -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 2 Sep 2022 09:13:17 -0000
@@ -305,6 +305,7 @@
#define ELF_SYMTAB ".symtab" /* symbol table */
#define ELF_TEXT ".text" /* code */
#define ELF_OPENBSDRANDOMDATA ".openbsd.randomdata" /* constant randomdata */
+#define ELF_OPENBSDMUTABLE ".openbsd.mutable" /* mutable bss */
/* Section Attribute Flags - sh_flags */
@@ -476,6 +477,7 @@
#define PT_GNU_EH_FRAME 0x6474e550 /* Exception handling
info */
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
+#define PT_OPENBSD_MUTABLE 0x65a3dbe5 /* like bss, but not immutable
*/
#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
#define PT_OPENBSD_WXNEEDED 0x65a3dbe7 /* program performs W^X
violations */
#define PT_OPENBSD_BOOTDATA 0x65a41be6 /* section for boot arguments */
@@ -484,6 +486,7 @@
#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 -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 @@
#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/sys/syscall.h
===================================================================
RCS file: /cvs/src/sys/sys/syscall.h,v
retrieving revision 1.240
diff -u -r1.240 syscall.h
--- sys/sys/syscall.h 1 Aug 2022 14:57:19 -0000 1.240
+++ sys/sys/syscall.h 24 Aug 2022 00:32:47 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.240 2022/08/01 14:57:19 deraadt Exp $ */
+/* $OpenBSD$ */
/*
* System call numbers.
@@ -437,6 +437,9 @@
/* 156 is obsolete ogetdirentries */
/* 157 is obsolete statfs25 */
/* 158 is obsolete fstatfs25 */
+/* syscall: "mimmutable" ret: "int" args: "void *" "size_t" */
+#define SYS_mimmutable 159
+
/* syscall: "getfh" ret: "int" args: "const char *" "fhandle_t *" */
#define SYS_getfh 161
Index: sys/sys/syscallargs.h
===================================================================
RCS file: /cvs/src/sys/sys/syscallargs.h,v
retrieving revision 1.243
diff -u -r1.243 syscallargs.h
--- sys/sys/syscallargs.h 1 Aug 2022 14:57:19 -0000 1.243
+++ sys/sys/syscallargs.h 24 Aug 2022 00:32:47 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscallargs.h,v 1.243 2022/08/01 14:57:19 deraadt Exp $
*/
+/* $OpenBSD$ */
/*
* System call argument lists.
@@ -718,6 +718,11 @@
syscallarg(void *) argp;
};
+struct sys_mimmutable_args {
+ syscallarg(void *) addr;
+ syscallarg(size_t) len;
+};
+
struct sys_getfh_args {
syscallarg(const char *) fname;
syscallarg(fhandle_t *) fhp;
@@ -1328,6 +1333,7 @@
int sys_nfssvc(struct proc *, void *, register_t *);
#else
#endif
+int sys_mimmutable(struct proc *, void *, register_t *);
int sys_getfh(struct proc *, void *, register_t *);
int sys___tmpfd(struct proc *, void *, register_t *);
int sys_sysarch(struct proc *, void *, register_t *);
Index: sys/uvm/uvm.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm.h,v
retrieving revision 1.69
diff -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 @@
/*
* 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 @@
#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 -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 @@
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 -r1.294 uvm_map.c
--- sys/uvm/uvm_map.c 15 Aug 2022 15:53:45 -0000 1.294
+++ sys/uvm/uvm_map.c 3 Sep 2022 14:16:10 -0000
@@ -797,7 +797,13 @@
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 @@
}
/* 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 @@
(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 @@
* 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 @@
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 @@
KDASSERT(uvm_map_entrybyaddr(&map->addr, a) == NULL);
}
#endif
+ return 0;
}
/*
@@ -3098,6 +3129,11 @@
if (iter->start == iter->end || UVM_ET_ISHOLE(iter))
continue;
+ if ((iter->etype & UVM_ET_IMMUTABLE)) {
+ printf("uvm_map_mprotect %lx: %s\n", start,
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 @@
* (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 @@
}
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 @@
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,48 @@
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, int imut,
char *name)
+{
+ 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);
+ if (imut) {
+ // printf("%s %lx imut\n", name, entry->start);
+ entry->etype |= UVM_ET_IMMUTABLE;
+ } else {
+ printf("%s %lx mut\n", name, entry->start);
+ 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 +4445,7 @@
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 -r1.75 uvm_map.h
--- sys/uvm/uvm_map.h 12 Mar 2022 08:11:07 -0000 1.75
+++ sys/uvm/uvm_map.h 3 Sep 2022 06:46:38 -0000
@@ -350,6 +350,7 @@
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, char
*);
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 @@
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 -r1.172 uvm_mmap.c
--- sys/uvm/uvm_mmap.c 1 Aug 2022 14:56:59 -0000 1.172
+++ sys/uvm/uvm_mmap.c 3 Sep 2022 06:49:27 -0000
@@ -569,7 +569,11 @@
}
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_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, 1,
"sys");
+}
+
+/*
* sys_minherit: the minherit system call
*/
int
@@ -1228,7 +1258,8 @@
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 @@
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 -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 @@
(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 @@
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 @@
(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 @@
}
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 @@
(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 @@
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 @@
}
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 @@
(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' : '-',