[prev in list] [next in list] [ prev in thread ] [next in thread] List: openbsd-tech Subject: tame(2) WIP From: Theo de Raadt <deraadt () cvs ! openbsd ! org> Date: 2015-07-18 22:50:27 Message-ID: 201507182250.t6IMoSS2022812 () shear ! ucar ! edu [Download RAW message or body] I have been working for a while on a subsystem to restrict programs into a "reduced feature operating model". Other people have made such systems in the past, but I have never been happy with them. I don't think I am alone. Generally there are two models of operation. The first model requires a major rewrite of application software for effective use (ie. capsicum). The other model in common use lacks granularity, and allows or denies an operation throughout the entire lifetime of a process. As a result, they lack differentiation between program "initialization" versus "main servicing loop". systrace had the same problem. My observation is that programs need a large variety of calls during initialization, but few in their main loops. Some BPF-style approaches have showed up. So you need to write a program to observe your program, to keep things secure? That is insane. So I asked myself if I could invent a simple system call, which people would place directly into programs, between initialization and main-loop. Secondly, I wondered what kind of semantics such programs would need. Not just directly themselves, but for DNS and other macro operations. Anyways, enough explanation. A manual page follows. Then the kernel diff. Finally, a sample of 29 userland programs protected to various degrees by using it: cat pax ps dmesg ping ping6 dc diff finger from id kdump logger script sed signify uniq w wc whois arp authpf bgpd httpd ntpd relayd syslogd tcpdump traceroute Not all these are perfect, but it shows the trend. The changes are fairly simple. In the simplest non-network programs, network access is disabled. In simple network programs, file access goes away. That is the trend. Sometimes a program is easily modified, making it better, because the integration of tame hints at an improvement which will make it tighter under tame. sed is an example... TAME(2) System Calls Manual TAME(2) NAME tame - restrict system operations SYNOPSIS #include <sys/tame.h> int tame(int flags); DESCRIPTION The current process is forced into a restricted-service operating mode. A few subsets are available, roughly described as computation, memory management, read-write operations on file descriptors, opening of files, networking. In general, these modes were selected by studying the operation of many programs using libc and other such interfaces. Use of tame in an application will require at least some study and understanding of the interfaces called. Subsequent calls to tame() can reduce abilities further, but abilities can never be regained. A process which attempts a restricted operation is killed with SIGKILL. If TAME_ABORT is set, then a non-blockable SIGABRT is delivered instead, possibly resulting in a core(5) file. A flags value of 0 restricts the process to the _exit(2) system call. This can be used for pure computation operating on memory shared with another process. All TAME_* options below (with the exception of TAME_ABORT) permit the following system calls: clock_getres(2), clock_gettime(2), fchdir(2), getdtablecount(2), getegid(2), geteuid(2), getgid(2), getgroups(2), getitimer(2), getlogin(2), getpgid(2), getpgrp(2), getpid(2), getppid(2), getresgid(2), getresuid(2), getrlimit(2), getsid(2), getthrid(2), gettimeofday(2), getuid(2), getuid(2), issetugid(2), nanosleep(2), sendsyslog(2), setitimer(2), sigaction(2), sigprocmask(2), sigreturn(2), umask(2), wait4(2). Calls allowed with restrictions include: sysctl(3) A small set of read-only operations are allowed, sufficient to support: getifaddrs(3), getdomainname(3), gethostname(3), system sensor readings. access(2) May check for existance of /etc/localtime. adjtime(2) Read-only, for ntpd(8). open(2) May open /etc/localtime, any files below /usr/share/zoneinfo and files ending in libc.cat in below the directory /usr/share/nls/. readlink(2) May operate on /etc/malloc.conf. tame(2) Can only reduce permissions. The flags are specified as a bitwise OR of the following values: TAME_MALLOC To allow use of the malloc(3) family of functions, the following system calls are permitted: getentropy(2), madvise(2), minherit(2), mmap(2), mprotect(2), mquery(2), munmap(2). TAME_RW The following system calls are permitted to allow most types of IO operations on previously allocated file descriptors, including libevent or handwritten async IO loops: poll(2), kevent(2), kqueue(2), select(2), close(2), dup(2), dup2(2), dup3(2), closefrom(2), shutdown(2), read(2), readv(2), pread(2), preadv(2), write(2), writev(2), pwrite(2), pwritev(2), ftruncate(2), lseek(2), utimes(2), futimes(2), utimensat(2), futimens(2), fcntl(2), fsync(2), pipe(2), pipe2(2), socketpair(2), getdents(2), sendto(2), sendmsg(2), recvmsg(2), recvfrom(2), fstat(2). TAME_STDIO This subset is simply the combination of TAME_MALLOC and TAME_RW. As a result, all functionalities of libc stdio works. TAME_RPATH A number of system calls are allowed if they only cause read-only effects on the filesystem: chdir(2), getcwd(3), openat(2), fstatat(2), faccessat(2), readlinkat(2), lstat(2), chmod(2), fchmod(2), fchmodat(2), chflags(2), chflagsat(2), chown(2), fchown(2), fchownat(2), fstat(2). TAME_WPATH A number of system calls are allowed and may cause write-effects on the filesystem: read-only effects: getcwd(3), openat(2), fstatat(2), faccessat(2), readlinkat(2), lstat(2), chmod(2), fchmod(2), fchmodat(2), chflags(2), chflagsat(2), chown(2), fchown(2), fchownat(2), fstat(2), fstat(2). TAME_TMPPATH A number of system calls are allowed to do operations in the /tmp directory, including create, read, or write: lstat(2), chmod(2), chflags(2), chown(2), unlink(2), fstat(2). TAME_CPATH A number of system calls and sub-modes are allowed, which may create new files or directories in the filesystem: rename(2), rmdir(2), renameat(2), link(2), linkat(2), symlink(2), unlink(2), unlinkat(2), mkdir(2), mkdirat(2). TAME_INET The following system calls are allowed to operate in the AF_INET and AF_INET6 domains: socket(2), listen(2), bind(2), connect(2), accept4(2), accept(2), getpeername(2), getsockname(2), setsockopt(2), getsockopt(2). setsockopt(2) has been reduced in functionality substantially. TAME_UNIX The following system calls are allowed to operate in the AF_UNIX domain: socket(2), listen(2), bind(2), connect(2), accept4(2), accept(2), getpeername(2), getsockname(2), setsockopt(2), getsockopt(2). TAME_DNSPATH Subsequent to a succesfull open(2) of /etc/resolv.conf, a few system calls become to allow DNS network transactions: sendto(2), recvfrom(2), socket(2), connect(2). TAME_GETPW This allows read-only opening of files in /etc for the getpwnam(3), getgrnam(3,) getgrouplist(3), and initgroups(3) family of functions. They may also need to operate in a yp(8) environment, so a succesfull open(2) of /var/run/ypbind.lock enables the TAME_INET flag. TAME_CMSG Allows passing of file descriptors using the sendmsg(2) and recvmsg(2) functions. TAME_IOCTL Allows a subset of ioctl(2) operations: FIOCLEX, FIONCLEX, FIONREAD, FIONBIO, FIOGETOWN, TIOCSWINSZ, TIOCSTI. TAME_PROC Allows the following process relationship operations: fork(2), vfork(2), kill(2), setresgid(2), SYS_setresuid(2), TAME_ABORT Deliver an unblockable SIGABRT upon violation instead of SIGKILL. RETURN VALUES Upon successful completion, the value 0 is returned; otherwise the value -1 is returned and the global variable errno is set to indicate the error. ERRORS tame() will fail if: [EPERM] This process is attempting to increase permissions. HISTORY The tame() system call appeared in OpenBSD 5.8. OpenBSD 5.8 July 18, 2015 OpenBSD 5.8 Index: sys/conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.595 diff -u -p -u -r1.595 files --- sys/conf/files 17 Jul 2015 22:52:29 -0000 1.595 +++ sys/conf/files 17 Jul 2015 22:57:21 -0000 @@ -666,6 +666,7 @@ file kern/kern_physio.c file kern/kern_proc.c file kern/kern_prot.c file kern/kern_resource.c +file kern/kern_tame.c file kern/kern_sched.c file kern/kern_sensors.c file kern/kern_sig.c Index: sys/kern/init_sysent.c =================================================================== RCS file: /cvs/src/sys/kern/init_sysent.c,v retrieving revision 1.166 diff -u -p -u -r1.166 init_sysent.c --- sys/kern/init_sysent.c 6 May 2015 11:26:02 -0000 1.166 +++ sys/kern/init_sysent.c 26 May 2015 17:40:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: init_sysent.c,v 1.166 2015/05/06 11:26:02 jsg Exp $ */ +/* $OpenBSD$ */ /* * System call switch table. @@ -248,8 +248,8 @@ struct sysent sysent[] = { sys_listen }, /* 106 = listen */ { 4, s(struct sys_chflagsat_args), 0, sys_chflagsat }, /* 107 = chflagsat */ - { 0, 0, 0, - sys_nosys }, /* 108 = obsolete osigvec */ + { 1, s(struct sys_tame_args), 0, + sys_tame }, /* 108 = tame */ { 4, s(struct sys_ppoll_args), 0, sys_ppoll }, /* 109 = ppoll */ { 6, s(struct sys_pselect_args), 0, Index: sys/kern/kern_fork.c =================================================================== RCS file: /cvs/src/sys/kern/kern_fork.c,v retrieving revision 1.180 diff -u -p -u -r1.180 kern_fork.c --- sys/kern/kern_fork.c 14 Mar 2015 07:33:42 -0000 1.180 +++ sys/kern/kern_fork.c 21 May 2015 22:35:59 -0000 @@ -203,7 +203,7 @@ process_new(struct proc *p, struct proce if (pr->ps_textvp) vref(pr->ps_textvp); - pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC); + pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC | PS_TAMED); if (parent->ps_session->s_ttyvp != NULL) pr->ps_flags |= parent->ps_flags & PS_CONTROLT; Index: sys/kern/kern_sig.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sig.c,v retrieving revision 1.180 diff -u -p -u -r1.180 kern_sig.c --- sys/kern/kern_sig.c 5 May 2015 02:13:46 -0000 1.180 +++ sys/kern/kern_sig.c 3 Jun 2015 00:59:59 -0000 @@ -1420,6 +1420,7 @@ sigexit(struct proc *p, int signum) TAILQ_NEXT(p, p_thr_link) != NULL) single_thread_set(p, SINGLE_SUSPEND, 0); + atomic_clearbits_int(&p->p_p->ps_flags, PS_TAMED); if (coredump(p) == 0) signum |= WCOREFLAG; } Index: sys/kern/kern_sysctl.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sysctl.c,v retrieving revision 1.285 diff -u -p -u -r1.285 kern_sysctl.c --- sys/kern/kern_sysctl.c 18 May 2015 19:10:35 -0000 1.285 +++ sys/kern/kern_sysctl.c 25 Jun 2015 01:14:24 -0000 @@ -70,6 +70,7 @@ #include <sys/domain.h> #include <sys/protosw.h> #include <sys/timetc.h> +#include <sys/tame.h> #include <sys/evcount.h> #include <sys/un.h> #include <sys/unpcb.h> @@ -169,6 +170,9 @@ sys___sysctl(struct proc *p, void *v, re SCARG(uap, namelen) * sizeof(int)); if (error) return (error); + + if (tame_sysctl_check(p, SCARG(uap, namelen), name, SCARG(uap, new))) + return (tame_fail(p, EPERM, _TM_SELF)); switch (name[0]) { case CTL_KERN: Index: sys/kern/kern_tame.c =================================================================== RCS file: sys/kern/kern_tame.c diff -N sys/kern/kern_tame.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/kern_tame.c 18 Jul 2015 21:36:11 -0000 @@ -0,0 +1,788 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/types.h> + +#include <sys/mount.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/file.h> +#include <sys/vnode.h> +#include <sys/mbuf.h> +#include <sys/sysctl.h> +#include <sys/ktrace.h> + +#include <sys/ioctl.h> +#include <sys/termios.h> +#include <sys/mtio.h> +#include <net/bpf.h> +#include <net/route.h> +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <sys/tame.h> + +#include <sys/signalvar.h> +#include <sys/syscall.h> +#include <sys/syscallargs.h> +#include <sys/systm.h> + +const u_int tame_syscalls[SYS_MAXSYSCALL] = { + [SYS_exit] = 0xffffffff, + + [SYS_getuid] = _TM_SELF, + [SYS_geteuid] = _TM_SELF, + [SYS_getresuid] = _TM_SELF, + [SYS_getgid] = _TM_SELF, + [SYS_getegid] = _TM_SELF, + [SYS_getresgid] = _TM_SELF, + [SYS_getgroups] = _TM_SELF, + [SYS_getlogin] = _TM_SELF, + [SYS_getpgrp] = _TM_SELF, + [SYS_getpgid] = _TM_SELF, + [SYS_getppid] = _TM_SELF, + [SYS_getsid] = _TM_SELF, + [SYS_getthrid] = _TM_SELF, + [SYS_getrlimit] = _TM_SELF, + [SYS_gettimeofday] = _TM_SELF, + [SYS_getdtablecount] = _TM_SELF, + [SYS_issetugid] = _TM_SELF, + [SYS_clock_getres] = _TM_SELF, + [SYS_clock_gettime] = _TM_SELF, + [SYS_getpid] = _TM_SELF, + [SYS_umask] = _TM_SELF, + [SYS___sysctl] = _TM_SELF, /* read-only; narrow subset */ + [SYS_adjtime] = _TM_SELF, /* read-only */ + + [SYS_chdir] = _TM_RPATH, + + [SYS_fchdir] = _TM_SELF, /* careful of directory fd inside jails */ + + [SYS_sendsyslog] = _TM_SELF, + [SYS_nanosleep] = _TM_SELF, + [SYS_sigprocmask] = _TM_SELF, + [SYS_sigaction] = _TM_SELF, + [SYS_sigreturn] = _TM_SELF, + [SYS_getitimer] = _TM_SELF, + [SYS_setitimer] = _TM_SELF, + + [SYS_tame] = _TM_SELF, + + [SYS_wait4] = _TM_SELF, + + [SYS_poll] = _TM_RW, + [SYS_kevent] = _TM_RW, + [SYS_kqueue] = _TM_RW, + [SYS_select] = _TM_RW, + + [SYS_close] = _TM_RW, + [SYS_dup] = _TM_RW, + [SYS_dup2] = _TM_RW, + [SYS_dup3] = _TM_RW, + [SYS_closefrom] = _TM_RW, + [SYS_shutdown] = _TM_RW, + [SYS_read] = _TM_RW, + [SYS_readv] = _TM_RW, + [SYS_pread] = _TM_RW, + [SYS_preadv] = _TM_RW, + [SYS_write] = _TM_RW, + [SYS_writev] = _TM_RW, + [SYS_pwrite] = _TM_RW, + [SYS_pwritev] = _TM_RW, + [SYS_ftruncate] = _TM_RW, + [SYS_lseek] = _TM_RW, + + [SYS_utimes] = _TM_RW, + [SYS_futimes] = _TM_RW, + [SYS_utimensat] = _TM_RW, + [SYS_futimens] = _TM_RW, + + [SYS_fcntl] = _TM_RW, + [SYS_fsync] = _TM_RW, + [SYS_pipe] = _TM_RW, + [SYS_pipe2] = _TM_RW, + [SYS_socketpair] = _TM_RW, + + [SYS_getdents] = _TM_RW, + + [SYS_sendto] = _TM_RW | _TM_DNS_ACTIVE | _TM_YP_ACTIVE, + [SYS_sendmsg] = _TM_RW, + [SYS_recvmsg] = _TM_RW, + [SYS_recvfrom] = _TM_RW | _TM_DNS_ACTIVE | _TM_YP_ACTIVE, + + [SYS_fork] = _TM_PROC, + [SYS_vfork] = _TM_PROC, + [SYS_kill] = _TM_PROC, + + [SYS_setresgid] = _TM_PROC, + [SYS_setresuid] = _TM_PROC, + + [SYS_ioctl] = _TM_IOCTL, /* very limited subset */ + + [SYS_getentropy] = _TM_MALLOC, + [SYS_madvise] = _TM_MALLOC, + [SYS_minherit] = _TM_MALLOC, + [SYS_mmap] = _TM_MALLOC, + [SYS_mprotect] = _TM_MALLOC, + [SYS_mquery] = _TM_MALLOC, + [SYS_munmap] = _TM_MALLOC, + + [SYS___getcwd] = _TM_RPATH | _TM_WPATH, + [SYS_open] = _TM_SELF, + [SYS_openat] = _TM_RPATH | _TM_WPATH, + [SYS_stat] = _TM_SELF, + [SYS_fstatat] = _TM_RPATH | _TM_WPATH, + [SYS_access] = _TM_SELF, + [SYS_faccessat] = _TM_RPATH | _TM_WPATH, + [SYS_readlink] = _TM_SELF, + [SYS_readlinkat] = _TM_RPATH | _TM_WPATH, + [SYS_lstat] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH | _TM_DNSPATH, + [SYS_chmod] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH, + [SYS_fchmod] = _TM_RPATH | _TM_WPATH, + [SYS_fchmodat] = _TM_RPATH | _TM_WPATH, + [SYS_chflags] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH, + [SYS_chflagsat] = _TM_RPATH | _TM_WPATH, + [SYS_chown] = _TM_RPATH | _TM_WPATH | _TM_TMPPATH, + [SYS_fchown] = _TM_RPATH | _TM_WPATH, + [SYS_fchownat] = _TM_RPATH | _TM_WPATH, + [SYS_rename] = _TM_CPATH, + [SYS_rmdir] = _TM_CPATH, + [SYS_renameat] = _TM_CPATH, + [SYS_link] = _TM_CPATH, + [SYS_linkat] = _TM_CPATH, + [SYS_symlink] = _TM_CPATH, + [SYS_unlink] = _TM_CPATH | _TM_TMPPATH, + [SYS_unlinkat] = _TM_CPATH, + [SYS_mkdir] = _TM_CPATH, + [SYS_mkdirat] = _TM_CPATH, + + [SYS_fstat] = _TM_RW | _TM_RPATH | _TM_WPATH | _TM_TMPPATH, /* rare */ + + [SYS_socket] = _TM_INET | _TM_UNIX | _TM_DNS_ACTIVE | _TM_YP_ACTIVE, + [SYS_listen] = _TM_INET | _TM_UNIX, + [SYS_bind] = _TM_INET | _TM_UNIX, + [SYS_connect] = _TM_INET | _TM_UNIX | _TM_DNS_ACTIVE | _TM_YP_ACTIVE, + [SYS_accept4] = _TM_INET | _TM_UNIX, + [SYS_accept] = _TM_INET | _TM_UNIX, + [SYS_getpeername] = _TM_INET | _TM_UNIX, + [SYS_getsockname] = _TM_INET | _TM_UNIX, + [SYS_setsockopt] = _TM_INET | _TM_UNIX, /* small subset */ + [SYS_getsockopt] = _TM_INET | _TM_UNIX, + + [SYS_flock] = _TM_GETPW, +}; + +int +sys_tame(struct proc *p, void *v, register_t *retval) +{ + struct sys_tame_args /* { + syscallarg(int) flags; + } */ *uap = v; + int flags = SCARG(uap, flags); + + flags &= _TM_USERSET; + if ((p->p_p->ps_flags & PS_TAMED) == 0) { + p->p_p->ps_flags |= PS_TAMED; + p->p_p->ps_tame = flags; + return (0); + } + + /* May not set new bits */ + if (((flags | p->p_p->ps_tame) & _TM_USERSET) != + (p->p_p->ps_tame & _TM_USERSET)) + return (EPERM); + + /* More tame bits being cleared. Force re-learning of _ACTIVE things */ + p->p_p->ps_tame &= flags; + p->p_p->ps_tame &= _TM_USERSET; + return (0); +} + +int +tame_check(struct proc *p, int code) +{ + p->p_tamenote = p->p_tameafter = 0; /* XX optimise? */ + p->p_tame_syscall = code; + + if (code < 0 || code > SYS_MAXSYSCALL - 1) + return (0); + + if (p->p_p->ps_tame == 0) + return (code == SYS_exit); + return (p->p_p->ps_tame & tame_syscalls[code]); +} + +int +tame_fail(struct proc *p, int error, int code) +{ + printf("tame: pid %d %s syscall %d

