Add 3 new pledge requests. "ps" exposes enough sysctl information for
authorderaadt <deraadt@openbsd.org>
Fri, 23 Oct 2015 01:10:01 +0000 (01:10 +0000)
committerderaadt <deraadt@openbsd.org>
Fri, 23 Oct 2015 01:10:01 +0000 (01:10 +0000)
ps-style programs (there are quite a few in the tree, including tmux).
"vminfo" exposes a bit more system operation information, which many
observation programs want (such as top).  settime allows setting the system
time, and will be used to pledge-protect the last ntpd process.

lib/libc/sys/pledge.2
sys/kern/kern_pledge.c
sys/sys/pledge.h
sys/uvm/uvm_swap.c

index b41e034..90505f6 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pledge.2,v 1.8 2015/10/22 09:23:41 deraadt Exp $
+.\" $OpenBSD: pledge.2,v 1.9 2015/10/23 01:10:01 deraadt Exp $
 .\"
 .\" Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: October 22 2015 $
+.Dd $Mdocdate: October 23 2015 $
 .Dt PLEDGE 2
 .Os
 .Sh NAME
@@ -455,6 +455,28 @@ with
 .Xr mmap 2
 and
 .Xr mprotect 2 .
+.It Va "settime"
+Allows the setting of system time, via the
+.Xr settimeofday 2 ,
+.Xr adjtime 2 ,
+and
+.Xr adjfreq 2
+system calls.
+.It Va "ps"
+Allows enough
+.Xr sysctl 2
+interfaces to allow inspection of processes operating on the system using
+programs like
+.Xr ps 1 .
+Allows the following system calls:
+.It Va "vminfo"
+Allows enough
+.Xr sysctl 2
+interfaces to allow inspection of the system's virtual memory by
+programs like
+.Xr top 1 ,
+and
+.Xr vmstat 8 .
 .It Va "id"
 Allows the following system calls:
 .Pp
index 5138455..a5ed8cc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_pledge.c,v 1.65 2015/10/23 00:56:52 deraadt Exp $        */
+/*     $OpenBSD: kern_pledge.c,v 1.66 2015/10/23 01:10:01 deraadt Exp $        */
 
 /*
  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -86,7 +86,6 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = {
        [SYS_getpid] = PLEDGE_SELF,
        [SYS_umask] = PLEDGE_SELF,
        [SYS_sysctl] = PLEDGE_SELF,     /* read-only; narrow subset */
-       [SYS_adjtime] = PLEDGE_SELF,    /* read-only */
 
        [SYS_setsockopt] = PLEDGE_SELF, /* white list */
        [SYS_getsockopt] = PLEDGE_SELF,
@@ -116,6 +115,10 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = {
 
        [SYS_wait4] = PLEDGE_SELF,
 
+       [SYS_adjtime] = PLEDGE_SELF,    /* read-only, unless "settime" */
+       [SYS_adjfreq] = PLEDGE_SETTIME,
+       [SYS_settimeofday] = PLEDGE_SETTIME,
+
        [SYS_poll] = PLEDGE_RW,
        [SYS_kevent] = PLEDGE_RW,
        [SYS_kqueue] = PLEDGE_RW,
@@ -191,6 +194,7 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = {
        [SYS_readlink] = PLEDGE_SELF,           /* further checks in namei */
 
        [SYS_chdir] = PLEDGE_RPATH,
+       [SYS_chroot] = PLEDGE_ID,
        [SYS_openat] = PLEDGE_RPATH | PLEDGE_WPATH,
        [SYS_fstatat] = PLEDGE_RPATH | PLEDGE_WPATH,
        [SYS_faccessat] = PLEDGE_RPATH | PLEDGE_WPATH,
@@ -248,6 +252,8 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = {
        [SYS_getpeername] = PLEDGE_INET | PLEDGE_UNIX,
 
        [SYS_flock] = PLEDGE_FLOCK | PLEDGE_YP_ACTIVE,
+
+       [SYS_swapctl] = PLEDGE_VMINFO,  /* XXX should limit to "get" operations */
 };
 
 static const struct {
@@ -278,6 +284,9 @@ static const struct {
        { "fattr",              PLEDGE_FATTR },
        { "prot_exec",          PLEDGE_PROTEXEC },
        { "flock",              PLEDGE_FLOCK },
+       { "ps",                 PLEDGE_PS },
+       { "vminfo",             PLEDGE_VMINFO },
+       { "settime",            PLEDGE_SETTIME },
 };
 
 int
@@ -644,6 +653,11 @@ pledge_namei(struct proc *p, char *origpath)
                    strcmp(path, "/etc/resolv.conf") == 0)
                        return (0);
                break;
+       case SYS_chroot:
+               /* Allowed for "proc id" */
+               if ((p->p_p->ps_pledge & PLEDGE_PROC))
+                       return (0);
+               break;
        }
 
        /* ensure PLEDGE_RPATH request for doing read */
@@ -857,6 +871,53 @@ pledge_sysctl_check(struct proc *p, int miblen, int *mib, void *new)
                        return (0);
        }
 
