> 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 > >