", p->p_pid, p->p_comm, + p->p_tame_syscall); +#ifdef KTRACE + if (KTRPOINT(p, KTR_PSIG)) { + siginfo_t si; + + memset(&si, 0, sizeof(si)); + if (p->p_p->ps_tame & _TM_ABORT) + si.si_signo = SIGABRT; + else + si.si_signo = SIGKILL; + si.si_code = code; + // si.si_syscall = p->p_tame_syscall; + /// si.si_nsysarg ... + ktrpsig(p, si.si_signo, SIG_DFL, p->p_sigmask, code, &si); + } +#endif + if (p->p_p->ps_tame & _TM_ABORT) { + /* Core dump requested */ + atomic_clearbits_int(&p->p_sigmask, sigmask(SIGABRT)); + atomic_clearbits_int(&p->p_p->ps_flags, PS_TAMED); + psignal(p, SIGABRT); + } else + psignal(p, SIGKILL); + return (error); +} + +/* + * Need to make it more obvious that one cannot get through here + * without the right flags set + */ +int +tame_namei(struct proc *p, char *path) +{ + /* Detect what looks like a mkstemp(3) family operation */ + if ((p->p_p->ps_tame & _TM_TMPPATH) && + (p->p_tame_syscall == SYS_open) && + (p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_CREAT && + strncmp(path, "/tmp/", 5) == 0) { + return (0); + } + + /* Allow unlinking of a mkstemp(3) file... + * Good opportunity for strict checks here. + */ + if ((p->p_p->ps_tame & _TM_TMPPATH) && + (p->p_tame_syscall == SYS_unlink) && + strncmp(path, "/tmp/", 5) == 0) { + return (0); + } + + /* open, mkdir, or other path creation operation */ + if ((p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_CREAT && + ((p->p_p->ps_tame & _TM_CPATH) == 0)) + return (tame_fail(p, EPERM, TAME_CPATH)); + + /* inode change operation, issued against a path */ + if ((p->p_tamenote & (TMN_CREAT | TMN_IMODIFY)) == TMN_IMODIFY && + ((p->p_p->ps_tame & _TM_CPATH) == 0)) { + // XXX should _TM_CPATH be a seperate check? + return (tame_fail(p, EPERM, TAME_CPATH)); + } + + if ((p->p_tamenote & TMN_WRITE) && + (p->p_p->ps_tame & _TM_WPATH) == 0) + return (tame_fail(p, EPERM, TAME_WPATH)); + + if (p->p_p->ps_tame & _TM_RPATH) + return (0); + + if (p->p_p->ps_tame & _TM_WPATH) + return (0); + + /* All remaining cases are RPATH */ + switch (p->p_tame_syscall) { + case SYS_access: + /* tzset() needs this. */ + if (strcmp(path, "/etc/localtime") == 0) + return (0); + break; + case SYS_open: + /* getpw* and friends need a few files */ + if (p->p_p->ps_tame & _TM_GETPW) { + if (strcmp(path, "/etc/spwd.db") == 0) + return (0); + if (strcmp(path, "/etc/pwd.db") == 0) + return (0); + if (strcmp(path, "/etc/group") == 0) + return (0); + } + + /* DNS needs /etc/{resolv.conf,hosts,services}. */ + if (p->p_p->ps_tame & _TM_DNSPATH) { + if (strcmp(path, "/etc/resolv.conf") == 0) { + p->p_tamenote |= TMN_DNSRESOLV; + p->p_tameafter = 1; + return (0); + } + if (strcmp(path, "/etc/hosts") == 0) + return (0); + if (strcmp(path, "/etc/services") == 0) + return (0); + } + if (p->p_p->ps_tame & _TM_GETPW) { + if (strcmp(path, "/var/run/ypbind.lock") == 0) { + p->p_tamenote |= TMN_YPLOCK; + p->p_tameafter = 1; + return (0); + } + if (strncmp(path, "/var/yp/binding/", 14) == 0) + return (0); + } + /* tzset() needs these. */ + if (strncmp(path, "/usr/share/zoneinfo/", 20) == 0) + return (0); + if (strcmp(path, "/etc/localtime") == 0) + return (0); + + /* /usr/share/nls/../libc.cat returns EPERM, for strerror(3). */ + if (strncmp(path, "/usr/share/nls/", 15) == 0 && + strcmp(path + strlen(path) - 9, "/libc.cat") == 0) + return (EPERM); + break; + case SYS_readlink: + /* Allow /etc/malloc.conf for malloc(3). */ + if (strcmp(path, "/etc/malloc.conf") == 0) + return (0); + break; + case SYS_stat: + /* DNS needs /etc/resolv.conf. */ + if (p->p_p->ps_tame & _TM_DNSPATH) { + if (strcmp(path, "/etc/resolv.conf") == 0) { + p->p_tamenote |= TMN_DNSRESOLV; + p->p_tameafter = 1; + return (0); + } + } + break; + } + + return (tame_fail(p, EPERM, TAME_RPATH)); +} + +void +tame_aftersyscall(struct proc *p, int code, int error) +{ + if ((p->p_tamenote & TMN_YPLOCK) && error == 0) + atomic_setbits_int(&p->p_p->ps_tame, _TM_YP_ACTIVE | TAME_INET); + if ((p->p_tamenote & TMN_DNSRESOLV) && error == 0) + atomic_setbits_int(&p->p_p->ps_tame, _TM_DNS_ACTIVE); +} + +/* + * 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 + * selected set of descriptors (specifically to exclude directories). + * + * This results in a kill upon recv, if some other process on the system + * send a SCM_RIGHTS to an open socket of some sort. That will discourage + * leaving such sockets lying around... + */ +int +tame_cmsg_recv(struct proc *p, void *v, int controllen) +{ + struct mbuf *control = v; + struct msghdr tmp; + struct cmsghdr *cmsg; + struct file **rp, *fp; + int nfds, i; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + /* Scan the cmsg */ + memset(&tmp, 0, sizeof(tmp)); + tmp.msg_control = mtod(control, struct cmsghdr *); + tmp.msg_controllen = controllen; + cmsg = CMSG_FIRSTHDR(&tmp); + + while (cmsg != NULL) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) + break; + cmsg = CMSG_NXTHDR(&tmp, cmsg); + } + + /* No SCM_RIGHTS found -> OK */ + if (cmsg == NULL) + return (0); + + if ((p->p_p->ps_tame & _TM_CMSG) == 0) + return tame_fail(p, EPERM, TAME_CMSG); + + /* In OpenBSD, a CMSG only contains one SCM_RIGHTS. Check it. */ + rp = (struct file **)CMSG_DATA(cmsg); + nfds = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg))) / + sizeof(struct file *); + for (i = 0; i < nfds; i++) { + struct vnode *vp; + + fp = *rp++; + + /* Only allow passing of sockets, pipes, and pure files */ + printf("f_type %d

", fp->f_type); + switch (fp->f_type) { + case DTYPE_SOCKET: + case DTYPE_PIPE: + continue; + case DTYPE_VNODE: + vp = (struct vnode *)fp->f_data; + printf("v_type %d

", vp->v_type); + if (vp->v_type == VREG) + continue; + break; + default: + break; + } + printf("bad fd type

"); + return tame_fail(p, EPERM, TAME_CMSG); + } + return (0); +} + +/* + * When tamed, default prevents sending of a cmsg. + * If CMSG flag is set, + */ +int +tame_cmsg_send(struct proc *p, void *v, int controllen) +{ + struct mbuf *control = v; + struct msghdr tmp; + struct cmsghdr *cmsg; + struct file **rp, *fp; + int nfds, i; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if ((p->p_p->ps_tame & _TM_CMSG) == 0) + return tame_fail(p, EPERM, TAME_CMSG); + + /* Scan the cmsg */ + memset(&tmp, 0, sizeof(tmp)); + tmp.msg_control = mtod(control, struct cmsghdr *); + tmp.msg_controllen = controllen; + cmsg = CMSG_FIRSTHDR(&tmp); + + while (cmsg != NULL) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) + break; + cmsg = CMSG_NXTHDR(&tmp, cmsg); + } + + /* Contains no SCM_RIGHTS, so OK */ + if (cmsg == NULL) + return (0); + + /* In OpenBSD, a CMSG only contains one SCM_RIGHTS. Check it. */ + rp = (struct file **)CMSG_DATA(cmsg); + nfds = (cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg))) / + sizeof(struct file *); + for (i = 0; i < nfds; i++) { + struct vnode *vp; + + fp = *rp++; + + /* Only allow passing of sockets, pipes, and pure files */ + printf("f_type %d