+       if (p->p_p->ps_pledge & (PLEDGE_PS | PLEDGE_VMINFO)) {
+               if (miblen == 2 &&                      /* kern.fscale */
+                   mib[0] == CTL_KERN && mib[1] == KERN_FSCALE)
+                       return (0);
+               if (miblen == 2 &&                      /* kern.boottime */
+                   mib[0] == CTL_KERN && mib[1] == KERN_BOOTTIME)
+                       return (0);
+               if (miblen == 2 &&                      /* kern.consdev */
+                   mib[0] == CTL_KERN && mib[1] == KERN_CONSDEV)
+                       return (0);
+               if (miblen == 2 &&                      /* kern.loadavg */
+                   mib[0] == CTL_VM && mib[1] == VM_LOADAVG)
+                       return (0);
+               if (miblen == 3 &&                      /* kern.cptime2 */
+                   mib[0] == CTL_KERN && mib[1] == KERN_CPTIME2)
+                       return (0);
+       }
+
+       if ((p->p_p->ps_pledge & PLEDGE_PS)) {
+               if (miblen == 4 &&                      /* kern.procargs.* */
+                   mib[0] == CTL_KERN && mib[1] == KERN_PROC_ARGS &&
+                   (mib[3] == KERN_PROC_ARGV || mib[3] == KERN_PROC_ENV))
+                       return (0);
+               if (miblen == 6 &&                      /* kern.proc.* */
+                   mib[0] == CTL_KERN && mib[1] == KERN_PROC)
+                       return (0);
+               if (miblen == 2 &&                      /* hw.physmem */
+                   mib[0] == CTL_HW && mib[1] == HW_PHYSMEM64)
+                       return (0);
+               if (miblen == 2 &&                      /* kern.ccpu */
+                   mib[0] == CTL_KERN && mib[1] == KERN_CCPU)
+                       return (0);
+               if (miblen == 2 &&                      /* vm.maxslp */
+                   mib[0] == CTL_VM && mib[1] == VM_MAXSLP)
+                       return (0);
+       }
+
+       if ((p->p_p->ps_pledge & PLEDGE_VMINFO)) {
+               if (miblen == 2 &&                      /* vm.uvmexp */
+                   mib[0] == CTL_VM && mib[1] == VM_UVMEXP)
+                       return (0);
+               if (miblen == 3 &&                      /* vfs.generic.bcachestat */
+                   mib[0] == CTL_VFS && mib[1] == VFS_GENERIC &&
+                   mib[2] == VFS_BCACHESTAT)
+                       return (0);
+       }
+
        if ((p->p_p->ps_pledge & (PLEDGE_ROUTE | PLEDGE_INET))) {
                if (miblen == 6 &&              /* getifaddrs() */
                    mib[0] == CTL_NET && mib[1] == PF_ROUTE &&
@@ -932,6 +993,8 @@ pledge_adjtime_check(struct proc *p, const void *v)
        if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
                return (0);
 
+       if ((p->p_p->ps_pledge & PLEDGE_SETTIME))
+               return (0);
        if (delta)
                return (EFAULT);
        return (0);
@@ -1191,6 +1254,14 @@ pledge_flock_check(struct proc *p)
        return (pledge_fail(p, EPERM, PLEDGE_FLOCK));
 }
 
+int
+pledge_swapctl_check(struct proc *p)
+{
+       if ((p->p_p->ps_flags & PS_PLEDGE) == 0)
+               return (0);
+       return (EPERM);
+}
+
 void
 pledge_dropwpaths(struct process *pr)
 {
index a241305..a781041 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pledge.h,v 1.9 2015/10/20 18:04:03 deraadt Exp $      */
+/*     $OpenBSD: pledge.h,v 1.10 2015/10/23 01:10:01 deraadt Exp $     */
 
 /*
  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
@@ -47,6 +47,9 @@
 #define PLEDGE_ROUTE   0x00100000      /* routing lookups */
 #define PLEDGE_MCAST   0x00200000      /* multicast joins */
 #define PLEDGE_FLOCK   0x00400000      /* file locking */
+#define PLEDGE_PS      0x00800000      /* ps listings */
+#define PLEDGE_VMINFO  0x01000000      /* vminfo listings */
+#define PLEDGE_SETTIME 0x02000000      /* able to set/adj time/freq */
 
 #define PLEDGE_ABORT   0x08000000      /* SIGABRT instead of SIGKILL */
 
@@ -72,6 +75,7 @@ int   pledge_sockopt_check(struct proc *p, int level, int optname);
 int    pledge_socket_check(struct proc *p, int dns);
 int    pledge_ioctl_check(struct proc *p, long com, void *);
 int    pledge_flock_check(struct proc *p);
+int    pledge_swapctl_check(struct proc *p);
 
 #define PLEDGE_MAXPATHS        8192
 
index ba8f10a..f7fa31d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uvm_swap.c,v 1.137 2015/09/06 17:06:43 deraadt Exp $  */
+/*     $OpenBSD: uvm_swap.c,v 1.138 2015/10/23 01:10:01 deraadt Exp $  */
 /*     $NetBSD: uvm_swap.c,v 1.40 2000/11/17 11:39:39 mrg Exp $        */
 
 /*
@@ -51,6 +51,7 @@
 #include <sys/swap.h>
 #include <sys/disk.h>
 #include <sys/task.h>
+#include <sys/pledge.h>
 #if defined(NFSCLIENT)
 #include <sys/socket.h>
 #include <sys/domain.h>
@@ -669,7 +670,7 @@ sys_swapctl(struct proc *p, void *v, register_t *retval)
        }
 
        /* all other requests require superuser privs.   verify. */
-       if ((error = suser(p, 0)))
+       if ((error = suser(p, 0)) || pledge_swapctl_check(p))
                goto out;
 
        /*