Restrict pledge("vminfo") callers to read-only swapctl(2) operations.
authorjca <jca@openbsd.org>
Mon, 18 Jul 2022 18:02:27 +0000 (18:02 +0000)
committerjca <jca@openbsd.org>
Mon, 18 Jul 2022 18:02:27 +0000 (18:02 +0000)
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
sys/sys/pledge.h
sys/uvm/uvm_swap.c

index c3e62d4..a9517c1 100644 (file)
@@ -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 <nicm@openbsd.org>
@@ -34,6 +34,7 @@
 #include <sys/syslog.h>
 #include <sys/ktrace.h>
 #include <sys/acct.h>
+#include <sys/swap.h>
 
 #include <sys/ioctl.h>
 #include <sys/termios.h>
@@ -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 */
index f569cde..3b64096 100644 (file)
@@ -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 <nicm@openbsd.org>
@@ -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);
index 62237d8..bbba5b0 100644 (file)
@@ -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;
 
        /*