", fp->f_type); + switch (fp->f_type) { + case DTYPE_SOCKET: + case DTYPE_PIPE: + continue; + case DTYPE_VNODE: + vp = (struct vnode *)fp->f_data; + printf("v_type %d

", vp->v_type); + if (vp->v_type == VREG) + continue; + break; + default: + break; + } + /* Not allowed to send a bad fd type */ + return tame_fail(p, EPERM, TAME_CMSG); + } + return (0); +} + +int +tame_sysctl_check(struct proc *p, int namelen, int *name, void *new) +{ + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if (new) + return (EFAULT); + + /* getifaddrs() */ + if ((p->p_p->ps_tame & _TM_INET) && + namelen == 6 && + name[0] == CTL_NET && name[1] == PF_ROUTE && + name[2] == 0 && name[3] == 0 && + name[4] == NET_RT_IFLIST && name[5] == 0) + return (0); + + /* used by arp(8). Exposes MAC addresses known on local nets */ + /* XXX Put into a special catagory. */ + if ((p->p_p->ps_tame & _TM_INET) && + namelen == 7 && + name[0] == CTL_NET && name[1] == PF_ROUTE && + name[2] == 0 && name[3] == AF_INET && + name[4] == NET_RT_FLAGS && name[5] == RTF_LLINFO) + return (0); + + /* used by ntpd(8) to read sensors. */ + /* XXX Put into a special catagory. */ + if (namelen >= 3 && + name[0] == CTL_HW && name[1] == HW_SENSORS) + return (0); + + if (namelen == 2 && + name[0] == CTL_KERN && name[1] == KERN_DOMAINNAME) + return (0); + if (namelen == 2 && + name[0] == CTL_KERN && name[1] == KERN_HOSTNAME) + return (0); + + printf("tame: pid %d %s sysctl %d: %d %d %d %d %d %d

", + p->p_pid, p->p_comm, namelen, name[0], name[1], + name[2], name[3], name[4], name[5]); + return (EFAULT); +} + +int +tame_adjtime_check(struct proc *p, const void *v) +{ + const struct timeval *delta = v; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if (delta) + return (EFAULT); + return (0); +} + +int +tame_connect_check(struct proc *p) +{ + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if ((p->p_p->ps_tame & _TM_DNS_ACTIVE)) + return (0); /* A port check happens inside sys_connect() */ + + if ((p->p_p->ps_tame & (_TM_INET | _TM_UNIX))) + return (0); + return (EPERM); +} + +int +tame_recvfrom_check(struct proc *p, void *v) +{ + struct sockaddr *from = v; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && from == NULL) + return (0); + if (p->p_p->ps_tame & _TM_INET) + return (0); + if (p->p_p->ps_tame & _TM_UNIX) + return (0); + if (from == NULL) + return (0); /* behaves just like write */ + return (EPERM); +} + +int +tame_sendto_check(struct proc *p, const void *v) +{ + const struct sockaddr *to = v; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && to == NULL) + return (0); + + if ((p->p_p->ps_tame & _TM_INET)) + return (0); + if ((p->p_p->ps_tame & _TM_UNIX)) + return (0); + if (to == NULL) + return (0); /* behaves just like write */ + return (EPERM); +} + +int +tame_socket_check(struct proc *p, int domain) +{ + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + if ((p->p_p->ps_tame & (_TM_INET | _TM_UNIX))) + return (0); + if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && domain == AF_INET) + return (0); + return (EPERM); +} + +int +tame_bind_check(struct proc *p, const void *v) +{ + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + if ((p->p_p->ps_tame & _TM_INET)) + return (0); + return (EPERM); +} + +int +tame_ioctl_check(struct proc *p, long com, void *v) +{ + struct file *fp = v; + struct vnode *vp = (struct vnode *)fp->f_data; + + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + switch (com) { + + /* + * This is a set of "get" info ioctls at the top layer. Hopefully + * a safe list, since they are used a lot. + */ + case FIOCLEX: + case FIONCLEX: + case FIONREAD: + case FIONBIO: + case FIOGETOWN: + return (0); + case FIOASYNC: + case FIOSETOWN: + return (EPERM); + + /* tty subsystem */ + case TIOCSWINSZ: /* various programs */ + case TIOCSTI: /* ksh? csh? */ + if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY)) + return (0); + break; + +// /* bpf read operations */ +// case BIOCGSTATS: /* tcpdump privsep on ^C */ +// /* XXX should check type of vnode? */ +// return (0); + + default: + break; + } + + if ((p->p_p->ps_tame & _TM_IOCTL) == 0) + return (EPERM); + + /* + * Further sets of ioctl become available, but are checked a + * bit more carefully against the vnode. + */ + + switch (com) { + 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... */ + if (fp->f_type == DTYPE_VNODE && + (vp->v_type == VCHR || vp->v_type == VBLK)) + return (0); + break; + + case SIOCGIFGROUP: + if ((p->p_p->ps_tame & _TM_INET) && + fp->f_type == DTYPE_SOCKET) + return (0); + break; + + default: + printf("ioctl %lx

