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