Early during pledge development the "ioctl" promise was a kitchen
sink of options until we could differentiate use cases, identify
common patterns, and then create domain-specific promises.

only 4 cases remain of "ioctl" remain:

- pax/tar/cpio experience great difficulty finding tape drives quite
  late, so they need a few MTIO ioctls.  this is not easily fixable
  in the program, let's create a "tape" promise.
- tcpdump and pflogd need a single bpf ioctl to collect status information
  at termination
- httpd wants SIOCGIFGROUP during the config file parser, but kernel code
  indicates this is a pretty safe piece of code, so let's serve it with
  the "inet" promise.

So let's just split these cases out.  "ioctl"'s number gets reused for
tape, and a new "bpf" promise is added..  That paves the way for a
more complex diff coming in a few hours.

Index: sys/sys/pledge.h
===================================================================
RCS file: /cvs/src/sys/sys/pledge.h,v
retrieving revision 1.29
diff -u -p -u -r1.29 pledge.h
--- sys/sys/pledge.h    3 Jul 2016 04:36:08 -0000       1.29
+++ sys/sys/pledge.h    23 Jan 2017 03:22:23 -0000
@@ -36,7 +36,7 @@
 #define PLEDGE_FLOCK   0x0000000000000080ULL   /* file locking */
 #define PLEDGE_UNIX    0x0000000000000100ULL   /* AF_UNIX sockets */
 #define PLEDGE_ID      0x0000000000000200ULL   /* allow setuid, setgid, etc */
-#define PLEDGE_IOCTL   0x0000000000000400ULL   /* Select ioctl */
+#define PLEDGE_TAPE    0x0000000000000400ULL   /* Tape ioctl */
 #define PLEDGE_GETPW   0x0000000000000800ULL   /* YP enables if ypbind.lock */
 #define PLEDGE_PROC    0x0000000000001000ULL   /* fork, waitpid, etc */
 #define PLEDGE_SETTIME 0x0000000000002000ULL   /* able to set/adj time/freq */
@@ -58,6 +58,7 @@
 #define PLEDGE_VMM     0x0000000040000000ULL   /* vmm ioctls */
 #define PLEDGE_CHOWN   0x0000000080000000ULL   /* chown(2) family */
 #define PLEDGE_CHOWNUID        0x0000000100000000ULL   /* allow owner/group 
changes */
+#define PLEDGE_BPF     0x0000000200000000ULL   /* bpf ioctl */
 
 /*
  * Bits outside PLEDGE_USERSET are used by the kernel itself
@@ -82,7 +83,7 @@ static struct {
        { PLEDGE_FLOCK,         "flock" },
        { PLEDGE_UNIX,          "unix" },
        { PLEDGE_ID,            "id" },
-       { PLEDGE_IOCTL,         "ioctl" },
+       { PLEDGE_TAPE,          "tape" },
        { PLEDGE_GETPW,         "getpw" },
        { PLEDGE_PROC,          "proc" },
        { PLEDGE_SETTIME,       "settime" },
@@ -103,6 +104,7 @@ static struct {
        { PLEDGE_DRM,           "drm" },
        { PLEDGE_VMM,           "vmm" },
        { PLEDGE_CHOWNUID,      "chown" },
+       { PLEDGE_BPF,           "bpf" },
        { 0, NULL },
 };
 #endif
Index: sys/kern/kern_pledge.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.190
diff -u -p -u -r1.190 kern_pledge.c
--- sys/kern/kern_pledge.c      23 Jan 2017 03:17:55 -0000      1.190
+++ sys/kern/kern_pledge.c      23 Jan 2017 03:28:08 -0000
@@ -235,8 +235,7 @@ const uint64_t pledge_syscalls[SYS_MAXSY
 
        /*
         * FIONREAD/FIONBIO for "stdio"
-        * A few non-tty ioctl available using "ioctl"
-        * tty-centric ioctl available using "tty"
+        * Other ioctl are selectively allowed based upon other pledges.
         */
        [SYS_ioctl] = PLEDGE_STDIO,
 
