From 7ba9c3eba0ab719782f31ed4f9953cc9e5e68b24 Mon Sep 17 00:00:00 2001 From: deraadt Date: Tue, 20 Oct 2015 01:44:00 +0000 Subject: [PATCH] Always allow the setsockopt & getsockopt system calls... however, in the default case only allows SOL_SOCKET SO_RCVBUF which is very common in network-facing daemons. Many of them manage this on a socket after dropping abilities which can get them _new_ sockets.. syslogd, bgpd, relayd, etc etc. Other sockopts still require specific pledges. Tested by bluhm. --- sys/kern/kern_pledge.c | 35 +++++++++++++++++++++++++++++------ sys/kern/uipc_syscalls.c | 8 ++++++-- sys/sys/pledge.h | 4 ++-- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/sys/kern/kern_pledge.c b/sys/kern/kern_pledge.c index 7bff183f241..4c8dae3686a 100644 --- a/sys/kern/kern_pledge.c +++ b/sys/kern/kern_pledge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_pledge.c,v 1.57 2015/10/19 16:20:56 deraadt Exp $ */ +/* $OpenBSD: kern_pledge.c,v 1.58 2015/10/20 01:44:00 deraadt Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -87,6 +87,9 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = { [SYS_sysctl] = PLEDGE_SELF, /* read-only; narrow subset */ [SYS_adjtime] = PLEDGE_SELF, /* read-only */ + [SYS_setsockopt] = PLEDGE_SELF, /* white list */ + [SYS_getsockopt] = PLEDGE_SELF, + [SYS_fchdir] = PLEDGE_SELF, /* careful of directory fd inside jails */ /* needed by threaded programs */ @@ -242,8 +245,6 @@ const u_int pledge_syscalls[SYS_MAXSYSCALL] = { [SYS_accept] = PLEDGE_INET | PLEDGE_UNIX, [SYS_getpeername] = PLEDGE_INET | PLEDGE_UNIX, [SYS_getsockname] = PLEDGE_INET | PLEDGE_UNIX, - [SYS_setsockopt] = PLEDGE_INET | PLEDGE_UNIX, - [SYS_getsockopt] = PLEDGE_INET | PLEDGE_UNIX, [SYS_flock] = PLEDGE_FLOCK | PLEDGE_YP_ACTIVE, }; @@ -1057,12 +1058,35 @@ pledge_ioctl_check(struct proc *p, long com, void *v) } int -pledge_setsockopt_check(struct proc *p, int level, int optname) +pledge_sockopt_check(struct proc *p, int level, int optname) { if ((p->p_p->ps_flags & PS_PLEDGE) == 0) return (0); - /* common case for PLEDGE_UNIX and PLEDGE_INET */ + /* Always allow these, which are too common to reject */ + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_RCVBUF: + return 0; + } + break; + } + + if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX|PLEDGE_DNS)) == 0) + return (EPERM); + /* In use by some service libraries */ + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_TIMESTAMP: + return 0; + } + break; + } + + if ((p->p_p->ps_pledge & (PLEDGE_INET|PLEDGE_UNIX)) == 0) + return (EPERM); switch (level) { case SOL_SOCKET: switch (optname) { @@ -1074,7 +1098,6 @@ pledge_setsockopt_check(struct proc *p, int level, int optname) if ((p->p_p->ps_pledge & PLEDGE_INET) == 0) return (EPERM); - switch (level) { case IPPROTO_TCP: switch (optname) { diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index b80c055e243..c95a77afea6 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.115 2015/10/18 20:15:10 deraadt Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.116 2015/10/20 01:44:00 deraadt Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -930,7 +930,7 @@ sys_setsockopt(struct proc *p, void *v, register_t *retval) error = EINVAL; goto bad; } - if (pledge_setsockopt_check(p, SCARG(uap, level), SCARG(uap, name))) { + if (pledge_sockopt_check(p, SCARG(uap, level), SCARG(uap, name))) { error = pledge_fail(p, EPERM, PLEDGE_INET); goto bad; } @@ -985,6 +985,10 @@ sys_getsockopt(struct proc *p, void *v, register_t *retval) if ((error = getsock(p, SCARG(uap, s), &fp)) != 0) return (error); + if (pledge_sockopt_check(p, SCARG(uap, level), SCARG(uap, name))) { + error = pledge_fail(p, EPERM, PLEDGE_INET); + goto out; + } if (isdnssocket((struct socket *)fp->f_data)) { error = EINVAL; goto out; diff --git a/sys/sys/pledge.h b/sys/sys/pledge.h index 67af2b60688..68b0ca13853 100644 --- a/sys/sys/pledge.h +++ b/sys/sys/pledge.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pledge.h,v 1.7 2015/10/18 20:15:10 deraadt Exp $ */ +/* $OpenBSD: pledge.h,v 1.8 2015/10/20 01:44:00 deraadt Exp $ */ /* * Copyright (c) 2015 Nicholas Marriott @@ -69,7 +69,7 @@ int pledge_adjtime_check(struct proc *p, const void *v); int pledge_recvit_check(struct proc *p, const void *from); int pledge_sendit_check(struct proc *p, const void *to); int pledge_socket_check(struct proc *p, int domain); -int pledge_setsockopt_check(struct proc *p, int level, int optname); +int pledge_sockopt_check(struct proc *p, int level, int optname); int pledge_dns_check(struct proc *p, in_port_t port); int pledge_ioctl_check(struct proc *p, long com, void *); int pledge_flock_check(struct proc *p); -- 2.20.1