From 8ef3921e4063d6630371d99f16513f4938c246de Mon Sep 17 00:00:00 2001 From: deraadt Date: Tue, 6 Oct 2015 15:21:26 +0000 Subject: [PATCH] Add new "tty" request, which allows TIOCGETA, TIOCGPGRP, TIOCGWINSZ, TIOCSBRK, TIOCCDTR, TIOCSETA, TIOCSETAW, and TIOCSETAF on tty vnodes. This helps programs which call tcsetattr(), tcgetattr(), or readpassphrase(). Especially the latter - tame's goal is to satisfy the libc requirements of security-sensitive programs. Remove TIOCSETAF from the basic "ioctl" request, because it is a "set" option. "ioctl" is slowly turning into a "request information, cannot set options" package. Split the "cmsg" request into "sendfd" and "recvfd". Non-SCM_RIGHTS messages are currently flowing through freely and we'll need to think about that. This split lets us more strictly describe what our many fd-passing programs will do. --- sys/kern/kern_tame.c | 58 +++++++++++++++++++++++++++----------------- sys/sys/param.h | 4 +-- sys/sys/tame.h | 11 ++++++--- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/sys/kern/kern_tame.c b/sys/kern/kern_tame.c index 0c36fb6293c..73f83a5c9fa 100644 --- a/sys/kern/kern_tame.c +++ b/sys/kern/kern_tame.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_tame.c,v 1.61 2015/10/06 14:55:41 claudio Exp $ */ +/* $OpenBSD: kern_tame.c,v 1.62 2015/10/06 15:21:26 deraadt Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -142,7 +142,7 @@ const u_int tame_syscalls[SYS_MAXSYSCALL] = { [SYS_setresuid] = TAME_PROC, /* FIONREAD/FIONBIO, plus further checks in tame_ioctl_check() */ - [SYS_ioctl] = TAME_RW | TAME_IOCTL, + [SYS_ioctl] = TAME_RW | TAME_IOCTL | TAME_TTY, [SYS_getentropy] = TAME_MALLOC, [SYS_madvise] = TAME_MALLOC, @@ -226,10 +226,13 @@ static const struct { { "tmppath", TAME_SELF | TAME_RW | TAME_TMPPATH }, { "inet", TAME_SELF | TAME_RW | TAME_INET }, { "unix", TAME_SELF | TAME_RW | TAME_UNIX }, - { "cmsg", TAME_SELF | TAME_RW | TAME_UNIX | TAME_CMSG }, { "dns", TAME_SELF | TAME_MALLOC | TAME_DNSPATH }, - { "ioctl", TAME_IOCTL }, { "getpw", TAME_SELF | TAME_MALLOC | TAME_RW | TAME_GETPW }, +/*X*/ { "cmsg", TAME_UNIX | TAME_INET | TAME_SENDFD | TAME_RECVFD }, + { "sendfd", TAME_RW | TAME_SENDFD }, + { "recvfd", TAME_RW | TAME_RECVFD }, + { "ioctl", TAME_IOCTL }, + { "tty", TAME_TTY }, { "proc", TAME_PROC }, { "cpath", TAME_CPATH }, { "abort", TAME_ABORT }, @@ -671,7 +674,7 @@ tame_aftersyscall(struct proc *p, int code, int error) * By default, only the advisory cmsg's can be received from the kernel, * such as TIMESTAMP ntpd. * - * If TAME_CMSG is set SCM_RIGHTS is also allowed through for a carefully + * If TAME_RECVFD is set SCM_RIGHTS is also allowed in for a carefully * selected set of descriptors (specifically to exclude directories). * * This results in a kill upon recv, if some other process on the system @@ -707,8 +710,8 @@ tame_cmsg_recv(struct proc *p, struct mbuf *control) if (cmsg == NULL) return (0); - if ((p->p_p->ps_tame & TAME_CMSG) == 0) - return tame_fail(p, EPERM, TAME_CMSG); + if ((p->p_p->ps_tame & TAME_RECVFD) == 0) + return tame_fail(p, EPERM, TAME_RECVFD); /* In OpenBSD, a CMSG only contains one SCM_RIGHTS. Check it. */ fdp = (int *)CMSG_DATA(cmsg); @@ -720,7 +723,7 @@ tame_cmsg_recv(struct proc *p, struct mbuf *control) fd = *fdp++; fp = fd_getfile(p->p_fd, fd); if (fp == NULL) - return tame_fail(p, EBADF, TAME_CMSG); + return tame_fail(p, EBADF, TAME_RECVFD); /* Only allow passing of sockets, pipes, and pure files */ switch (fp->f_type) { @@ -735,7 +738,7 @@ tame_cmsg_recv(struct proc *p, struct mbuf *control) default: break; } - return tame_fail(p, EPERM, TAME_CMSG); + return tame_fail(p, EPERM, TAME_RECVFD); } return (0); } @@ -757,8 +760,8 @@ tame_cmsg_send(struct proc *p, struct mbuf *control) if ((p->p_p->ps_flags & PS_TAMED) == 0) return (0); - if ((p->p_p->ps_tame & TAME_CMSG) == 0) - return tame_fail(p, EPERM, TAME_CMSG); + if ((p->p_p->ps_tame & TAME_SENDFD) == 0) + return tame_fail(p, EPERM, TAME_SENDFD); /* Scan the cmsg */ cmsg = mtod(control, struct cmsghdr *); @@ -778,7 +781,7 @@ tame_cmsg_send(struct proc *p, struct mbuf *control) fd = *fdp++; fp = fd_getfile(p->p_fd, fd); if (fp == NULL) - return tame_fail(p, EBADF, TAME_CMSG); + return tame_fail(p, EBADF, TAME_SENDFD); /* Only allow passing of sockets, pipes, and pure files */ switch (fp->f_type) { @@ -794,7 +797,7 @@ tame_cmsg_send(struct proc *p, struct mbuf *control) break; } /* Not allowed to send a bad fd type */ - return tame_fail(p, EPERM, TAME_CMSG); + return tame_fail(p, EPERM, TAME_SENDFD); } return (0); } @@ -996,9 +999,6 @@ tame_ioctl_check(struct proc *p, long com, void *v) case TIOCGETA: case TIOCGPGRP: case TIOCGWINSZ: /* various programs */ - case TIOCSTI: /* ksh? csh? */ - case TIOCSBRK: /* cu */ - case TIOCCDTR: /* cu */ if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) return (0); break; @@ -1007,10 +1007,6 @@ tame_ioctl_check(struct proc *p, long com, void *v) fp->f_ops->fo_ioctl == vn_ioctl) return (0); break; - case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */ - if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) - return (0); - break; case MTIOCGET: case MTIOCTOP: /* for pax(1) and such, checking tapes... */ @@ -1026,8 +1022,26 @@ tame_ioctl_check(struct proc *p, long com, void *v) } } - printf("tame: ioctl %lx\n", com); - return (EPERM); + if ((p->p_p->ps_tame & TAME_TTY)) { + switch (com) { + case TIOCGETA: + case TIOCGPGRP: + case TIOCGWINSZ: /* various programs */ +#if notyet + case TIOCSTI: /* ksh? csh? */ +#endif + case TIOCSBRK: /* cu */ + case TIOCCDTR: /* cu */ + case TIOCSETA: /* cu, ... */ + case TIOCSETAW: /* cu, ... */ + case TIOCSETAF: /* tcsetattr TCSAFLUSH, script */ + if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) + return (0); + break; + } + } + + return tame_fail(p, EPERM, TAME_IOCTL); } int diff --git a/sys/sys/param.h b/sys/sys/param.h index 68c3ef4c117..8d7a7c32c2d 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -1,4 +1,4 @@ -/* $OpenBSD: param.h,v 1.118 2015/07/02 01:34:00 dlg Exp $ */ +/* $OpenBSD: param.h,v 1.119 2015/10/06 15:21:26 deraadt Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -38,8 +38,6 @@ #define _SYS_PARAM_H_ #define BSD 199306 /* System version (year & month). */ -#define BSD4_3 1 -#define BSD4_4 1 #define OpenBSD 201510 /* OpenBSD version (year & month). */ #define OpenBSD5_8 1 /* OpenBSD 5.8 */ diff --git a/sys/sys/tame.h b/sys/sys/tame.h index c553729ce02..8cfbd036b6a 100644 --- a/sys/sys/tame.h +++ b/sys/sys/tame.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tame.h,v 1.9 2015/10/06 14:55:41 claudio Exp $ */ +/* $OpenBSD: tame.h,v 1.10 2015/10/06 15:21:26 deraadt Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -33,13 +33,16 @@ #define TAME_TMPPATH 0x00000040 /* for mk*temp() */ #define TAME_INET 0x00000080 /* AF_INET/AF_INET6 sockets */ #define TAME_UNIX 0x00000100 /* AF_UNIX sockets */ -#define TAME_CMSG 0x00000200 /* AF_UNIX CMSG fd passing */ -#define TAME_IOCTL 0x00000400 /* scary */ -#define TAME_GETPW 0x00000800 /* enough to enable YP */ +// reuse, old CMSG 0x00000200 +#define TAME_IOCTL 0x00000400 /* Select ioctl */ +#define TAME_GETPW 0x00000800 /* YP enables if ypbind.lock */ #define TAME_PROC 0x00001000 /* fork, waitpid, etc */ #define TAME_CPATH 0x00002000 /* allow creat, mkdir, path creations */ #define TAME_FATTR 0x00004000 /* allow explicit file st_* mods */ #define TAME_PROTEXEC 0x00008000 /* allow use of PROT_EXEC */ +#define TAME_TTY 0x00010000 /* tty setting */ +#define TAME_SENDFD 0x00020000 /* AF_UNIX CMSG fd sending */ +#define TAME_RECVFD 0x00040000 /* AF_UNIX CMSG fd receiving */ #define TAME_ABORT 0x08000000 /* SIGABRT instead of SIGKILL */ -- 2.20.1