", com); + break; + } + return (EPERM); +} + +int +tame_setsockopt_check(struct proc *p, int level, int optname) +{ + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_RTABLE: + return (EPERM); + } + return (0); + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + case TCP_MD5SIG: + case TCP_SACK_ENABLE: + case TCP_MAXSEG: + case TCP_NOPUSH: + return (0); + } + case IPPROTO_IP: + switch (optname) { + case IP_TOS: + case IP_TTL: + case IP_MINTTL: + case IP_PORTRANGE: + case IP_RECVDSTADDR: + return (0); + } + case IPPROTO_ICMP: + break; + case IPPROTO_IPV6: + case IPPROTO_ICMPV6: + break; + } + return (EPERM); +} + +int +tame_dns_check(struct proc *p, in_port_t port) +{ + if ((p->p_p->ps_flags & PS_TAMED) == 0) + return (0); + + if ((p->p_p->ps_tame & _TM_INET)) + return (0); + if ((p->p_p->ps_tame & _TM_DNS_ACTIVE) && port == htons(53)) + return (0); /* Allow a DNS connect outbound */ + return (EPERM); +} Index: sys/kern/kern_time.c =================================================================== RCS file: /cvs/src/sys/kern/kern_time.c,v retrieving revision 1.90 diff -u -p -u -r1.90 kern_time.c --- sys/kern/kern_time.c 28 Apr 2015 20:54:18 -0000 1.90 +++ sys/kern/kern_time.c 26 May 2015 20:12:46 -0000 @@ -40,6 +40,7 @@ #include <sys/ktrace.h> #include <sys/vnode.h> #include <sys/signalvar.h> +#include <sys/tame.h> #include <sys/timetc.h> #include <sys/mount.h> @@ -431,6 +432,9 @@ sys_adjtime(struct proc *p, void *v, reg struct timeval *olddelta = SCARG(uap, olddelta); struct timeval atv; int error; + + if (tame_adjtime_check(p, delta)) + return (EPERM); if (olddelta) { memset(&atv, 0, sizeof(atv)); Index: sys/kern/sys_generic.c =================================================================== RCS file: /cvs/src/sys/kern/sys_generic.c,v retrieving revision 1.98 diff -u -p -u -r1.98 sys_generic.c --- sys/kern/sys_generic.c 10 May 2015 22:35:38 -0000 1.98 +++ sys/kern/sys_generic.c 25 Jun 2015 01:14:53 -0000 @@ -52,6 +52,7 @@ #include <sys/stat.h> #include <sys/malloc.h> #include <sys/poll.h> +#include <sys/tame.h> #ifdef KTRACE #include <sys/ktrace.h> #endif @@ -384,7 +385,7 @@ sys_ioctl(struct proc *p, void *v, regis } */ *uap = v; struct file *fp; struct filedesc *fdp; - u_long com; + u_long com = SCARG(uap, com); int error; u_int size; caddr_t data, memp; @@ -393,10 +394,15 @@ sys_ioctl(struct proc *p, void *v, regis long long stkbuf[STK_PARAMS / sizeof(long long)]; fdp = p->p_fd; - if ((fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE)) == NULL) + fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE); + + if (tame_ioctl_check(p, com, fp)) + return (tame_fail(p, EPERM, _TM_IOCTL)); + + if (fp == NULL) return (EBADF); - switch (com = SCARG(uap, com)) { + switch (com) { case FIONCLEX: case FIOCLEX: fdplock(fdp); Index: sys/kern/syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/syscalls.c,v retrieving revision 1.165 diff -u -p -u -r1.165 syscalls.c --- sys/kern/syscalls.c 6 May 2015 11:26:02 -0000 1.165 +++ sys/kern/syscalls.c 26 May 2015 17:40:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscalls.c,v 1.165 2015/05/06 11:26:02 jsg Exp $ */ +/* $OpenBSD$ */ /* * System call names. @@ -128,7 +128,7 @@ char *syscallnames[] = { "setsockopt", /* 105 = setsockopt */ "listen", /* 106 = listen */ "chflagsat", /* 107 = chflagsat */ - "#108 (obsolete osigvec)", /* 108 = obsolete osigvec */ + "tame", /* 108 = tame */ "ppoll", /* 109 = ppoll */ "pselect", /* 110 = pselect */ "sigsuspend", /* 111 = sigsuspend */ Index: sys/kern/syscalls.master =================================================================== RCS file: /cvs/src/sys/kern/syscalls.master,v retrieving revision 1.153 diff -u -p -u -r1.153 syscalls.master --- sys/kern/syscalls.master 6 May 2015 11:20:07 -0000 1.153 +++ sys/kern/syscalls.master 21 May 2015 22:35:59 -0000 @@ -224,7 +224,7 @@ 106 STD { int sys_listen(int s, int backlog); } 107 STD { int sys_chflagsat(int fd, const char *path, \ u_int flags, int atflags); } -108 OBSOL osigvec +108 STD { int sys_tame(int flags); } 109 STD { int sys_ppoll(struct pollfd *fds, \ u_int nfds, const struct timespec *ts, \ const sigset_t *mask); } Index: sys/kern/uipc_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.103 diff -u -p -u -r1.103 uipc_syscalls.c --- sys/kern/uipc_syscalls.c 17 Jul 2015 15:23:59 -0000 1.103 +++ sys/kern/uipc_syscalls.c 17 Jul 2015 21:35:51 -0000 @@ -45,6 +45,7 @@ #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/signalvar.h> +#include <sys/tame.h> #include <sys/unpcb.h> #include <sys/un.h> #ifdef KTRACE @@ -78,6 +79,9 @@ sys_socket(struct proc *p, void *v, regi int type = SCARG(uap, type); int fd, error; + if (tame_socket_check(p, SCARG(uap, domain))) + return (tame_fail(p, EPERM, _TM_UNIX)); + fdplock(fdp); error = falloc(p, &fp, &fd); if (error == 0 && (type & SOCK_CLOEXEC)) @@ -120,6 +124,9 @@ sys_bind(struct proc *p, void *v, regist struct mbuf *nam; int error; + if (tame_bind_check(p, SCARG(uap, name))) + return (tame_fail(p, EPERM, _TM_UNIX)); + if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), @@ -315,6 +322,9 @@ sys_connect(struct proc *p, void *v, reg struct mbuf *nam = NULL; int error, s; + if (tame_connect_check(p)) + return (tame_fail(p, EPERM, _TM_UNIX)); + if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); so = fp->f_data; @@ -455,6 +465,9 @@ sys_sendto(struct proc *p, void *v, regi struct msghdr msg; struct iovec aiov; + if (tame_sendto_check(p, SCARG(uap, to))) + return (tame_fail(p, EPERM, _TM_UNIX)); + msg.msg_name = (caddr_t)SCARG(uap, to); msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov; @@ -479,6 +492,10 @@ sys_sendmsg(struct proc *p, void *v, reg int error; error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); + + if (tame_sendto_check(p, msg.msg_name)) + return (tame_fail(p, EPERM, _TM_UNIX)); + if (error) return (error); if (msg.msg_iovlen > IOV_MAX) @@ -555,6 +572,11 @@ sendit(struct proc *p, int s, struct msg mp->msg_controllen, MT_CONTROL); if (error) goto bad; + + if (tame_cmsg_send(p, control, mp->msg_controllen)) { + m_free(control); + goto bad; + } } else control = 0; #ifdef KTRACE @@ -609,6 +631,9 @@ sys_recvfrom(struct proc *p, void *v, re struct iovec aiov; int error; + if (tame_recvfrom_check(p, SCARG(uap, from))) + return (tame_fail(p, EPERM, _TM_UNIX)); + if (SCARG(uap, fromlenaddr)) { error = copyin(SCARG(uap, fromlenaddr), &msg.msg_namelen, sizeof (msg.msg_namelen)); @@ -640,6 +665,10 @@ sys_recvmsg(struct proc *p, void *v, reg int error; error = copyin(SCARG(uap, msg), &msg, sizeof (msg)); + + if (tame_recvfrom_check(p, msg.msg_name)) + return (tame_fail(p, EPERM, _TM_UNIX)); + if (error) return (error); if (msg.msg_iovlen > IOV_MAX) @@ -767,6 +796,8 @@ recvit(struct proc *p, int s, struct msg mp->msg_flags |= MSG_CTRUNC; i = len; } + if (tame_cmsg_recv(p, control, mp->msg_controllen)) + goto out; error = copyout(mtod(m, caddr_t), cp, i); if (m->m_next) i = ALIGN(i); @@ -824,6 +855,9 @@ sys_setsockopt(struct proc *p, void *v, struct file *fp; struct mbuf *m = NULL; int error; + + if (tame_setsockopt_check(p, SCARG(uap, level), SCARG(uap, name))) + return (tame_fail(p, EPERM, _TM_INET)); if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); Index: sys/kern/vfs_lookup.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_lookup.c,v retrieving revision 1.53 diff -u -p -u -r1.53 vfs_lookup.c --- sys/kern/vfs_lookup.c 23 Apr 2015 02:55:15 -0000 1.53 +++ sys/kern/vfs_lookup.c 17 Jul 2015 23:27:18 -0000 @@ -51,6 +51,7 @@ #include <sys/proc.h> #include <sys/file.h> #include <sys/fcntl.h> +#include <sys/tame.h> #ifdef KTRACE #include <sys/ktrace.h> @@ -126,6 +127,7 @@ namei(struct nameidata *ndp) error = ENOENT; if (error) { +fail: pool_put(&namei_pool, cnp->cn_pnbuf); ndp->ni_vp = NULL; return (error); @@ -164,6 +166,12 @@ namei(struct nameidata *ndp) */ if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) ndp->ni_rootdir = rootvnode; + if ((p->p_p->ps_flags & PS_TAMED)) { + error = tame_namei(p, cnp->cn_pnbuf); + if (error) + goto fail; + } + /* * Check if starting from root directory or current directory. */ Index: sys/kern/vfs_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.220 diff -u -p -u -r1.220 vfs_syscalls.c --- sys/kern/vfs_syscalls.c 7 May 2015 08:53:33 -0000 1.220 +++ sys/kern/vfs_syscalls.c 14 Jun 2015 19:54:27 -0000 @@ -812,6 +812,16 @@ sys_open(struct proc *p, void *v, regist syscallarg(int) flags; syscallarg(mode_t) mode; } */ *uap = v; + int flags = SCARG(uap, flags); + + switch (flags & O_ACCMODE) { + case O_WRONLY: + case O_RDWR: + p->p_tamenote |= TMN_WRITE; + break; + } + if (flags & O_CREAT) + p->p_tamenote |= TMN_CREAT; return (doopenat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, flags), SCARG(uap, mode), retval)); @@ -1186,6 +1196,7 @@ sys_mknod(struct proc *p, void *v, regis syscallarg(int) dev; } */ *uap = v; + p->p_tamenote |= TMN_IMODIFY; return (domknodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), SCARG(uap, dev))); } @@ -1280,6 +1291,7 @@ sys_mkfifo(struct proc *p, void *v, regi syscallarg(mode_t) mode; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (domknodat(p, AT_FDCWD, SCARG(uap, path), (SCARG(uap, mode) & ALLPERMS) | S_IFIFO, 0)); } @@ -1309,6 +1321,7 @@ sys_link(struct proc *p, void *v, regist syscallarg(const char *) link; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (dolinkat(p, AT_FDCWD, SCARG(uap, path), AT_FDCWD, SCARG(uap, link), AT_SYMLINK_FOLLOW)); } @@ -1382,6 +1395,7 @@ sys_symlink(struct proc *p, void *v, reg syscallarg(const char *) link; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (dosymlinkat(p, SCARG(uap, path), AT_FDCWD, SCARG(uap, link))); } @@ -1442,6 +1456,7 @@ sys_unlink(struct proc *p, void *v, regi syscallarg(const char *) path; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), 0)); } @@ -1835,6 +1850,7 @@ sys_chflags(struct proc *p, void *v, reg syscallarg(u_int) flags; } */ *uap = v; + p->p_tamenote |= TMN_IMODIFY; return (dochflagsat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, flags), 0)); } @@ -1933,6 +1949,7 @@ sys_chmod(struct proc *p, void *v, regis syscallarg(mode_t) mode; } */ *uap = v; + p->p_tamenote |= TMN_IMODIFY; return (dofchmodat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode), 0)); } @@ -2028,6 +2045,7 @@ sys_chown(struct proc *p, void *v, regis syscallarg(gid_t) gid; } */ *uap = v; + p->p_tamenote |= TMN_IMODIFY; return (dofchownat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, uid), SCARG(uap, gid), 0)); } @@ -2111,6 +2129,7 @@ sys_lchown(struct proc *p, void *v, regi uid_t uid = SCARG(uap, uid); gid_t gid = SCARG(uap, gid); + p->p_tamenote |= TMN_IMODIFY; NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); @@ -2207,6 +2226,7 @@ sys_utimes(struct proc *p, void *v, regi const struct timeval *tvp; int error; + p->p_tamenote |= TMN_IMODIFY; tvp = SCARG(uap, tptr); if (tvp != NULL) { error = copyin(tvp, tv, sizeof(tv)); @@ -2402,6 +2422,7 @@ sys_truncate(struct proc *p, void *v, re int error; struct nameidata nd; + p->p_tamenote |= TMN_IMODIFY; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); @@ -2501,6 +2522,7 @@ sys_rename(struct proc *p, void *v, regi syscallarg(const char *) to; } */ *uap = v; + p->p_tamenote |= TMN_IMODIFY; return (dorenameat(p, AT_FDCWD, SCARG(uap, from), AT_FDCWD, SCARG(uap, to))); } @@ -2609,6 +2631,7 @@ sys_mkdir(struct proc *p, void *v, regis syscallarg(mode_t) mode; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (domkdirat(p, AT_FDCWD, SCARG(uap, path), SCARG(uap, mode))); } @@ -2667,6 +2690,7 @@ sys_rmdir(struct proc *p, void *v, regis syscallarg(const char *) path; } */ *uap = v; + p->p_tamenote |= TMN_CREAT; return (dounlinkat(p, AT_FDCWD, SCARG(uap, path), AT_REMOVEDIR)); } @@ -2761,6 +2785,7 @@ sys_revoke(struct proc *p, void *v, regi int error; struct nameidata nd; + p->p_tamenote |= TMN_CREAT; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); Index: sys/netinet/in_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.171 diff -u -p -u -r1.171 in_pcb.c --- sys/netinet/in_pcb.c 15 Jul 2015 22:16:42 -0000 1.171 +++ sys/netinet/in_pcb.c 17 Jul 2015 20:44:57 -0000 @@ -79,6 +79,7 @@ #include <sys/proc.h> #include <sys/domain.h> #include <sys/pool.h> +#include <sys/tame.h> #include <net/if.h> #include <net/if_var.h> @@ -442,6 +443,7 @@ in_pcbconnect(struct inpcb *inp, struct { struct in_addr *ina = NULL; struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *); + struct proc *p = curproc; int error; #ifdef INET6 @@ -457,6 +459,9 @@ in_pcbconnect(struct inpcb *inp, struct return (EAFNOSUPPORT); if (sin->sin_port == 0) return (EADDRNOTAVAIL); + + if (tame_dns_check(p, sin->sin_port)) + return (tame_fail(p, EPERM, TAME_DNS)); error = in_selectsrc(&ina, sin, inp->inp_moptions, &inp->inp_route, &inp->inp_laddr, inp->inp_rtableid); Index: sys/netinet6/in6_pcb.c =================================================================== RCS file: /cvs/src/sys/netinet6/in6_pcb.c,v retrieving revision 1.68 diff -u -p -u -r1.68 in6_pcb.c --- sys/netinet6/in6_pcb.c 8 Jun 2015 22:19:28 -0000 1.68 +++ sys/netinet6/in6_pcb.c 17 Jul 2015 20:45:14 -0000 @@ -108,6 +108,8 @@ #include <sys/socketvar.h> #include <sys/errno.h> #include <sys/time.h> +#include <sys/proc.h> +#include <sys/tame.h> #include <net/if.h> #include <net/if_var.h> @@ -388,6 +390,7 @@ in6_pcbconnect(struct inpcb *inp, struct struct in6_addr *in6a = NULL; struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *); struct ifnet *ifp = NULL; /* outgoing interface */ + struct proc *p = curproc; int error = 0; struct sockaddr_in6 tmp; @@ -399,6 +402,9 @@ in6_pcbconnect(struct inpcb *inp, struct return (EAFNOSUPPORT); if (sin6->sin6_port == 0) return (EADDRNOTAVAIL); + + if (tame_dns_check(p, sin6->sin6_port)) + return (tame_fail(p, EPERM, TAME_DNS)); /* reject IPv4 mapped address, we have no support for it */ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) Index: sys/sys/proc.h =================================================================== RCS file: /cvs/src/sys/sys/proc.h,v retrieving revision 1.199 diff -u -p -u -r1.199 proc.h --- sys/sys/proc.h 10 Feb 2015 05:28:18 -0000 1.199 +++ sys/sys/proc.h 14 Jun 2015 20:14:06 -0000 @@ -214,6 +214,8 @@ struct process { u_short ps_acflag; /* Accounting flags. */ + u_int ps_tame; + /* End area that is copied on creation. */ #define ps_endcopy ps_refcnt int ps_refcnt; /* Number of references. */ @@ -251,13 +253,14 @@ struct process { #define PS_EMBRYO 0x00020000 /* New process, not yet fledged */ #define PS_ZOMBIE 0x00040000 /* Dead and ready to be waited for */ #define PS_NOBROADCASTKILL 0x00080000 /* Process excluded from kill -1. */ +#define PS_TAMED 0x00100000 /* Has called tame(2) */ #define PS_BITS \ ("\20" "\01CONTROLT" "\02EXEC" "\03INEXEC" "\04EXITING" "\05SUGID" \ "\06SUGIDEXEC" "\07PPWAIT" "\010ISPWAIT" "\011PROFIL" "\012TRACED" \ "\013WAITED" "\014COREDUMP" "\015SINGLEEXIT" "\016SINGLEUNWIND" \ "\017NOZOMBIE" "\020STOPPED" "\021SYSTEM" "\022EMBRYO" "\023ZOMBIE" \ - "\024NOBROADCASTKILL") + "\024NOBROADCASTKILL" "\025TAMED") struct proc { @@ -321,6 +324,15 @@ struct proc { u_char p_usrpri; /* User-priority based on p_cpu and ps_nice. */ char p_comm[MAXCOMLEN+1]; + int p_tame_syscall; /* Cache of current syscall */ + int p_tamenote; /* Observance during syscall */ +#define TMN_CREAT 0x00000001 +#define TMN_WRITE 0x00000002 +#define TMN_IMODIFY 0x00000004 +#define TMN_YPLOCK 0x00000008 +#define TMN_DNSRESOLV 0x00000010 + int p_tameafter; + #ifndef __HAVE_MD_TCB void *p_tcb; /* user-space thread-control-block address */ # define TCB_SET(p, addr) ((p)->p_tcb = (addr)) @@ -361,22 +373,22 @@ struct proc { /* * These flags are per-thread and kept in p_flag */ -#define P_INKTR 0x000001 /* In a ktrace op, don't recurse */ -#define P_PROFPEND 0x000002 /* SIGPROF needs to be posted */ -#define P_ALRMPEND 0x000004 /* SIGVTALRM needs to be posted */ -#define P_SIGSUSPEND 0x000008 /* Need to restore before-suspend mask*/ -#define P_CANTSLEEP 0x000010 /* insomniac thread */ -#define P_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */ -#define P_SINTR 0x000080 /* Sleep is interruptible. */ -#define P_SYSTEM 0x000200 /* No sigs, stats or swapping. */ -#define P_TIMEOUT 0x000400 /* Timing out during sleep. */ -#define P_WEXIT 0x002000 /* Working on exiting. */ -#define P_OWEUPC 0x008000 /* Owe proc an addupc() at next ast. */ -#define P_SUSPSINGLE 0x080000 /* Need to stop for single threading. */ -#define P_SYSTRACE 0x400000 /* Process system call tracing active*/ -#define P_CONTINUED 0x800000 /* Proc has continued from a stopped state. */ -#define P_THREAD 0x4000000 /* Only a thread, not a real process */ -#define P_SUSPSIG 0x8000000 /* Stopped from signal. */ +#define P_INKTR 0x00000001 /* In a ktrace op, don't recurse */ +#define P_PROFPEND 0x00000002 /* SIGPROF needs to be posted */ +#define P_ALRMPEND 0x00000004 /* SIGVTALRM needs to be posted */ +#define P_SIGSUSPEND 0x00000008 /* Need to restore before-suspend mask*/ +#define P_CANTSLEEP 0x00000010 /* insomniac thread */ +#define P_SELECT 0x00000040 /* Selecting; wakeup/waiting danger. */ +#define P_SINTR 0x00000080 /* Sleep is interruptible. */ +#define P_SYSTEM 0x00000200 /* No sigs, stats or swapping. */ +#define P_TIMEOUT 0x00000400 /* Timing out during sleep. */ +#define P_WEXIT 0x00002000 /* Working on exiting. */ +#define P_OWEUPC 0x00008000 /* Owe proc an addupc() at next ast. */ +#define P_SUSPSINGLE 0x00080000 /* Need to stop for single threading. */ +#define P_SYSTRACE 0x00400000 /* Process system call tracing active*/ +#define P_CONTINUED 0x00800000 /* Proc has continued from a stopped state. */ +#define P_THREAD 0x04000000 /* Only a thread, not a real process */ +#define P_SUSPSIG 0x08000000 /* Stopped from signal. */ #define P_SOFTDEP 0x10000000 /* Stuck processing softdep worklist */ #define P_CPUPEG 0x40000000 /* Do not move to another cpu. */ Index: sys/sys/syscall.h =================================================================== RCS file: /cvs/src/sys/sys/syscall.h,v retrieving revision 1.164 diff -u -p -u -r1.164 syscall.h --- sys/sys/syscall.h 6 May 2015 11:26:02 -0000 1.164 +++ sys/sys/syscall.h 26 May 2015 17:40:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.164 2015/05/06 11:26:02 jsg Exp $ */ +/* $OpenBSD$ */ /* * System call numbers. @@ -329,7 +329,9 @@ /* syscall: "chflagsat" ret: "int" args: "int" "const char *" "u_int" "int" */ #define SYS_chflagsat 107 - /* 108 is obsolete osigvec */ +/* syscall: "tame" ret: "int" args: "int" */ +#define SYS_tame 108 + /* syscall: "ppoll" ret: "int" args: "struct pollfd *" "u_int" "const struct \ timespec *" "const sigset_t *" */ #define SYS_ppoll 109 Index: sys/sys/syscall_mi.h =================================================================== RCS file: /cvs/src/sys/sys/syscall_mi.h,v retrieving revision 1.5 diff -u -p -u -r1.5 syscall_mi.h --- sys/sys/syscall_mi.h 11 May 2014 00:12:44 -0000 1.5 +++ sys/sys/syscall_mi.h 18 Jul 2015 00:02:54 -0000 @@ -33,6 +33,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/tame.h> #include <sys/proc.h> #ifdef KTRACE @@ -53,7 +54,7 @@ mi_syscall(struct proc *p, register_t co register_t *argp, register_t retval[2]) { int lock = !(callp->sy_flags & SY_NOLOCK); - int error; + int error, tamed, tval; /* refresh the thread's cache of the process's creds */ refreshcreds(p); @@ -76,15 +77,27 @@ mi_syscall(struct proc *p, register_t co KERNEL_LOCK(); error = systrace_redirect(code, p, argp, retval); KERNEL_UNLOCK(); - } else + return (error); + } #endif - { - if (lock) + + if (lock) + KERNEL_LOCK(); + tamed = (p->p_p->ps_flags & PS_TAMED); + if (tamed && !(tval = tame_check(p, code))) { + if (!lock) KERNEL_LOCK(); - error = (*callp->sy_call)(p, argp, retval); - if (lock) + error = tame_fail(p, EPERM, tval); + if (!lock) KERNEL_UNLOCK(); + } + else { + error = (*callp->sy_call)(p, argp, retval); + if (tamed && p->p_tameafter) + tame_aftersyscall(p, code, error); } + if (lock) + KERNEL_UNLOCK(); return (error); } Index: sys/sys/syscallargs.h =================================================================== RCS file: /cvs/src/sys/sys/syscallargs.h,v retrieving revision 1.166 diff -u -p -u -r1.166 syscallargs.h --- sys/sys/syscallargs.h 6 May 2015 11:26:02 -0000 1.166 +++ sys/sys/syscallargs.h 26 May 2015 17:40:00 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: syscallargs.h,v 1.166 2015/05/06 11:26:02 jsg Exp $ */ +/* $OpenBSD$ */ /* * System call argument lists. @@ -538,6 +538,10 @@ struct sys_chflagsat_args { syscallarg(int) atflags; }; +struct sys_tame_args { + syscallarg(int) flags; +}; + struct sys_ppoll_args { syscallarg(struct pollfd *) fds; syscallarg(u_int) nfds; @@ -1189,6 +1193,7 @@ int sys_bind(struct proc *, void *, regi int sys_setsockopt(struct proc *, void *, register_t *); int sys_listen(struct proc *, void *, register_t *); int sys_chflagsat(struct proc *, void *, register_t *); +int sys_tame(struct proc *, void *, register_t *); int sys_ppoll(struct proc *, void *, register_t *); int sys_pselect(struct proc *, void *, register_t *); int sys_sigsuspend(struct proc *, void *, register_t *); Index: sys/sys/tame.h =================================================================== RCS file: sys/sys/tame.h diff -N sys/sys/tame.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/sys/tame.h 18 Jul 2015 20:52:00 -0000 @@ -0,0 +1,89 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_TAME_H_ +#define _SYS_TAME_H_ + +#include <sys/cdefs.h> + +#define _TM_SELF 0x00000001 /* operate on own pid */ +#define _TM_RW 0x00000002 /* basic io operations */ +#define _TM_MALLOC 0x00000004 /* enough for malloc */ +#define _TM_DNSPATH 0x00000008 /* access to DNS pathnames */ +#define _TM_RPATH 0x00000010 /* allow open for read */ +#define _TM_WPATH 0x00000020 /* allow open for write */ +#define _TM_TMPPATH 0x00000040 /* for mk*temp() */ +#define _TM_INET 0x00000080 /* AF_INET/AF_INET6 sockets */ +#define _TM_UNIX 0x00000100 /* AF_UNIX sockets */ +#define _TM_CMSG 0x00000200 /* AF_UNIX CMSG fd passing */ +#define _TM_IOCTL 0x00000400 /* scary */ +#define _TM_GETPW 0x00000800 /* enough to enable YP */ +#define _TM_PROC 0x00001000 /* fork, waitpid, etc */ +#define _TM_CPATH 0x00002000 /* allow create, mkdir, or inode mods */ + +#define _TM_ABORT 0x08000000 /* SIGABRT instea of SIGKILL */ + +/* Following flags are set by kernel, as it learns things. + * Not user settable. Should be moved to a seperate variable */ +#define _TM_USERSET 0x0fffffff +#define _TM_YP_ACTIVE 0x10000000 /* YP use detected and allowed */ +#define _TM_DNS_ACTIVE 0x20000000 /* DNS use detected and allowed */ + +#define TAME_MALLOC (_TM_SELF | _TM_MALLOC) +#define TAME_RW (_TM_SELF | _TM_RW) +#define TAME_STDIO (_TM_SELF | _TM_MALLOC | _TM_RW) +#define TAME_RPATH (_TM_SELF | _TM_RW | _TM_RPATH) +#define TAME_WPATH (_TM_SELF | _TM_RW | _TM_WPATH) +#define TAME_TMPPATH (_TM_SELF | _TM_RW | _TM_TMPPATH) +#define TAME_INET (_TM_SELF | _TM_RW | _TM_INET) +#define TAME_UNIX (_TM_SELF | _TM_RW | _TM_UNIX) +#define TAME_CMSG (TAME_UNIX | _TM_CMSG) +#define TAME_DNS (TAME_MALLOC | _TM_DNSPATH) +#define TAME_IOCTL (_TM_IOCTL) +#define TAME_GETPW (TAME_STDIO | _TM_GETPW) +#define TAME_PROC (_TM_PROC) +#define TAME_CPATH (_TM_CPATH) +#define TAME_ABORT (_TM_ABORT) + +#ifdef _KERNEL + +int tame_check(struct proc *, int); +int tame_fail(struct proc *, int, int); +int tame_namei(struct proc *, char *); +void tame_aftersyscall(struct proc *, int, int); + +int tame_cmsg_send(struct proc *p, void *v, int controllen); +int tame_cmsg_recv(struct proc *p, void *v, int controllen); +int tame_sysctl_check(struct proc *p, int namelen, int *name, void *new); +int tame_adjtime_check(struct proc *p, const void *v); +int tame_recvfrom_check(struct proc *p, void *from); +int tame_sendto_check(struct proc *p, const void *to); +int tame_bind_check(struct proc *p, const void *v); +int tame_connect_check(struct proc *p); +int tame_socket_check(struct proc *p, int domain); +int tame_setsockopt_check(struct proc *p, int level, int optname); +int tame_dns_check(struct proc *p, in_port_t port); +int tame_ioctl_check(struct proc *p, long com, void *); + +#else /* _KERNEL */ + +int tame(int); + +#endif /* _KERNEL */ + +#endif /* _SYS_TAME_H_ */ Index: bin/cat/cat.c =================================================================== RCS file: /cvs/src/bin/cat/cat.c,v retrieving revision 1.21 diff -u -p -u -r1.21 cat.c --- bin/cat/cat.c 16 Jan 2015 06:39:28 -0000 1.21 +++ bin/cat/cat.c 24 May 2015 01:03:25 -0000 @@ -35,6 +35,7 @@ #include <sys/types.h> #include <sys/stat.h> +#include <sys/tame.h> #include <ctype.h> #include <err.h> @@ -65,6 +66,8 @@ main(int argc, char *argv[]) int ch; setlocale(LC_ALL, ""); + + tame(TAME_STDIO | TAME_RPATH); while ((ch = getopt(argc, argv, "benstuv")) != -1) switch (ch) { Index: bin/pax/pax.c =================================================================== RCS file: /cvs/src/bin/pax/pax.c,v retrieving revision 1.41 diff -u -p -u -r1.41 pax.c --- bin/pax/pax.c 9 Mar 2015 04:23:29 -0000 1.41 +++ bin/pax/pax.c 4 Jun 2015 20:54:58 -0000 @@ -38,6 +38,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/tame.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> @@ -255,6 +256,10 @@ main(int argc, char **argv) options(argc, argv); if ((gen_init() < 0) || (tty_init() < 0)) return(exit_val); + + if (gzip_program == NULL) + tame(TAME_STDIO | TAME_GETPW | TAME_IOCTL | TAME_PROC | + TAME_CPATH | TAME_WPATH | TAME_RPATH); /* * select a primary operation mode Index: bin/ps/print.c =================================================================== RCS file: /cvs/src/bin/ps/print.c,v retrieving revision 1.61 diff -u -p -u -r1.61 print.c --- bin/ps/print.c 29 Jun 2015 15:03:33 -0000 1.61 +++ bin/ps/print.c 14 Jul 2015 18:35:53 -0000 @@ -269,6 +269,8 @@ state(const struct kinfo_proc *kp, VAREN *cp++ = 's'; if ((kp->p_psflags & PS_CONTROLT) && kp->p__pgid == kp->p_tpgid) *cp++ = '+'; + if (kp->p_psflags & PS_TAMED) + *cp++ = 't'; *cp = '\0'; if (state == 'R' && kp->p_cpuid != KI_NOCPU) { Index: bin/ps/ps.1 =================================================================== RCS file: /cvs/src/bin/ps/ps.1,v retrieving revision 1.99 diff -u -p -u -r1.99 ps.1 --- bin/ps/ps.1 29 Jun 2015 15:03:33 -0000 1.99 +++ bin/ps/ps.1 14 Jul 2015 18:35:53 -0000 @@ -341,6 +341,7 @@ PS_SYSTEM 0x10000 No signals, s PS_EMBRYO 0x20000 New process, not yet fledged PS_ZOMBIE 0x40000 Dead and ready to be waited for PS_NOBROADCASTKILL 0x80000 Process excluded from kill -1 +PS_TAMED 0x100000 process has called tame(2) .Ed .It Cm re Core residency time (in seconds; 127 = infinity). @@ -463,6 +464,9 @@ scheduling priority. .\" sequentially address voluminous data). .It s The process is a session leader. +.It t +The process has called +.Xr tame 2 . .It V The process is suspended during a .Xr vfork 2 . Index: lib/libc/sys/Makefile.inc =================================================================== RCS file: /cvs/src/lib/libc/sys/Makefile.inc,v retrieving revision 1.125 diff -u -p -u -r1.125 Makefile.inc --- lib/libc/sys/Makefile.inc 7 Apr 2015 01:27:07 -0000 1.125 +++ lib/libc/sys/Makefile.inc 21 May 2015 22:35:59 -0000 @@ -56,7 +56,7 @@ ASM= __get_tcb.o __getcwd.o __semctl.o _ settimeofday.o setuid.o shmat.o shmctl.o shmdt.o \ shmget.o shutdown.o sigaction.o sigaltstack.o socket.o \ socketpair.o stat.o statfs.o swapctl.o symlink.o \ - symlinkat.o sync.o sysarch.o umask.o unlink.o unlinkat.o \ + symlinkat.o sync.o sysarch.o tame.o umask.o unlink.o unlinkat.o \ unmount.o utimensat.o utimes.o utrace.o wait4.o write.o writev.o SRCS+= ${SRCS_${MACHINE_CPU}} @@ -218,7 +218,7 @@ MAN+= __get_tcb.2 __thrsigdivert.2 __thr shmctl.2 shmget.2 shutdown.2 sigaction.2 sigaltstack.2 sigpending.2 \ sigprocmask.2 sigreturn.2 sigsuspend.2 socket.2 \ socketpair.2 stat.2 statfs.2 swapctl.2 symlink.2 \ - sync.2 sysarch.2 syscall.2 truncate.2 umask.2 unlink.2 \ + sync.2 sysarch.2 syscall.2 tame.2 truncate.2 umask.2 unlink.2 \ utimes.2 utrace.2 vfork.2 wait.2 write.2 MLINKS+=__get_tcb.2 __set_tcb.2 Index: lib/libc/sys/tame.2 =================================================================== RCS file: lib/libc/sys/tame.2 diff -N lib/libc/sys/tame.2 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/libc/sys/tame.2 18 Jul 2015 22:16:20 -0000 @@ -0,0 +1,381 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate$ +.Dt TAME 2 +.Os +.Sh NAME +.Nm tame +.Nd restrict system operations +.Sh SYNOPSIS +.In sys/tame.h +.Ft int +.Fn tame "int flags" +.Sh DESCRIPTION +The current process is forced into a restricted-service operating mode. +A few subsets are available, roughly described as computation, memory +management, read-write operations on file descriptors, opening of files, +networking. In general, these modes were selected by studying the operation +of many programs using libc and other such interfaces. +.Pp +Use of +.Nm tame +in an application will require at least some study and understanding +of the interfaces called. +.Pp +Subsequent calls to +.Fn tame +can reduce abilities further, but abilities can never be regained. +.Pp +A process which attempts a restricted operation is killed with +.Dv SIGKILL . +If +.Va TAME_ABORT +is set, then a non-blockable SIGABRT is delivered instead, possibly +resulting in a +.Xr core 5 +file. +.Pp +A +.Fa flags +value of 0 restricts the process to the +.Xr _exit 2 +system call. +This can be used for pure computation operating on memory shared +with another process. +.Pp +All +.Ar TAME_* +options below (with the exception of +.Ar TAME_ABORT ) +permit the following system calls: +.Pp +.Bd -ragged -offset indent +.Xr clock_getres 2 , +.Xr clock_gettime 2 , +.Xr fchdir 2 , +.Xr getdtablecount 2 , +.Xr getegid 2 , +.Xr geteuid 2 , +.Xr getgid 2 , +.Xr getgroups 2 , +.Xr getitimer 2 , +.Xr getlogin 2 , +.Xr getpgid 2 , +.Xr getpgrp 2 , +.Xr getpid 2 , +.Xr getppid 2 , +.Xr getresgid 2 , +.Xr getresuid 2 , +.Xr getrlimit 2 , +.Xr getsid 2 , +.Xr getthrid 2 , +.Xr gettimeofday 2 , +.Xr getuid 2 , +.Xr getuid 2 , +.Xr issetugid 2 , +.Xr nanosleep 2 , +.Xr sendsyslog 2 , +.Xr setitimer 2 , +.Xr sigaction 2 , +.Xr sigprocmask 2 , +.Xr sigreturn 2 , +.Xr umask 2 , +.Xr wait4 2 . +.Ed +.Pp +Calls allowed with restrictions include: +.Bl -tag -width TAME_TMPPATH -offset indent -compact +.It Xr sysctl 3 +A small set of read-only operations are allowed, sufficient to +support: +.Xr getifaddrs 3 , +.Xr getdomainname 3 , +.Xr gethostname 3 , +system sensor readings. +.It Xr access 2 +May check for existance of +.Pa /etc/localtime . +.It Xr adjtime 2 +Read-only, for +.Xr ntpd 8 . +.It Xr open 2 +May open +.Pa /etc/localtime , +any files below +.Pa /usr/share/zoneinfo +and files ending in +.Pa libc.cat +in below the directory +.Pa /usr/share/nls/ . +.It Xr readlink 2 +May operate on +.Pa /etc/malloc.conf . +.It Xr tame 2 +Can only reduce permissions. +.El +.Pp +The +.Ar flags +are specified as a bitwise OR of the following values: +.Bl -tag -width TAME_TMPPATH -offset indent -compact +.Pp +.It Ar TAME_MALLOC +To allow use of the +.Xr malloc 3 +family of functions, the following system calls are permitted: +.Pp +.Xr getentropy 2 , +.Xr madvise 2 , +.Xr minherit 2 , +.Xr mmap 2 , +.Xr mprotect 2 , +.Xr mquery 2 , +.Xr munmap 2 . +.Pp +.It Ar TAME_RW +The following system calls are permitted to allow most types of IO +operations on previously allocated file descriptors, including +libevent or handwritten async IO loops: +.Pp +.Xr poll 2 , +.Xr kevent 2 , +.Xr kqueue 2 , +.Xr select 2 , +.Xr close 2 , +.Xr dup 2 , +.Xr dup2 2 , +.Xr dup3 2 , +.Xr closefrom 2 , +.Xr shutdown 2 , +.Xr read 2 , +.Xr readv 2 , +.Xr pread 2 , +.Xr preadv 2 , +.Xr write 2 , +.Xr writev 2 , +.Xr pwrite 2 , +.Xr pwritev 2 , +.Xr ftruncate 2 , +.Xr lseek 2 , +.Xr utimes 2 , +.Xr futimes 2 , +.Xr utimensat 2 , +.Xr futimens 2 , +.Xr fcntl 2 , +.Xr fsync 2 , +.Xr pipe 2 , +.Xr pipe2 2 , +.Xr socketpair 2 , +.Xr getdents 2 , +.Xr sendto 2 , +.Xr sendmsg 2 , +.Xr recvmsg 2 , +.Xr recvfrom 2 , +.Xr fstat 2 . +.Pp +.It Ar TAME_STDIO +This subset is simply the combination of +.Ar TAME_MALLOC +and +.Ar TAME_RW . +As a result, all functionalities of libc +stdio works. +.Pp +.It Ar TAME_RPATH +A number of system calls are allowed if they only cause +read-only effects on the filesystem: +.Pp +.Xr chdir 2 , +.Xr getcwd 3 , +.Xr openat 2 , +.Xr fstatat 2 , +.Xr faccessat 2 , +.Xr readlinkat 2 , +.Xr lstat 2 , +.Xr chmod 2 , +.Xr fchmod 2 , +.Xr fchmodat 2 , +.Xr chflags 2 , +.Xr chflagsat 2 , +.Xr chown 2 , +.Xr fchown 2 , +.Xr fchownat 2 , +.Xr fstat 2 . +.Pp +.It Ar TAME_WPATH +A number of system calls are allowed and may cause +write-effects on the filesystem: +read-only effects: +.Pp +.Xr getcwd 3 , +.Xr openat 2 , +.Xr fstatat 2 , +.Xr faccessat 2 , +.Xr readlinkat 2 , +.Xr lstat 2 , +.Xr chmod 2 , +.Xr fchmod 2 , +.Xr fchmodat 2 , +.Xr chflags 2 , +.Xr chflagsat 2 , +.Xr chown 2 , +.Xr fchown 2 , +.Xr fchownat 2 , +.Xr fstat 2 , +.Xr fstat 2 . +.Pp +.It Ar TAME_TMPPATH +A number of system calls are allowed to do operations in the +.Pa /tmp +directory, including create, read, or write: +.Pp +.Xr lstat 2 , +.Xr chmod 2 , +.Xr chflags 2 , +.Xr chown 2 , +.Xr unlink 2 , +.Xr fstat 2 . +.Pp +.It Ar TAME_CPATH +A number of system calls and sub-modes are allowed, which may +create new files or directories in the filesystem: +.Pp +.Xr rename 2 , +.Xr rmdir 2 , +.Xr renameat 2 , +.Xr link 2 , +.Xr linkat 2 , +.Xr symlink 2 , +.Xr unlink 2 , +.Xr unlinkat 2 , +.Xr mkdir 2 , +.Xr mkdirat 2 . +.Pp +.It Ar TAME_INET +The following system calls are allowed to operate in the +.Ar AF_INET +and +.Ar AF_INET6 +domains: +.Pp +.Xr socket 2 , +.Xr listen 2 , +.Xr bind 2 , +.Xr connect 2 , +.Xr accept4 2 , +.Xr accept 2 , +.Xr getpeername 2 , +.Xr getsockname 2 , +.Xr setsockopt 2 , +.Xr getsockopt 2 . +.Pp +.Xr setsockopt 2 +has been reduced in functionality substantially. +.It Ar TAME_UNIX +The following system calls are allowed to operate in the +.Ar AF_UNIX +domain: +.Pp +.Xr socket 2 , +.Xr listen 2 , +.Xr bind 2 , +.Xr connect 2 , +.Xr accept4 2 , +.Xr accept 2 , +.Xr getpeername 2 , +.Xr getsockname 2 , +.Xr setsockopt 2 , +.Xr getsockopt 2 . +.Pp +.It Ar TAME_DNSPATH +Subsequent to a succesfull +.Xr open 2 +of +.Pa /etc/resolv.conf , +a few system calls become to allow DNS network transactions: +.Pp +.Xr sendto 2 , +.Xr recvfrom 2 , +.Xr socket 2 , +.Xr connect 2 . +.Pp +.It Ar TAME_GETPW +This allows read-only opening of files in +.Pa /etc +for the +.Xr getpwnam 3 , +.Xr getgrnam 3, +.Xr getgrouplist 3 , +and +.Xr initgroups 3 +family of functions. +They may also need to operate in a +.Xr yp 8 +environment, so a succesfull +.Xr open 2 +of +.Pa /var/run/ypbind.lock +enables the +.Ar TAME_INET +flag. +.Pp +.It Ar TAME_CMSG +Allows passing of file descriptors using the +.Xr sendmsg 2 +and +.Xr recvmsg 2 +functions. +.Pp +.It Ar TAME_IOCTL +Allows a subset of +.Xr ioctl 2 +operations: +.Pp +.Va FIOCLEX , +.Va FIONCLEX , +.Va FIONREAD , +.Va FIONBIO , +.Va FIOGETOWN , +.Va TIOCSWINSZ , +.Va TIOCSTI . +.Pp +.It Ar TAME_PROC +Allows the following process relationship operations: +.Pp +.Xr fork 2 , +.Xr vfork 2 , +.Xr kill 2 , +.Xr setresgid 2 , +.Xr SYS_setresuid 2 , +.Pp +.It Ar TAME_ABORT +Deliver an unblockable SIGABRT upon violation instead of SIGKILL. +.El +.Sh RETURN VALUES +.Rv -std +.Sh ERRORS +.Fn tame +will fail if: +.Bl -tag -width Er +.It Bq Er EPERM +This process is attempting to increase permissions. +.El +.Sh HISTORY +The +.Fn tame +system call appeared in +.Ox 5.8 . Index: regress/etc/Makefile =================================================================== RCS file: /cvs/src/regress/etc/Makefile,v retrieving revision 1.2 diff -u -p -u -r1.2 Makefile --- regress/etc/Makefile 23 Feb 2002 01:25:10 -0000 1.2 +++ regress/etc/Makefile 28 May 2015 23:12:08 -0000 @@ -1,6 +1,6 @@ # $OpenBSD: Makefile,v 1.2 2002/02/23 01:25:10 art Exp $ -SUBDIR+= MAKEDEV +#SUBDIR+= MAKEDEV install: Index: regress/sys/kern/Makefile =================================================================== RCS file: /cvs/src/regress/sys/kern/Makefile,v retrieving revision 1.63 diff -u -p -u -r1.63 Makefile --- regress/sys/kern/Makefile 10 Feb 2015 00:45:31 -0000 1.63 +++ regress/sys/kern/Makefile 15 Jun 2015 01:22:40 -0000 @@ -14,7 +14,7 @@ SUBDIR+= rlimit-file signal signal-stres SUBDIR+= sosplice SUBDIR+= syscall sysvmsg sysvsem SUBDIR+= sysvshm unalign unfdpass wait -SUBDIR+= sig-stop +#SUBDIR+= sig-stop SUBDIR+= unixsock bind install: Index: regress/usr.bin/signify/Makefile =================================================================== RCS file: /cvs/src/regress/usr.bin/signify/Makefile,v retrieving revision 1.4 diff -u -p -u -r1.4 Makefile --- regress/usr.bin/signify/Makefile 17 Mar 2014 02:49:02 -0000 1.4 +++ regress/usr.bin/signify/Makefile 15 Jun 2015 00:55:33 -0000 @@ -4,7 +4,7 @@ CLEANFILES += test.sig confirmorders con REGRESS_TARGETS = t1 t1: - @sh ${.CURDIR}/signify.sh ${.CURDIR} + sh ${.CURDIR}/signify.sh ${.CURDIR} .PHONY: t1 Index: sbin/dmesg/dmesg.c =================================================================== RCS file: /cvs/src/sbin/dmesg/dmesg.c,v retrieving revision 1.25 diff -u -p -u -r1.25 dmesg.c --- sbin/dmesg/dmesg.c 16 Jan 2015 06:39:57 -0000 1.25 +++ sbin/dmesg/dmesg.c 28 May 2015 08:58:51 -0000 @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/msgbuf.h> #include <sys/sysctl.h> +#include <sys/tame.h> #include <err.h> #include <fcntl.h> @@ -107,6 +108,8 @@ main(int argc, char *argv[]) len = msgbufsize; if (sysctl(mib, 2, bufdata, &len, NULL, 0)) err(1, "sysctl: KERN_MSGBUF"); + + tame(TAME_STDIO); memcpy(&cur, bufdata, sizeof(cur)); bufdata = ((struct msgbuf *)bufdata)->msg_bufc; Index: sbin/ping/ping.c =================================================================== RCS file: /cvs/src/sbin/ping/ping.c,v retrieving revision 1.123 diff -u -p -u -r1.123 ping.c --- sbin/ping/ping.c 2 May 2015 18:03:37 -0000 1.123 +++ sbin/ping/ping.c 26 May 2015 21:25:52 -0000 @@ -55,6 +55,7 @@ #include <sys/queue.h> #include <sys/socket.h> #include <sys/time.h> +#include <sys/tame.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -347,15 +348,6 @@ main(int argc, char *argv[]) if (argc != 1) usage(); - arc4random_buf(&tv64_offset, sizeof(tv64_offset)); - arc4random_buf(&mac_key, sizeof(mac_key)); - - memset(&interstr, 0, sizeof(interstr)); - - interstr.it_value.tv_sec = interval; - interstr.it_value.tv_usec = - (long) ((interval - interstr.it_value.tv_sec) * 1000000); - target = *argv; memset(&whereto, 0, sizeof(whereto)); @@ -374,6 +366,33 @@ main(int argc, char *argv[]) hostname = hnamebuf; } + if (options & F_SADDR) { + if (IN_MULTICAST(ntohl(to->sin_addr.s_addr))) + moptions |= MULTICAST_IF; + else { + memset(&whence, 0, sizeof(whence)); + whence.sin_len = sizeof(whence); + whence.sin_family = AF_INET; + memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr)); + if (bind(s, (struct sockaddr *)&whence, + sizeof(whence)) < 0) + err(1, "bind"); + } + } + + if (options & F_SO_DEBUG) + (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &optval, + sizeof(optval)); + + arc4random_buf(&tv64_offset, sizeof(tv64_offset)); + arc4random_buf(&mac_key, sizeof(mac_key)); + + memset(&interstr, 0, sizeof(interstr)); + + interstr.it_value.tv_sec = interval; + interstr.it_value.tv_usec = + (long) ((interval - interstr.it_value.tv_sec) * 1000000); + if (options & F_FLOOD && options & F_INTERVAL) errx(1, "-f and -i options are incompatible"); @@ -393,24 +412,6 @@ main(int argc, char *argv[]) ident = getpid() & 0xFFFF; - if (options & F_SADDR) { - if (IN_MULTICAST(ntohl(to->sin_addr.s_addr))) - moptions |= MULTICAST_IF; - else { - memset(&whence, 0, sizeof(whence)); - whence.sin_len = sizeof(whence); - whence.sin_family = AF_INET; - memcpy(&whence.sin_addr.s_addr, &saddr, sizeof(saddr)); - if (bind(s, (struct sockaddr *)&whence, - sizeof(whence)) < 0) - err(1, "bind"); - } - } - - if (options & F_SO_DEBUG) - (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &optval, - sizeof(optval)); - if (options & F_TTL) { if (IN_MULTICAST(ntohl(to->sin_addr.s_addr))) moptions |= MULTICAST_TTL; @@ -500,6 +501,11 @@ main(int argc, char *argv[]) datalen); else (void)printf("PING %s: %d data bytes

