From 09de7c43c1cd632319c49d7501ab65d628fbcc01 Mon Sep 17 00:00:00 2001 From: jca Date: Mon, 18 Jul 2022 18:02:27 +0000 Subject: [PATCH] Restrict pledge("vminfo") callers to read-only swapctl(2) operations. Those are the read-only operations allowed for non-root users: SWAP_NSWAP and SWAP_STATS. Users of pledge("vminfo") in base which also call swapctl(2) with said commands: top(1) and pstat(8). No regression spotted with top(1) and pstat(8) -s/-T. ok deraadt@ --- sys/kern/kern_pledge.c | 18 ++++++++++++++---- sys/sys/pledge.h | 4 ++-- sys/uvm/uvm_swap.c | 7 +++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c index c3e62d4a751..a9517c18841 100644 --- a/sys/kern/kern_pledge.c +++ b/sys/kern/kern_pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_pledge.c,v 1.289 2022/07/18 17:45:46 deraadt Exp $ */ +/* $OpenBSD: kern_pledge.c,v 1.290 2022/07/18 18:02:27 jca Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -363,7 +364,7 @@ const uint64_t pledge_syscalls[SYS_MAXSYSCALL] = { [SYS_ypconnect] = PLEDGE_GETPW, - [SYS_swapctl] = PLEDGE_VMINFO, /* XXX should limit to "get" operations */ + [SYS_swapctl] = PLEDGE_VMINFO, }; static const struct { @@ -1539,11 +1540,20 @@ pledge_flock(struct proc *p) } int -pledge_swapctl(struct proc *p) +pledge_swapctl(struct proc *p, int cmd) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); - return (EPERM); + + if (p->p_p->ps_pledge & PLEDGE_VMINFO) { + switch (cmd) { + case SWAP_NSWAP: + case SWAP_STATS: + return (0); + } + } + + return pledge_fail(p, EPERM, PLEDGE_VMINFO); } /* bsearch over pledgereq. return flags value if found, 0 else */ diff --git a/sys/sys/pledge.h b/sys/sys/pledge.h index f569cde4339..3b64096f820 100644 --- a/sys/sys/pledge.h +++ b/sys/sys/pledge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pledge.h,v 1.45 2022/07/18 17:45:46 deraadt Exp $ */ +/* $OpenBSD: pledge.h,v 1.46 2022/07/18 18:02:27 jca Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -136,7 +136,7 @@ int pledge_ioctl_drm(struct proc *p, long com, dev_t device); int pledge_ioctl_vmm(struct proc *p, long com); int pledge_flock(struct proc *p); int pledge_fcntl(struct proc *p, int cmd); -int pledge_swapctl(struct proc *p); +int pledge_swapctl(struct proc *p, int cmd); int pledge_kill(struct proc *p, pid_t pid); int pledge_protexec(struct proc *p, int prot); void ppath_destroy(struct process *ps); diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c index 62237d86468..bbba5b03b99 100644 --- a/sys/uvm/uvm_swap.c +++ b/sys/uvm/uvm_swap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_swap.c,v 1.160 2022/07/11 11:29:11 mpi Exp $ */ +/* $OpenBSD: uvm_swap.c,v 1.161 2022/07/18 18:02:27 jca Exp $ */ /* $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $ */ /* @@ -637,6 +637,9 @@ sys_swapctl(struct proc *p, void *v, register_t *retval) misc = SCARG(uap, misc); + if ((error = pledge_swapctl(p, SCARG(uap, cmd)))) + return error; + /* * ensure serialized syscall access by grabbing the swap_syscall_lock */ @@ -696,7 +699,7 @@ sys_swapctl(struct proc *p, void *v, register_t *retval) } /* all other requests require superuser privs. verify. */ - if ((error = suser(p)) || (error = pledge_swapctl(p))) + if ((error = suser(p))) goto out; /* -- 2.20.1