Dear tech,

currently the MAP_CONCEAL flag for mmap(2) can be bypassed with a
stack overflow. FreeBSD introduced a similar flag called MAP_NOCORE.
They also save the auxinfo pointer in some struct that is attached
to the proc struct, similar to the diff below.

Here is an example CTF challenge:

/*
 * Setup:
 * make mmap
 * echo 'this is a well kept secret' > flag.txt
 * printf 'flag.txt\0' | ./mmap
 * strings mmap.core | grep secret
 */

#include <sys/mman.h>

#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

char *
load_file(char *path)
{
        char *addr;
        int fd;

        fd = open(path, O_RDONLY);
        if ((addr = mmap((char *)0x40000, 0x100, PROT_READ, MAP_FIXED
        | MAP_CONCEAL, fd, 0)) == MAP_FAILED)
                err(1, NULL);
        close(fd);

        return (addr);
}

int
main(void)
{
        char file[0x100];
        char *buf;

        puts("Content-type: text/html\n");
        puts("<h1>simple mmap</h1><p>POST filename to /cgi-bin/mmap</p>");
        read(0, file, 0x1000);
        buf = load_file(file);
        printf("load: %p\n", buf);
        fflush(stdout);

        return (0);
}


With the following python program (on amd64) I can generate an input
string that writes the MAP_CONCEALED content of flag.txt to the
core file:

import struct
p64 = lambda x: struct.pack("<Q", x)

leak=0x40000
pwn = (b"flag.txt" + b"\x00"*8 + (p64(leak) + p64(0) )* 100)

import sys
sys.stdout.buffer.write(pwn)

Below is a diff that addresses this.
OK?

mbuhl


Index: kern/exec_elf.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/kern/exec_elf.c,v
retrieving revision 1.174
diff -u -p -r1.174 exec_elf.c
--- kern/exec_elf.c     5 Nov 2022 10:31:16 -0000       1.174
+++ kern/exec_elf.c     6 Nov 2022 13:33:53 -0000
@@ -1221,9 +1221,6 @@ coredump_walk_elf(vaddr_t start, vaddr_t
 int
 coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep)
 {
-       struct ps_strings pss;
-       struct iovec iov;
-       struct uio uio;
        struct elfcore_procinfo cpi;
        Elf_Note nhdr;
        struct process *pr = p->p_p;
@@ -1282,23 +1279,7 @@ coredump_notes_elf(struct proc *p, void 
        /* Second, write an NT_OPENBSD_AUXV note. */
        notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
            elfround(ELF_AUX_WORDS * sizeof(char *));
-       if (iocookie) {
-               iov.iov_base = &pss;
-               iov.iov_len = sizeof(pss);
-               uio.uio_iov = &iov;
-               uio.uio_iovcnt = 1;
-               uio.uio_offset = (off_t)pr->ps_strings;
-               uio.uio_resid = sizeof(pss);
-               uio.uio_segflg = UIO_SYSSPACE;
-               uio.uio_rw = UIO_READ;
-               uio.uio_procp = NULL;
-
-               error = uvm_io(&p->p_vmspace->vm_map, &uio, 0);
-               if (error)
-                       return (error);
-
-               if (pss.ps_envstr == NULL)
-                       return (EIO);
+       if (iocookie && pr->ps_auxinfo) {
 
                nhdr.namesz = sizeof("OpenBSD");
                nhdr.descsz = ELF_AUX_WORDS * sizeof(char *);
@@ -1315,7 +1296,7 @@ coredump_notes_elf(struct proc *p, void 
                        return (error);
 
                error = coredump_write(iocookie, UIO_USERSPACE,
-                   pss.ps_envstr + pss.ps_nenvstr + 1, nhdr.descsz);
+                   (caddr_t)pr->ps_auxinfo, nhdr.descsz);
                if (error)
                        return (error);
        }
Index: kern/kern_exec.c
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.238
diff -u -p -r1.238 kern_exec.c
--- kern/kern_exec.c    30 Oct 2022 17:43:40 -0000      1.238
+++ kern/kern_exec.c    6 Nov 2022 10:37:19 -0000
@@ -492,6 +492,8 @@ sys_execve(struct proc *p, void *v, regi
        if (!copyargs(&pack, &arginfo, stack, argp))
                goto exec_abort;
 
+       pr->ps_auxinfo = (vaddr_t)pack.ep_auxinfo;
+
        /* copy out the process's ps_strings structure */
        if (copyout(&arginfo, (char *)pr->ps_strings, sizeof(arginfo)))
                goto exec_abort;
Index: sys/proc.h
===================================================================
RCS file: /mount/openbsd/cvs/src/sys/sys/proc.h,v
retrieving revision 1.334
diff -u -p -r1.334 proc.h
--- sys/proc.h  23 Jul 2022 22:10:59 -0000      1.334
+++ sys/proc.h  6 Nov 2022 10:37:19 -0000
@@ -215,6 +215,7 @@ struct process {
        char    ps_comm[_MAXCOMLEN];    /* command name, incl NUL */
 
        vaddr_t ps_strings;             /* User pointers to argv/env */
+       vaddr_t ps_auxinfo;             /* User pointer to auxinfo */
        vaddr_t ps_timekeep;            /* User pointer to timekeep */
        vaddr_t ps_sigcode;             /* [I] User pointer to signal code */
        vaddr_t ps_sigcoderet;          /* [I] User ptr to sigreturn retPC */

Reply via email to