", hostname, datalen); + + if (options & F_NUMERIC) + tame(TAME_STDIO | TAME_INET); + else + tame(TAME_STDIO | TAME_INET | TAME_DNS); (void)signal(SIGINT, finish); (void)signal(SIGALRM, catcher); Index: sbin/ping6/ping6.c =================================================================== RCS file: /cvs/src/sbin/ping6/ping6.c,v retrieving revision 1.108 diff -u -p -u -r1.108 ping6.c --- sbin/ping6/ping6.c 2 May 2015 17:19:42 -0000 1.108 +++ sbin/ping6/ping6.c 26 May 2015 21:26:23 -0000 @@ -83,6 +83,7 @@ #include <sys/types.h> #include <sys/uio.h> #include <sys/socket.h> +#include <sys/tame.h> #include <net/if.h> #include <net/route.h> @@ -772,6 +773,11 @@ main(int argc, char *argv[]) close(dummy); } + + if (options & F_HOSTNAME) + tame(TAME_INET | TAME_DNS); + else + tame(TAME_INET); if (sockbufsize) { if (datalen > sockbufsize) Index: usr.bin/dc/dc.c =================================================================== RCS file: /cvs/src/usr.bin/dc/dc.c,v retrieving revision 1.13 diff -u -p -u -r1.13 dc.c --- usr.bin/dc/dc.c 26 Nov 2014 18:34:51 -0000 1.13 +++ usr.bin/dc/dc.c 26 May 2015 19:28:31 -0000 @@ -48,6 +48,9 @@ main(int argc, char *argv[]) struct stat st; +#include <sys/tame.h> + tame(TAME_STDIO | TAME_RW); + if ((buf = strdup("")) == NULL) err(1, NULL); /* accept and ignore a single dash to be 4.4BSD dc(1) compatible */ Index: usr.bin/diff/diff.c =================================================================== RCS file: /cvs/src/usr.bin/diff/diff.c,v retrieving revision 1.59 diff -u -p -u -r1.59 diff.c --- usr.bin/diff/diff.c 29 Apr 2015 04:00:25 -0000 1.59 +++ usr.bin/diff/diff.c 5 Jun 2015 00:07:31 -0000 @@ -21,6 +21,7 @@ */ #include <sys/stat.h> +#include <sys/tame.h> #include <ctype.h> #include <err.h> @@ -216,6 +217,9 @@ main(int argc, char **argv) } argc -= optind; argv += optind; + + if (lflag == 0) + tame(TAME_STDIO | TAME_WPATH | TAME_RPATH | TAME_TMPPATH); /* * Do sanity checks, fill in stb1 and stb2 and call the appropriate Index: usr.bin/finger/finger.c =================================================================== RCS file: /cvs/src/usr.bin/finger/finger.c,v retrieving revision 1.19 diff -u -p -u -r1.19 finger.c --- usr.bin/finger/finger.c 16 Jan 2015 06:40:07 -0000 1.19 +++ usr.bin/finger/finger.c 25 May 2015 21:51:46 -0000 @@ -58,6 +58,7 @@ #include <sys/file.h> #include <sys/stat.h> +#include <sys/tame.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -125,6 +126,8 @@ main(int argc, char *argv[]) if (sb.st_size > 1048576) mflag++; } + + tame(TAME_STDIO | TAME_GETPW | TAME_RPATH); (void)time(&now); setpassent(1); Index: usr.bin/from/from.c =================================================================== RCS file: /cvs/src/usr.bin/from/from.c,v retrieving revision 1.20 diff -u -p -u -r1.20 from.c --- usr.bin/from/from.c 3 Jun 2015 18:08:54 -0000 1.20 +++ usr.bin/from/from.c 3 Jun 2015 19:15:43 -0000 @@ -31,6 +31,7 @@ */ #include <sys/types.h> +#include <sys/tame.h> #include <ctype.h> #include <pwd.h> #include <stdio.h> @@ -74,12 +75,14 @@ main(int argc, char *argv[]) } argv += optind; + tame(TAME_STDIO | TAME_RPATH); file = mail_spool(file, *argv); if ((fp = fopen(file, "r")) == NULL) { if (!fflag && errno == ENOENT) exit(EXIT_SUCCESS); err(1, "%s", file); } + tame(TAME_STDIO); for (newline = 1; (linelen = getline(&line, &linesize, fp)) != -1;) { if (*line == '