@@ -360,6 +359,7 @@ static const struct {
        uint64_t flags;
 } pledgereq[] = {
        { "audio",              PLEDGE_AUDIO },
+       { "bpf",                PLEDGE_BPF },
        { "chown",              PLEDGE_CHOWN | PLEDGE_CHOWNUID },
        { "cpath",              PLEDGE_CPATH },
        { "disklabel",          PLEDGE_DISKLABEL },
@@ -372,7 +372,6 @@ static const struct {
        { "getpw",              PLEDGE_GETPW },
        { "id",                 PLEDGE_ID },
        { "inet",               PLEDGE_INET },
-       { "ioctl",              PLEDGE_IOCTL },
        { "mcast",              PLEDGE_MCAST },
        { "pf",                 PLEDGE_PF },
        { "proc",               PLEDGE_PROC },
@@ -384,6 +383,7 @@ static const struct {
        { "sendfd",             PLEDGE_SENDFD },
        { "settime",            PLEDGE_SETTIME },
        { "stdio",              PLEDGE_STDIO },
+       { "tape",               PLEDGE_TAPE },
        { "tmppath",            PLEDGE_TMPPATH },
        { "tty",                PLEDGE_TTY },
        { "unix",               PLEDGE_UNIX },
@@ -1127,23 +1127,27 @@ pledge_ioctl(struct proc *p, long com, s
                        return (ENOTTY);
        }
 
-       /*
-        * Further sets of ioctl become available, but are checked a
-        * bit more carefully against the vnode.
-        */
-       if ((p->p_p->ps_pledge & PLEDGE_IOCTL)) {
+       if ((p->p_p->ps_pledge & PLEDGE_INET)) {
                switch (com) {
-               case TIOCGETA:
-               case TIOCGPGRP:
-               case TIOCGWINSZ:        /* ENOTTY return for non-tty */
-                       if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
+               case SIOCGIFGROUP:
+                       if (fp->f_type == DTYPE_SOCKET)
                                return (0);
-                       return (ENOTTY);
+                       break;
+               }
+       }
+
+       if ((p->p_p->ps_pledge & PLEDGE_BPF)) {
+               switch (com) {
                case BIOCGSTATS:        /* bpf: tcpdump privsep on ^C */
                        if (fp->f_type == DTYPE_VNODE &&
                            fp->f_ops->fo_ioctl == vn_ioctl)
                                return (0);
                        break;
+               }
+       }
+
+       if ((p->p_p->ps_pledge & PLEDGE_TAPE)) {
+               switch (com) {
                case MTIOCGET:
                case MTIOCTOP:
                        /* for pax(1) and such, checking tapes... */
@@ -1151,11 +1155,6 @@ pledge_ioctl(struct proc *p, long com, s
                            (vp->v_type == VCHR || vp->v_type == VBLK))
                                return (0);
                        break;
-               case SIOCGIFGROUP:
-                       if ((p->p_p->ps_pledge & PLEDGE_INET) &&
-                           fp->f_type == DTYPE_SOCKET)
-                               return (0);
-                       break;
                }
        }
 
@@ -1314,7 +1313,7 @@ pledge_ioctl(struct proc *p, long com, s
 #endif
        }
 
-       return pledge_fail(p, error, PLEDGE_IOCTL);
+       return pledge_fail(p, error, PLEDGE_TTY);
 }
 
 int
Index: bin/pax/ar_io.c
===================================================================
RCS file: /cvs/src/bin/pax/ar_io.c,v
retrieving revision 1.59
diff -u -p -u -r1.59 ar_io.c
--- bin/pax/ar_io.c     26 Aug 2016 04:31:35 -0000      1.59
+++ bin/pax/ar_io.c     23 Jan 2017 03:39:43 -0000
@@ -1261,7 +1261,7 @@ ar_start_gzip(int fd, const char *path, 
                close(fds[1]);
 
                if (pmode == 0 || (act != EXTRACT && act != COPY)) {
-                   if (pledge("stdio rpath wpath cpath fattr dpath getpw ioctl 
proc",
+                   if (pledge("stdio rpath wpath cpath fattr dpath getpw proc 
tape",
                        NULL) == -1)
                                err(1, "pledge");
                }
Index: bin/pax/pax.c
===================================================================
RCS file: /cvs/src/bin/pax/pax.c,v
retrieving revision 1.47
diff -u -p -u -r1.47 pax.c
--- bin/pax/pax.c       26 Aug 2016 04:11:16 -0000      1.47
+++ bin/pax/pax.c       23 Jan 2017 03:26:23 -0000
@@ -261,13 +261,13 @@ main(int argc, char **argv)
         * so can't pledge at all then.
         */
        if (pmode == 0 || (act != EXTRACT && act != COPY)) {
-               if (pledge("stdio rpath wpath cpath fattr dpath getpw ioctl 
proc exec",
+               if (pledge("stdio rpath wpath cpath fattr dpath getpw proc exec 
tape",
                    NULL) == -1)
                        err(1, "pledge");
 
                /* Copy mode, or no gzip -- don't need to fork/exec. */
                if (gzip_program == NULL || act == COPY) {
-                       if (pledge("stdio rpath wpath cpath fattr dpath getpw 
ioctl",
+                       if (pledge("stdio rpath wpath cpath fattr dpath getpw 
tape",
                            NULL) == -1)
                                err(1, "pledge");
                }
Index: usr.sbin/tcpdump/privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v
retrieving revision 1.43
diff -u -p -u -r1.43 privsep.c
--- usr.sbin/tcpdump/privsep.c  25 Jul 2016 02:35:26 -0000      1.43
+++ usr.sbin/tcpdump/privsep.c  23 Jan 2017 03:26:54 -0000
@@ -272,7 +272,7 @@ priv_init(int argc, char **argv)
                        test_state(cmd, STATE_RUN);
                        impl_init_done(socks[0], &bpfd);
 
-                       if (pledge("stdio rpath inet unix ioctl dns recvfd", 
NULL) == -1)
+                       if (pledge("stdio rpath inet unix dns recvfd bpf", 
NULL) == -1)
                                err(1, "pledge");
 
                        break;
Index: sbin/pflogd/privsep.c
===================================================================
RCS file: /cvs/src/sbin/pflogd/privsep.c,v
retrieving revision 1.22
diff -u -p -u -r1.22 privsep.c
--- sbin/pflogd/privsep.c       16 Jan 2016 03:17:48 -0000      1.22
+++ sbin/pflogd/privsep.c       23 Jan 2017 03:27:22 -0000
@@ -120,8 +120,7 @@ priv_init(void)
 
 
 #if notyet
-       /* This needs to do bpf ioctl */
-       if (pledge("stdio rpath wpath cpath ioctl sendfd", NULL) == -1)
+       if (pledge("stdio rpath wpath cpath sendfd bpf", NULL) == -1)
                err(1, "pledge");
 #endif
        while (!gotsig_chld) {
Index: usr.sbin/httpd/httpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v
retrieving revision 1.63
diff -u -p -u -r1.63 httpd.c
--- usr.sbin/httpd/httpd.c      9 Jan 2017 14:49:22 -0000       1.63
+++ usr.sbin/httpd/httpd.c      23 Jan 2017 03:27:57 -0000
@@ -222,8 +222,7 @@ main(int argc, char *argv[])
        if (ps->ps_noaction == 0)
                log_info("startup");
 
-       if (pledge("stdio rpath wpath cpath inet dns ioctl sendfd",
-           NULL) == -1)
+       if (pledge("stdio rpath wpath cpath inet dns sendfd", NULL) == -1)
                fatal("pledge");
 
        event_init();
Index: lib/libc/sys/pledge.2
===================================================================
RCS file: /cvs/src/lib/libc/sys/pledge.2,v
retrieving revision 1.37
diff -u -p -u -r1.37 pledge.2
--- lib/libc/sys/pledge.2       27 Oct 2016 10:48:25 -0000      1.37
+++ lib/libc/sys/pledge.2       23 Jan 2017 03:50:13 -0000
@@ -76,11 +76,25 @@ Read-only, for
 .Pp
 .It Xr ioctl 2
 Only the
-.Dv FIONREAD
+.Dv FIONREAD ,
+.Dv FIONBIO ,
+.Dv FIOCLEX ,
 and
-.Dv FIONBIO
+.Dv FIONCLEX
 operations are allowed by default.
-Use of the "tty" and "ioctl" promises receive more ioctl requests.
+Various ioctl requests are allowed against specific file descriptors
+based upon the requests
+.Va "audio" ,
+.Va "bpf" ,
+.Va "disklabel" ,
+.Va "drm" ,
+.Va "inet" ,
+.Va "pf" ,
+.Va "route" ,
+.Va "tape" ,
+.Va "tty" ,
+and
+.Va "vmm".
 .Pp
 .It Xr chmod 2
 .It Xr fchmod 2
@@ -386,26 +400,12 @@ File descriptors referring to directorie
 Allows receiving of file descriptors using
 .Xr recvmsg 2 .
 File descriptors referring to directories may not be passed.
-.It Va "ioctl"
-Allows a subset of
-.Xr ioctl 2
-operations:
-.Pp
-.Dv FIOCLEX ,
-.Dv FIONCLEX ,
-.Dv FIOASYNC ,
-.Dv FIOGETOWN ,
-and
-.Dv FIOSETOWN .
-On a tty device
-.Dv TIOCGETA will succeed otherwise fail with
-.Er EPERM .
-On a tty device,
-.Dv TIOCGPGRP
+.It Va "tape"
+Allow
+.Dv MTIOCGET
 and
-.Dv TIOCGWINSZ
-are allowed.
-A few other operations are allowed, but not listed here.
+.Dv MTIOCTOP
+operations against tape drives.
 .It Va "tty"
 In addition to allowing read-write operations on
 .Pa /dev/tty ,
@@ -528,6 +528,10 @@ devices:
 .Dv AUDIO_SETPAR ,
 .Dv AUDIO_START ,
 .Dv AUDIO_STOP .
+.It Va "bpf"
+Allow
+.Dv BIOCGSTATS
+operation for statistics collection from a bpf device.
 .Pp
 See
 .Xr sio_open 3

Reply via email to