> From: Theo de Raadt <dera...@openbsd.org>
> Date: Sun, 22 Jan 2017 20:52:14 -0700
> 
> 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.

ok kettenis@

> 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