') { newline = 1; @@ -98,6 +101,8 @@ char * mail_spool(char *file, const char *user) { struct passwd *pwd; + + tame(TAME_STDIO | TAME_RPATH | TAME_GETPW); /* * We find the mailbox by: Index: usr.bin/id/id.c =================================================================== RCS file: /cvs/src/usr.bin/id/id.c,v retrieving revision 1.23 diff -u -p -u -r1.23 id.c --- usr.bin/id/id.c 19 May 2015 16:03:19 -0000 1.23 +++ usr.bin/id/id.c 26 May 2015 19:19:45 -0000 @@ -29,6 +29,7 @@ * SUCH DAMAGE. */ +#include <sys/tame.h> #include <err.h> #include <errno.h> #include <grp.h> @@ -104,6 +105,8 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; + + tame(TAME_STDIO | TAME_GETPW); switch (cflag + Gflag + gflag + pflag + uflag) { case 1: Index: usr.bin/kdump/kdump.c =================================================================== RCS file: /cvs/src/usr.bin/kdump/kdump.c,v retrieving revision 1.101 diff -u -p -u -r1.101 kdump.c --- usr.bin/kdump/kdump.c 18 Apr 2015 18:28:37 -0000 1.101 +++ usr.bin/kdump/kdump.c 25 Jun 2015 01:33:20 -0000 @@ -46,6 +46,7 @@ #include <sys/vmmeter.h> #include <sys/tty.h> #include <sys/wait.h> +#include <sys/tame.h> #define _KERNEL #include <errno.h> #undef _KERNEL @@ -164,6 +165,8 @@ static void clockname(int); static void sockoptlevelname(int); static void ktraceopname(int); +static int screenwidth; + int main(int argc, char *argv[]) { @@ -175,6 +178,16 @@ main(int argc, char *argv[]) def_emul = current = &emulations[0]; /* native */ + if (screenwidth == 0) { + struct winsize ws; + + if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && + ws.ws_col > 8) + screenwidth = ws.ws_col; + else + screenwidth = 80; + } + while ((ch = getopt(argc, argv, "e:f:dHlm:nRp:Tt:xX")) != -1) switch (ch) { case 'e': @@ -229,6 +242,8 @@ main(int argc, char *argv[]) if (argc > optind) usage(); + tame(TAME_MALLOC | TAME_RPATH); + m = malloc(size = 1025); if (m == NULL) err(1, NULL); @@ -1177,19 +1192,9 @@ static void showbuf(unsigned char *dp, size_t datalen) { int i, j; - static int screenwidth; int col = 0, width, bpl; unsigned char visbuf[5], *cp, c; - if (screenwidth == 0) { - struct winsize ws; - - if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && - ws.ws_col > 8) - screenwidth = ws.ws_col; - else - screenwidth = 80; - } if (iohex == 1) { putchar('\t'); col = 8; Index: usr.bin/logger/logger.c =================================================================== RCS file: /cvs/src/usr.bin/logger/logger.c,v retrieving revision 1.14 diff -u -p -u -r1.14 logger.c --- usr.bin/logger/logger.c 18 Apr 2015 18:28:37 -0000 1.14 +++ usr.bin/logger/logger.c 3 Jun 2015 17:36:15 -0000 @@ -30,6 +30,7 @@ * SUCH DAMAGE. */ +#include <sys/tame.h> #include <errno.h> #include <unistd.h> #include <limits.h> @@ -91,6 +92,8 @@ main(int argc, char *argv[]) /* setup for logging */ openlog(tag ? tag : getlogin(), logflags, 0); (void) fclose(stdout); + + tame(TAME_STDIO); /* log input line if appropriate */ if (argc > 0) { Index: usr.bin/script/script.c =================================================================== RCS file: /cvs/src/usr.bin/script/script.c,v retrieving revision 1.26 diff -u -p -u -r1.26 script.c --- usr.bin/script/script.c 15 Mar 2015 00:41:28 -0000 1.26 +++ usr.bin/script/script.c 3 Jun 2015 01:20:42 -0000 @@ -60,6 +60,7 @@ #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/time.h> +#include <sys/tame.h> #include <errno.h> #include <fcntl.h> @@ -137,11 +138,6 @@ main(int argc, char *argv[]) rtt.c_lflag &= ~ECHO; (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); - bzero(&sa, sizeof sa); - sigemptyset(&sa.sa_mask); - sa.sa_handler = finish; - (void)sigaction(SIGCHLD, &sa, NULL); - sa.sa_handler = handlesigwinch; sa.sa_flags = SA_RESTART; (void)sigaction(SIGWINCH, &sa, NULL); @@ -163,6 +159,13 @@ main(int argc, char *argv[]) doshell(); } + bzero(&sa, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = finish; + (void)sigaction(SIGCHLD, &sa, NULL); + + tame(TAME_STDIO | TAME_IOCTL); + (void)fclose(fscript); while (1) { if (dead) @@ -240,6 +243,13 @@ dooutput(void) sigemptyset(&sa.sa_mask); sa.sa_handler = scriptflush; (void)sigaction(SIGALRM, &sa, NULL); + + bzero(&sa, sizeof sa); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + (void)sigaction(SIGCHLD, &sa, NULL); + + tame(TAME_STDIO); value.it_interval.tv_sec = 30; value.it_interval.tv_usec = 0; Index: usr.bin/sed/main.c =================================================================== RCS file: /cvs/src/usr.bin/sed/main.c,v retrieving revision 1.21 diff -u -p -u -r1.21 main.c --- usr.bin/sed/main.c 17 Jul 2015 21:54:26 -0000 1.21 +++ usr.bin/sed/main.c 17 Jul 2015 22:57:24 -0000 @@ -34,6 +34,8 @@ */ #include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/tame.h> #include <sys/stat.h> #include <ctype.h> @@ -102,6 +104,8 @@ static void add_compunit(enum e_cut, cha static void add_file(char *); static int next_files_have_lines(void); +int termwidth = -1; + int main(int argc, char *argv[]) { @@ -144,6 +148,23 @@ main(int argc, char *argv[]) } argc -= optind; argv += optind; + + if (termwidth == -1) { + struct winsize win; + char *p; + + termwidth = 0; + if ((p = getenv("COLUMNS"))) + termwidth = strtonum(p, 0, INT_MAX, NULL); + if (termwidth == 0 && + ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && + win.ws_col > 0) + termwidth = win.ws_col; + if (termwidth == 0) + termwidth = 60; + } + + tame(TAME_STDIO | TAME_WPATH | TAME_RPATH | TAME_CPATH); /* First usage case; script is the first arg */ if (!eflag && !fflag && *argv) { Index: usr.bin/sed/process.c =================================================================== RCS file: /cvs/src/usr.bin/sed/process.c,v retrieving revision 1.24 diff -u -p -u -r1.24 process.c --- usr.bin/sed/process.c 17 Jul 2015 20:38:57 -0000 1.24 +++ usr.bin/sed/process.c 17 Jul 2015 21:27:04 -0000 @@ -35,7 +35,6 @@ #include <sys/types.h> #include <sys/stat.h> -#include <sys/ioctl.h> #include <sys/uio.h> #include <ctype.h> @@ -473,25 +472,8 @@ static void lputs(char *s) { int count; - const char *escapes; - char *p; - struct winsize win; - static int termwidth = -1; - - if (outfile != stdout) - termwidth = 60; - - if (termwidth == -1) { - termwidth = 0; - if ((p = getenv("COLUMNS"))) - termwidth = strtonum(p, 0, INT_MAX, NULL); - if (termwidth == 0 && - ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && - win.ws_col > 0) - termwidth = win.ws_col; - if (termwidth == 0) - termwidth = 60; - } + extern int termwidth; + char *escapes, *p; for (count = 0; *s; ++s) { if (count >= termwidth) { Index: usr.bin/signify/signify.c =================================================================== RCS file: /cvs/src/usr.bin/signify/signify.c,v retrieving revision 1.100 diff -u -p -u -r1.100 signify.c --- usr.bin/signify/signify.c 16 Jan 2015 06:16:12 -0000 1.100 +++ usr.bin/signify/signify.c 15 Jun 2015 00:55:45 -0000 @@ -15,6 +15,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sys/stat.h> +#include <sys/tame.h> #include <netinet/in.h> #include <resolv.h> Index: usr.bin/uniq/uniq.c =================================================================== RCS file: /cvs/src/usr.bin/uniq/uniq.c,v retrieving revision 1.19 diff -u -p -u -r1.19 uniq.c --- usr.bin/uniq/uniq.c 26 Nov 2013 19:25:39 -0000 1.19 +++ usr.bin/uniq/uniq.c 3 Jun 2015 22:09:03 -0000 @@ -33,6 +33,7 @@ * SUCH DAMAGE. */ +#include <sys/tame.h> #include <ctype.h> #include <err.h> #include <errno.h> @@ -61,6 +62,8 @@ main(int argc, char *argv[]) int ch; char *prevline, *thisline; + tame(TAME_STDIO | TAME_RPATH | TAME_WPATH); + obsolete(argv); while ((ch = getopt(argc, argv, "cdf:s:u")) != -1) { const char *errstr; @@ -118,6 +121,8 @@ main(int argc, char *argv[]) default: usage(); } + + tame(TAME_STDIO); prevline = malloc(MAXLINELEN); thisline = malloc(MAXLINELEN); Index: usr.bin/w/w.c =================================================================== RCS file: /cvs/src/usr.bin/w/w.c,v retrieving revision 1.58 diff -u -p -u -r1.58 w.c --- usr.bin/w/w.c 15 Mar 2015 00:41:28 -0000 1.58 +++ usr.bin/w/w.c 26 May 2015 19:26:58 -0000 @@ -219,6 +219,20 @@ main(int argc, char *argv[]) kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*kp), &nentries); if (kp == NULL) errx(1, "%s", kvm_geterr(kd)); + + if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 && + ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 && + ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0) + ttywidth = 79; + else + ttywidth = ws.ws_col - 1; + argwidth = ttywidth - WUSED; + if (argwidth < 4) + argwidth = 8; + +#include <sys/tame.h> +// tame(TAME_STDIO | TAME_GETPW | TAME_RPATH); + for (i = 0; i < nentries; i++, kp++) { if (kp->p_psflags & (PS_EMBRYO | PS_ZOMBIE)) continue; @@ -247,15 +261,6 @@ main(int argc, char *argv[]) } } } - if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 && - ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 && - ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0) - ttywidth = 79; - else - ttywidth = ws.ws_col - 1; - argwidth = ttywidth - WUSED; - if (argwidth < 4) - argwidth = 8; /* sort by idle time */ if (sortidle && ehead != NULL) { struct entry *from = ehead, *save; Index: usr.bin/wc/wc.c =================================================================== RCS file: /cvs/src/usr.bin/wc/wc.c,v retrieving revision 1.17 diff -u -p -u -r1.17 wc.c --- usr.bin/wc/wc.c 16 Jan 2015 06:40:14 -0000 1.17 +++ usr.bin/wc/wc.c 23 May 2015 18:11:59 -0000 @@ -32,6 +32,7 @@ #include <sys/param.h> /* MAXBSIZE */ #include <sys/stat.h> #include <sys/file.h> +#include <sys/tame.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -56,6 +57,8 @@ main(int argc, char *argv[]) int ch; setlocale(LC_ALL, ""); + + tame(TAME_STDIO | TAME_RPATH); while ((ch = getopt(argc, argv, "lwchm")) != -1) switch(ch) { Index: usr.bin/whois/whois.c =================================================================== RCS file: /cvs/src/usr.bin/whois/whois.c,v retrieving revision 1.47 diff -u -p -u -r1.47 whois.c --- usr.bin/whois/whois.c 9 Apr 2015 19:29:53 -0000 1.47 +++ usr.bin/whois/whois.c 3 Jun 2015 22:09:48 -0000 @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/socket.h> +#include <sys/tame.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -137,6 +138,8 @@ main(int argc, char *argv[]) if (!argc || (country != NULL && host != NULL)) usage(); + + tame(TAME_STDIO | TAME_DNS | TAME_INET); if (host == NULL && country == NULL && !(flags & WHOIS_QUICK)) flags |= WHOIS_RECURSE; Index: usr.sbin/arp/arp.c =================================================================== RCS file: /cvs/src/usr.sbin/arp/arp.c,v retrieving revision 1.64 diff -u -p -u -r1.64 arp.c --- usr.sbin/arp/arp.c 3 Jun 2015 08:10:53 -0000 1.64 +++ usr.sbin/arp/arp.c 3 Jun 2015 18:05:03 -0000 @@ -41,6 +41,7 @@ #include <sys/socket.h> #include <sys/sysctl.h> #include <sys/ioctl.h> +#include <sys/tame.h> #include <net/bpf.h> #include <net/if.h> #include <net/if_dl.h> @@ -160,8 +161,11 @@ main(int argc, char *argv[]) func = F_GET; rtn = 0; + getsocket(); + switch (func) { case F_GET: + tame(TAME_STDIO | TAME_DNS | TAME_INET); if (aflag && argc == 0) dump(); else if (!aflag && argc == 1) @@ -177,6 +181,7 @@ main(int argc, char *argv[]) rtn = set(argc, argv) ? 1 : 0; break; case F_DELETE: + tame(TAME_STDIO | TAME_DNS | TAME_INET); if (aflag && argc == 0) search(0, nuke_entry); else if (!aflag && argc == 1) Index: usr.sbin/authpf/authpf.c =================================================================== RCS file: /cvs/src/usr.sbin/authpf/authpf.c,v retrieving revision 1.123 diff -u -p -u -r1.123 authpf.c --- usr.sbin/authpf/authpf.c 21 Jan 2015 21:50:32 -0000 1.123 +++ usr.sbin/authpf/authpf.c 24 May 2015 01:09:52 -0000 @@ -23,6 +23,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/wait.h> +#include <sys/tame.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -147,6 +148,8 @@ main(int argc, char *argv[]) shell = pw->pw_shell; login_close(lc); + + tame(TAME_STDIO | TAME_WPATH); if (strcmp(shell, PATH_AUTHPF_SHELL) && strcmp(shell, PATH_AUTHPF_SHELL_NOIP)) { Index: usr.sbin/bgpd/rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.333 diff -u -p -u -r1.333 rde.c --- usr.sbin/bgpd/rde.c 16 Jul 2015 17:26:57 -0000 1.333 +++ usr.sbin/bgpd/rde.c 17 Jul 2015 21:15:24 -0000 @@ -20,6 +20,7 @@ #include <sys/socket.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/tame.h> #include <errno.h> #include <ifaddrs.h> @@ -193,6 +194,8 @@ rde_main(int pipe_m2r[2], int pipe_s2r[2 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); + + tame(TAME_MALLOC | TAME_UNIX | TAME_CMSG); signal(SIGTERM, rde_sighdlr); signal(SIGINT, rde_sighdlr); Index: usr.sbin/bgpd/session.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/session.c,v retrieving revision 1.338 diff -u -p -u -r1.338 session.c --- usr.sbin/bgpd/session.c 9 Feb 2015 11:37:31 -0000 1.338 +++ usr.sbin/bgpd/session.c 27 May 2015 21:04:35 -0000 @@ -17,12 +17,13 @@ */ #include <sys/types.h> - #include <sys/mman.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/un.h> +#include <sys/tame.h> + #include <net/if_types.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -229,6 +230,8 @@ session_main(int pipe_m2s[2], int pipe_s setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) fatal("can't drop privileges"); + + tame(TAME_MALLOC | TAME_INET | TAME_CMSG); signal(SIGTERM, session_sighdlr); signal(SIGINT, session_sighdlr); Index: usr.sbin/httpd/httpd.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v retrieving revision 1.37 diff -u -p -u -r1.37 httpd.c --- usr.sbin/httpd/httpd.c 3 Jun 2015 02:24:36 -0000 1.37 +++ usr.sbin/httpd/httpd.c 13 Jun 2015 14:56:53 -0000 @@ -23,6 +23,7 @@ #include <sys/stat.h> #include <sys/wait.h> #include <sys/resource.h> +#include <sys/tame.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -246,6 +247,9 @@ main(int argc, char *argv[]) proc_init(ps, procs, nitems(procs)); setproctitle("parent"); + + tame(TAME_MALLOC | TAME_INET | TAME_CMSG | TAME_RPATH | TAME_WPATH | + TAME_PROC | TAME_IOCTL); event_init(); Index: usr.sbin/httpd/logger.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/logger.c,v retrieving revision 1.12 diff -u -p -u -r1.12 logger.c --- usr.sbin/httpd/logger.c 11 Apr 2015 14:52:49 -0000 1.12 +++ usr.sbin/httpd/logger.c 13 Jun 2015 14:58:06 -0000 @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/queue.h> #include <sys/uio.h> +#include <sys/tame.h> #include <limits.h> #include <stdio.h> @@ -70,6 +71,8 @@ logger_shutdown(void) void logger_init(struct privsep *ps, struct privsep_proc *p, void *arg) { + tame(TAME_MALLOC | TAME_CMSG); + if (config_init(ps->ps_env) == -1) fatal("failed to initialize configuration"); Index: usr.sbin/httpd/server.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/server.c,v retrieving revision 1.70 diff -u -p -u -r1.70 server.c --- usr.sbin/httpd/server.c 16 Jul 2015 16:29:25 -0000 1.70 +++ usr.sbin/httpd/server.c 17 Jul 2015 21:15:25 -0000 @@ -24,6 +24,7 @@ #include <sys/socket.h> #include <sys/uio.h> #include <sys/tree.h> +#include <sys/tame.h> #include <netinet/in.h> #include <netinet/tcp.h> @@ -243,6 +244,14 @@ server_init(struct privsep *ps, struct p /* Unlimited file descriptors (use system limits) */ socket_rlimit(-1); + + /* + * XXX TAME_INET and TAME_UNIX are only needed for fcgi + * however if fcgi is used or not can change on config reload + * should we re-fork the children and tame again on reload + */ + tame(TAME_MALLOC | TAME_CMSG | TAME_RPATH | TAME_PROC | + TAME_INET | TAME_UNIX | TAME_IOCTL); #if 0 /* Schedule statistics timer */ Index: usr.sbin/ntpd/ntp.c =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntp.c,v retrieving revision 1.132 diff -u -p -u -r1.132 ntp.c --- usr.sbin/ntpd/ntp.c 25 May 2015 14:58:34 -0000 1.132 +++ usr.sbin/ntpd/ntp.c 28 May 2015 06:08:44 -0000 @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/time.h> #include <sys/stat.h> +#include <sys/tame.h> #include <errno.h> #include <fcntl.h> #include <paths.h> @@ -164,6 +165,9 @@ ntp_main(int pipe_prnt[2], int fd_ctl, s fatal("can't drop privileges"); endservent(); + + /* TAME_DNS for constraint.c */ + tame(TAME_STDIO | TAME_RW | TAME_INET | TAME_DNS | TAME_PROC); signal(SIGTERM, ntp_sighdlr); signal(SIGINT, ntp_sighdlr); Index: usr.sbin/ntpd/ntp_dns.c =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntp_dns.c,v retrieving revision 1.10 diff -u -p -u -r1.10 ntp_dns.c --- usr.sbin/ntpd/ntp_dns.c 24 Mar 2015 18:25:27 -0000 1.10 +++ usr.sbin/ntpd/ntp_dns.c 28 May 2015 17:29:24 -0000 @@ -19,6 +19,7 @@ #include <sys/types.h> #include <sys/resource.h> #include <sys/time.h> +#include <sys/tame.h> #include <err.h> #include <errno.h> @@ -89,6 +90,8 @@ ntp_dns(int pipe_ntp[2], struct ntpd_con if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf_dns, pipe_ntp[1]); + + tame(TAME_DNS | TAME_RW); while (quit_dns == 0) { pfd[0].fd = ibuf_dns->fd; Index: usr.sbin/ntpd/ntpd.c =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntpd.c,v retrieving revision 1.93 diff -u -p -u -r1.93 ntpd.c --- usr.sbin/ntpd/ntpd.c 11 Mar 2015 19:38:48 -0000 1.93 +++ usr.sbin/ntpd/ntpd.c 28 May 2015 17:24:43 -0000 @@ -22,6 +22,7 @@ #include <sys/socket.h> #include <sys/wait.h> #include <sys/un.h> +#include <sys/tame.h> #include <netinet/in.h> #include <errno.h> #include <poll.h> @@ -196,6 +197,9 @@ main(int argc, char *argv[]) setproctitle("[priv]"); readfreq(); +// XXX missing: adjtime() to change time +// tame(TAME_STDIO | TAME_UNIX | TAME_PROC); + signal(SIGTERM, sighdlr); signal(SIGINT, sighdlr); signal(SIGHUP, sighdlr); @@ -564,6 +568,8 @@ ctl_main(int argc, char *argv[]) errx(1, "ctl socket name too long"); if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) err(1, "connect: %s", sockname); + + tame(TAME_STDIO); if ((ibuf_ctl = malloc(sizeof(struct imsgbuf))) == NULL) err(1, NULL); Index: usr.sbin/relayd/ca.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/ca.c,v retrieving revision 1.13 diff -u -p -u -r1.13 ca.c --- usr.sbin/relayd/ca.c 2 May 2015 13:15:24 -0000 1.13 +++ usr.sbin/relayd/ca.c 11 Jun 2015 13:59:32 -0000 @@ -19,6 +19,7 @@ #include <sys/types.h> #include <sys/queue.h> #include <sys/uio.h> +#include <sys/tame.h> #include <unistd.h> #include <string.h> @@ -73,6 +74,8 @@ ca(struct privsep *ps, struct privsep_pr void ca_init(struct privsep *ps, struct privsep_proc *p, void *arg) { + tame(TAME_MALLOC | TAME_RW | TAME_CMSG); + if (config_init(ps->ps_env) == -1) fatal("failed to initialize configuration"); Index: usr.sbin/syslogd/syslogd.c =================================================================== RCS file: /cvs/src/usr.sbin/syslogd/syslogd.c,v retrieving revision 1.173 diff -u -p -u -r1.173 syslogd.c --- usr.sbin/syslogd/syslogd.c 16 Jul 2015 23:29:14 -0000 1.173 +++ usr.sbin/syslogd/syslogd.c 17 Jul 2015 21:15:27 -0000 @@ -75,6 +75,7 @@ #include <sys/un.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/tame.h> #include <netinet/in.h> #include <netdb.h> @@ -584,6 +585,8 @@ main(int argc, char *argv[]) /* Privilege separation begins here */ if (priv_init(ConfFile, NoDNS, lockpipe[1], nullfd, argv) < 0) errx(1, "unable to privsep"); + + tame(TAME_MALLOC | TAME_RPATH | TAME_UNIX | TAME_INET | TAME_CMSG); /* Process is now unprivileged and inside a chroot */ event_init(); Index: usr.sbin/tcpdump/privsep.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v retrieving revision 1.34 diff -u -p -u -r1.34 privsep.c --- usr.sbin/tcpdump/privsep.c 14 Jul 2015 20:23:40 -0000 1.34 +++ usr.sbin/tcpdump/privsep.c 14 Jul 2015 20:25:36 -0000 @@ -21,6 +21,7 @@ #include <sys/socket.h> #include <sys/wait.h> #include <sys/ioctl.h> +#include <sys/tame.h> #include <netinet/in.h> #include <net/if.h> @@ -258,6 +259,10 @@ priv_init(int argc, char **argv) setproctitle("[priv]"); close(socks[1]); + /* rpath for the device + * plus: resolv.conf, hosts, services, protocols, ethers, etc etc + * Unlikely to need YP? + */ for (;;) { if (may_read(socks[0], &cmd, sizeof(int))) break; @@ -281,6 +286,8 @@ priv_init(int argc, char **argv) case PRIV_INIT_DONE: test_state(cmd, STATE_RUN); impl_init_done(socks[0], &bpfd); + tame(TAME_MALLOC | TAME_CMSG | TAME_INET | + TAME_IOCTL | TAME_DNS | TAME_RPATH); break; case PRIV_GETHOSTBYADDR: test_state(cmd, STATE_RUN); Index: usr.sbin/tcpdump/tcpdump.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v retrieving revision 1.72 diff -u -p -u -r1.72 tcpdump.c --- usr.sbin/tcpdump/tcpdump.c 14 Jul 2015 20:23:40 -0000 1.72 +++ usr.sbin/tcpdump/tcpdump.c 14 Jul 2015 20:25:20 -0000 @@ -33,6 +33,7 @@ #include <sys/time.h> #include <sys/ioctl.h> #include <sys/wait.h> +#include <sys/tame.h> #include <netinet/in.h> @@ -490,6 +491,7 @@ main(int argc, char **argv) if (tflag > 0) thiszone = gmt2local(0); + tame(TAME_STDIO); if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { (void)fprintf(stderr, "%s: pcap_loop: %s

", Index: usr.sbin/traceroute/traceroute.c =================================================================== RCS file: /cvs/src/usr.sbin/traceroute/traceroute.c,v retrieving revision 1.140 diff -u -p -u -r1.140 traceroute.c --- usr.sbin/traceroute/traceroute.c 16 Jul 2015 22:47:46 -0000 1.140 +++ usr.sbin/traceroute/traceroute.c 17 Jul 2015 21:15:27 -0000 @@ -239,6 +239,7 @@ #include <sys/file.h> #include <sys/ioctl.h> #include <sys/sysctl.h> +#include <sys/tame.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -843,6 +844,11 @@ main(int argc, char *argv[]) if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, sizeof(datalen)) < 0) err(6, "SO_SNDBUF"); + + if (nflag) + tame(TAME_STDIO | TAME_INET); + else + tame(TAME_STDIO | TAME_INET | TAME_DNS); if (getnameinfo(to, to->sa_len, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) [prev in list] [next in list] [ prev in thread ] [next in thread]