Date: Tue, 2 Jul 2019 19:07:18 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r349609 - in head: lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys sys/vm Message-ID: <201907021907.x62J7IdO092798@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Tue Jul 2 19:07:17 2019 New Revision: 349609 URL: https://svnweb.freebsd.org/changeset/base/349609 Log: Control implicit PROT_MAX() using procctl(2) and the FreeBSD note feature bit. In particular, allocate the bit to opt-out the image from implicit PROTMAX enablement. Provide procctl(2) verbs to set and query implicit PROTMAX handling. The knobs mimic the same per-image flag and per-process controls for ASLR. Reviewed by: emaste, markj (previous version) Discussed with: brooks Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D20795 Modified: head/lib/libc/sys/procctl.2 head/sys/compat/freebsd32/freebsd32_misc.c head/sys/kern/kern_procctl.c head/sys/sys/elf_common.h head/sys/sys/proc.h head/sys/sys/procctl.h head/sys/sys/syscallsubr.h head/sys/vm/vm_mmap.c Modified: head/lib/libc/sys/procctl.2 ============================================================================== --- head/lib/libc/sys/procctl.2 Tue Jul 2 19:01:14 2019 (r349608) +++ head/lib/libc/sys/procctl.2 Tue Jul 2 19:07:17 2019 (r349609) @@ -94,7 +94,7 @@ Same notes as for .Dv PROC_ASLR_FORCE_ENABLE apply. .It Dv PROC_ASLR_NOFORCE -Use system-wide configured policy for ASLR. +Use the system-wide configured policy for ASLR. .El .It Dv PROC_ASLR_STATUS Returns the current status of ASLR enablement for the target process. @@ -112,6 +112,47 @@ If the currently executed image in the process itself the .Dv PROC_ASLR_ACTIVE flag is or-ed with the value listed above. +.It Dv PROC_PROTMAX_CTL +Controls implicit application of PROT_MAX protection equal to the +.Fa prot +argument of the +.Xr mmap 2 +syscall, in the target process. +The +.Va arg +parameter must point to the integer variable holding one of the following +values: +.Bl -tag -width PROC_PROTMAX_FORCE_DISABLE +.It Dv PROC_PROTMAX_FORCE_ENABLE +Enables implicit PROT_MAX application, +even if it is disabled system-wide by the sysctl +.Va vm.imply_prot_max . +The image flag might still prevent the enablement. +.It Dv PROC_ASLR_FORCE_DISABLE +Request that implicit application of PROT_MAX be disabled. +Same notes as for +.Dv PROC_PROTMAX_FORCE_ENABLE +apply. +.It Dv PROC_PROTMAX_NOFORCE +Use the system-wide configured policy for PROT_MAX. +.El +.It Dv PROC_PROTMAX_STATUS +Returns the current status of implicit PROT_MAX enablement for the +target process. +The +.Va arg +parameter must point to the integer variable, where one of the +following values is written: +.Bl -tag -width PROC_PROTMAX_FORCE_DISABLE +.It Dv PROC_PROTMAX_FORCE_ENABLE +.It Dv PROC_PROTMAX_FORCE_DISABLE +.It Dv PROC_PROTMAX_NOFORCE +.El +.Pp +If the currently executed image in the process itself has implicit PROT_MAX +application enabled, the +.Dv PROC_PROTMAX_ACTIVE +flag is or-ed with the value listed above. .It Dv PROC_SPROTECT Set process protection state. This is used to mark a process as protected from being killed if the system @@ -575,6 +616,8 @@ or invalid signal number. .Xr cap_enter 2, .Xr kill 2 , .Xr ktrace 2 , +.Xr mmap 2 , +.Xr mprotect 2 , .Xr ptrace 2 , .Xr wait 2 , .Xr capsicum 4 , Modified: head/sys/compat/freebsd32/freebsd32_misc.c ============================================================================== --- head/sys/compat/freebsd32/freebsd32_misc.c Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/compat/freebsd32/freebsd32_misc.c Tue Jul 2 19:07:17 2019 (r349609) @@ -3333,6 +3333,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_ switch (uap->com) { case PROC_ASLR_CTL: + case PROC_PROTMAX_CTL: case PROC_SPROTECT: case PROC_TRACE_CTL: case PROC_TRAPCAP_CTL: @@ -3365,6 +3366,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_ data = &x.rk; break; case PROC_ASLR_STATUS: + case PROC_PROTMAX_STATUS: case PROC_TRACE_STATUS: case PROC_TRAPCAP_STATUS: data = &flags; @@ -3394,6 +3396,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_ error = error1; break; case PROC_ASLR_STATUS: + case PROC_PROTMAX_STATUS: case PROC_TRACE_STATUS: case PROC_TRAPCAP_STATUS: if (error == 0) Modified: head/sys/kern/kern_procctl.c ============================================================================== --- head/sys/kern/kern_procctl.c Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/kern/kern_procctl.c Tue Jul 2 19:07:17 2019 (r349609) @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/systm.h> #include <sys/capsicum.h> #include <sys/lock.h> +#include <sys/mman.h> #include <sys/mutex.h> #include <sys/priv.h> #include <sys/proc.h> @@ -419,6 +420,51 @@ trapcap_status(struct thread *td, struct proc *p, int } static int +protmax_ctl(struct thread *td, struct proc *p, int state) +{ + PROC_LOCK_ASSERT(p, MA_OWNED); + + switch (state) { + case PROC_PROTMAX_FORCE_ENABLE: + p->p_flag2 &= ~P2_PROTMAX_DISABLE; + p->p_flag2 |= P2_PROTMAX_ENABLE; + break; + case PROC_PROTMAX_FORCE_DISABLE: + p->p_flag2 |= P2_PROTMAX_DISABLE; + p->p_flag2 &= ~P2_PROTMAX_ENABLE; + break; + case PROC_PROTMAX_NOFORCE: + p->p_flag2 &= ~(P2_PROTMAX_ENABLE | P2_PROTMAX_DISABLE); + break; + default: + return (EINVAL); + } + return (0); +} + +static int +protmax_status(struct thread *td, struct proc *p, int *data) +{ + int d; + + switch (p->p_flag2 & (P2_PROTMAX_ENABLE | P2_PROTMAX_DISABLE)) { + case 0: + d = PROC_ASLR_NOFORCE; + break; + case P2_PROTMAX_ENABLE: + d = PROC_PROTMAX_FORCE_ENABLE; + break; + case P2_PROTMAX_DISABLE: + d = PROC_PROTMAX_FORCE_DISABLE; + break; + } + if (kern_mmap_maxprot(p, PROT_READ) == PROT_READ) + d |= PROC_PROTMAX_ACTIVE; + *data = d; + return (0); +} + +static int aslr_ctl(struct thread *td, struct proc *p, int state) { @@ -500,6 +546,7 @@ sys_procctl(struct thread *td, struct procctl_args *ua switch (uap->com) { case PROC_ASLR_CTL: + case PROC_PROTMAX_CTL: case PROC_SPROTECT: case PROC_TRACE_CTL: case PROC_TRAPCAP_CTL: @@ -530,6 +577,7 @@ sys_procctl(struct thread *td, struct procctl_args *ua data = &x.rk; break; case PROC_ASLR_STATUS: + case PROC_PROTMAX_STATUS: case PROC_TRACE_STATUS: case PROC_TRAPCAP_STATUS: data = &flags; @@ -558,6 +606,7 @@ sys_procctl(struct thread *td, struct procctl_args *ua error = error1; break; case PROC_ASLR_STATUS: + case PROC_PROTMAX_STATUS: case PROC_TRACE_STATUS: case PROC_TRAPCAP_STATUS: if (error == 0) @@ -583,6 +632,10 @@ kern_procctl_single(struct thread *td, struct proc *p, return (aslr_status(td, p, data)); case PROC_SPROTECT: return (protect_set(td, p, *(int *)data)); + case PROC_PROTMAX_CTL: + return (protmax_ctl(td, p, *(int *)data)); + case PROC_PROTMAX_STATUS: + return (protmax_status(td, p, data)); case PROC_REAP_ACQUIRE: return (reap_acquire(td, p)); case PROC_REAP_RELEASE: @@ -618,6 +671,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t switch (com) { case PROC_ASLR_CTL: case PROC_ASLR_STATUS: + case PROC_PROTMAX_CTL: + case PROC_PROTMAX_STATUS: case PROC_REAP_ACQUIRE: case PROC_REAP_RELEASE: case PROC_REAP_STATUS: @@ -669,6 +724,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t break; case PROC_ASLR_CTL: case PROC_ASLR_STATUS: + case PROC_PROTMAX_CTL: + case PROC_PROTMAX_STATUS: case PROC_TRACE_STATUS: case PROC_TRAPCAP_STATUS: tree_locked = false; Modified: head/sys/sys/elf_common.h ============================================================================== --- head/sys/sys/elf_common.h Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/sys/elf_common.h Tue Jul 2 19:07:17 2019 (r349609) @@ -777,6 +777,7 @@ typedef struct { /* NT_FREEBSD_FEATURE_CTL desc[0] bits */ #define NT_FREEBSD_FCTL_ASLR_DISABLE 0x00000001 +#define NT_FREEBSD_FCTL_PROTMAX_DISABLE 0x00000002 /* Values for n_type. Used in core files. */ #define NT_PRSTATUS 1 /* Process status. */ Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/sys/proc.h Tue Jul 2 19:07:17 2019 (r349609) @@ -761,6 +761,8 @@ struct proc { #define P2_ASLR_ENABLE 0x00000040 /* Force enable ASLR. */ #define P2_ASLR_DISABLE 0x00000080 /* Force disable ASLR. */ #define P2_ASLR_IGNSTART 0x00000100 /* Enable ASLR to consume sbrk area. */ +#define P2_PROTMAX_ENABLE 0x00000200 /* Force enable implied PROT_MAX. */ +#define P2_PROTMAX_DISABLE 0x00000400 /* Force disable implied PROT_MAX. */ /* Flags protected by proctree_lock, kept in p_treeflags. */ #define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */ Modified: head/sys/sys/procctl.h ============================================================================== --- head/sys/sys/procctl.h Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/sys/procctl.h Tue Jul 2 19:07:17 2019 (r349609) @@ -59,6 +59,8 @@ #define PROC_PDEATHSIG_STATUS 12 /* get parent death signal */ #define PROC_ASLR_CTL 13 /* en/dis ASLR */ #define PROC_ASLR_STATUS 14 /* query ASLR status */ +#define PROC_PROTMAX_CTL 15 /* en/dis implicit PROT_MAX */ +#define PROC_PROTMAX_STATUS 16 /* query implicit PROT_MAX status */ /* Operations for PROC_SPROTECT (passed in integer arg). */ #define PPROT_OP(x) ((x) & 0xf) @@ -126,6 +128,11 @@ struct procctl_reaper_kill { #define PROC_ASLR_FORCE_DISABLE 2 #define PROC_ASLR_NOFORCE 3 #define PROC_ASLR_ACTIVE 0x80000000 + +#define PROC_PROTMAX_FORCE_ENABLE 1 +#define PROC_PROTMAX_FORCE_DISABLE 2 +#define PROC_PROTMAX_NOFORCE 3 +#define PROC_PROTMAX_ACTIVE 0x80000000 #ifndef _KERNEL __BEGIN_DECLS Modified: head/sys/sys/syscallsubr.h ============================================================================== --- head/sys/sys/syscallsubr.h Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/sys/syscallsubr.h Tue Jul 2 19:07:17 2019 (r349609) @@ -175,6 +175,7 @@ int kern_mlock(struct proc *proc, struct ucred *cred, size_t len); int kern_mmap(struct thread *td, uintptr_t addr, size_t len, int prot, int flags, int fd, off_t pos); +int kern_mmap_maxprot(struct proc *p, int prot); int kern_mprotect(struct thread *td, uintptr_t addr, size_t size, int prot); int kern_msgctl(struct thread *, int, int, struct msqid_ds *); int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *); Modified: head/sys/vm/vm_mmap.c ============================================================================== --- head/sys/vm/vm_mmap.c Tue Jul 2 19:01:14 2019 (r349608) +++ head/sys/vm/vm_mmap.c Tue Jul 2 19:07:17 2019 (r349609) @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/mutex.h> #include <sys/sysproto.h> +#include <sys/elf.h> #include <sys/filedesc.h> #include <sys/priv.h> #include <sys/proc.h> @@ -182,6 +183,19 @@ sys_mmap(struct thread *td, struct mmap_args *uap) } int +kern_mmap_maxprot(struct proc *p, int prot) +{ + + if ((p->p_flag2 & P2_PROTMAX_DISABLE) != 0 || + (p->p_fctl0 & NT_FREEBSD_FCTL_PROTMAX_DISABLE) != 0) + return (_PROT_ALL); + if (((p->p_flag2 & P2_PROTMAX_ENABLE) != 0 || imply_prot_max) && + prot != PROT_NONE) + return (prot); + return (_PROT_ALL); +} + +int kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags, int fd, off_t pos) { @@ -206,12 +220,9 @@ kern_mmap(struct thread *td, uintptr_t addr0, size_t l /* * Always honor PROT_MAX if set. If not, default to all * permissions unless we're implying maximum permissions. - * - * XXX: should be tunable per process and ABI. */ if (max_prot == 0) - max_prot = (imply_prot_max && prot != PROT_NONE) ? - prot : _PROT_ALL; + max_prot = kern_mmap_maxprot(p, prot); vms = p->p_vmspace; fp = NULL;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201907021907.x62J7IdO092798>