capsicum: Limit socket operations in capability mode
Capsicum did not prevent certain privileged networking operations, specifically creation of raw sockets and network configuration ioctls. However, these facilities can be used to circumvent some of the restrictions that capability mode is supposed to enforce. Add capability mode checks to disallow network configuration ioctls and creation of sockets other than PF_LOCAL and SOCK_DGRAM/STREAM/SEQPACKET internet sockets. Reviewed by: oshogbo Discussed with: emaste Reported by: manu Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D29423
This commit is contained in:
parent
12db51d208
commit
274579831b
@ -271,7 +271,7 @@ soo_ioctl(struct file *fp, u_long cmd, void *data, struct ucred *active_cred,
|
||||
error = ifioctl(so, cmd, data, td);
|
||||
else if (IOCGROUP(cmd) == 'r') {
|
||||
CURVNET_SET(so->so_vnet);
|
||||
error = rtioctl_fib(cmd, data, so->so_fibnum);
|
||||
error = rtioctl_fib(cmd, data, so->so_fibnum, td);
|
||||
CURVNET_RESTORE();
|
||||
} else {
|
||||
CURVNET_SET(so->so_vnet);
|
||||
|
@ -112,6 +112,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/lock.h>
|
||||
@ -526,6 +527,9 @@ socreate(int dom, struct socket **aso, int type, int proto,
|
||||
prp->pr_usrreqs->pru_attach == pru_attach_notsupp)
|
||||
return (EPROTONOSUPPORT);
|
||||
|
||||
if (IN_CAPABILITY_MODE(td) && (prp->pr_flags & PR_CAPATTACH) == 0)
|
||||
return (ECAPMODE);
|
||||
|
||||
if (prison_check_af(cred, prp->pr_domain->dom_family) != 0)
|
||||
return (EPROTONOSUPPORT);
|
||||
|
||||
|
@ -428,14 +428,15 @@ static struct protosw localsw[] = {
|
||||
{
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &localdomain,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_RIGHTS|
|
||||
PR_CAPATTACH,
|
||||
.pr_ctloutput = &uipc_ctloutput,
|
||||
.pr_usrreqs = &uipc_usrreqs_stream
|
||||
},
|
||||
{
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &localdomain,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_RIGHTS|PR_CAPATTACH,
|
||||
.pr_ctloutput = &uipc_ctloutput,
|
||||
.pr_usrreqs = &uipc_usrreqs_dgram
|
||||
},
|
||||
@ -448,8 +449,8 @@ static struct protosw localsw[] = {
|
||||
* due to our use of sbappendaddr. A new sbappend variants is needed
|
||||
* that supports both atomic record writes and control data.
|
||||
*/
|
||||
.pr_flags = PR_ADDR|PR_ATOMIC|PR_CONNREQUIRED|PR_WANTRCVD|
|
||||
PR_RIGHTS,
|
||||
.pr_flags = PR_ADDR|PR_ATOMIC|PR_CONNREQUIRED|
|
||||
PR_WANTRCVD|PR_RIGHTS|PR_CAPATTACH,
|
||||
.pr_ctloutput = &uipc_ctloutput,
|
||||
.pr_usrreqs = &uipc_usrreqs_seqpacket,
|
||||
},
|
||||
|
10
sys/net/if.c
10
sys/net/if.c
@ -37,6 +37,7 @@
|
||||
#include "opt_inet.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/malloc.h>
|
||||
@ -2967,6 +2968,15 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
|
||||
bool shutdown;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface ioctls access a global namespace. There is currently no
|
||||
* capability-based representation for interfaces, so the configuration
|
||||
* interface is simply unaccessible from capability mode. If necessary,
|
||||
* select ioctls may be permitted here.
|
||||
*/
|
||||
if (IN_CAPABILITY_MODE(td))
|
||||
return (ECAPMODE);
|
||||
|
||||
CURVNET_SET(so->so_vnet);
|
||||
#ifdef VIMAGE
|
||||
/* Make sure the VNET is stable. */
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/socket.h>
|
||||
@ -245,8 +246,10 @@ rib_add_redirect(u_int fibnum, struct sockaddr *dst, struct sockaddr *gateway,
|
||||
* Routing table ioctl interface.
|
||||
*/
|
||||
int
|
||||
rtioctl_fib(u_long req, caddr_t data, u_int fibnum)
|
||||
rtioctl_fib(u_long req, caddr_t data, u_int fibnum, struct thread *td)
|
||||
{
|
||||
if (IN_CAPABILITY_MODE(td))
|
||||
return (ECAPMODE);
|
||||
|
||||
/*
|
||||
* If more ioctl commands are added here, make sure the proper
|
||||
|
@ -431,11 +431,13 @@ void rt_updatemtu(struct ifnet *);
|
||||
|
||||
void rt_flushifroutes(struct ifnet *ifp);
|
||||
|
||||
struct thread;
|
||||
|
||||
/* XXX MRT NEW VERSIONS THAT USE FIBs
|
||||
* For now the protocol indepedent versions are the same as the AF_INET ones
|
||||
* but this will change..
|
||||
*/
|
||||
int rtioctl_fib(u_long, caddr_t, u_int);
|
||||
int rtioctl_fib(u_long, caddr_t, u_int, struct thread *);
|
||||
int rib_lookup_info(uint32_t, const struct sockaddr *, uint32_t, uint32_t,
|
||||
struct rt_addrinfo *);
|
||||
void rib_free_info(struct rt_addrinfo *info);
|
||||
|
@ -36,6 +36,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sockio.h>
|
||||
@ -237,6 +238,9 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
|
||||
if (ifp == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
|
||||
if (td != NULL && IN_CAPABILITY_MODE(td))
|
||||
return (ECAPMODE);
|
||||
|
||||
/*
|
||||
* Filter out 4 ioctls we implement directly. Forward the rest
|
||||
* to specific functions and ifp->if_ioctl().
|
||||
|
@ -112,6 +112,7 @@ struct protosw inetsw[] = {
|
||||
.pr_type = 0,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_IP,
|
||||
.pr_flags = PR_CAPATTACH,
|
||||
.pr_init = ip_init,
|
||||
.pr_slowtimo = ip_slowtimo,
|
||||
.pr_drain = ip_drain,
|
||||
@ -121,7 +122,7 @@ struct protosw inetsw[] = {
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_UDP,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_CAPATTACH,
|
||||
.pr_input = udp_input,
|
||||
.pr_ctlinput = udp_ctlinput,
|
||||
.pr_ctloutput = udp_ctloutput,
|
||||
@ -132,7 +133,8 @@ struct protosw inetsw[] = {
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_TCP,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|
|
||||
PR_CAPATTACH,
|
||||
.pr_input = tcp_input,
|
||||
.pr_ctlinput = tcp_ctlinput,
|
||||
.pr_ctloutput = tcp_ctloutput,
|
||||
@ -170,7 +172,7 @@ struct protosw inetsw[] = {
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inetdomain,
|
||||
.pr_protocol = IPPROTO_UDPLITE,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_CAPATTACH,
|
||||
.pr_input = udp_input,
|
||||
.pr_ctlinput = udplite_ctlinput,
|
||||
.pr_ctloutput = udp_ctloutput,
|
||||
|
@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "opt_inet6.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/jail.h>
|
||||
@ -254,6 +255,9 @@ in6_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
int error;
|
||||
u_long ocmd = cmd;
|
||||
|
||||
if (td != NULL && IN_CAPABILITY_MODE(td))
|
||||
return (ECAPMODE);
|
||||
|
||||
/*
|
||||
* Compat to make pre-10.x ifconfig(8) operable.
|
||||
*/
|
||||
|
@ -145,6 +145,7 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = 0,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_IPV6,
|
||||
.pr_flags = PR_CAPATTACH,
|
||||
.pr_init = ip6_init,
|
||||
.pr_slowtimo = frag6_slowtimo,
|
||||
.pr_drain = frag6_drain,
|
||||
@ -154,7 +155,7 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_UDP,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_CAPATTACH,
|
||||
.pr_input = udp6_input,
|
||||
.pr_ctlinput = udp6_ctlinput,
|
||||
.pr_ctloutput = ip6_ctloutput,
|
||||
@ -167,7 +168,8 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = SOCK_STREAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_TCP,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|PR_LISTEN,
|
||||
.pr_flags = PR_CONNREQUIRED|PR_IMPLOPCL|PR_WANTRCVD|
|
||||
PR_LISTEN|PR_CAPATTACH,
|
||||
.pr_input = tcp6_input,
|
||||
.pr_ctlinput = tcp6_ctlinput,
|
||||
.pr_ctloutput = tcp_ctloutput,
|
||||
@ -209,7 +211,7 @@ struct protosw inet6sw[] = {
|
||||
.pr_type = SOCK_DGRAM,
|
||||
.pr_domain = &inet6domain,
|
||||
.pr_protocol = IPPROTO_UDPLITE,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR,
|
||||
.pr_flags = PR_ATOMIC|PR_ADDR|PR_CAPATTACH,
|
||||
.pr_input = udp6_input,
|
||||
.pr_ctlinput = udplite6_ctlinput,
|
||||
.pr_ctloutput = udp_ctloutput,
|
||||
|
@ -121,6 +121,7 @@ struct protosw {
|
||||
#define PR_RIGHTS 0x10 /* passes capabilities */
|
||||
#define PR_IMPLOPCL 0x20 /* implied open/close */
|
||||
#define PR_LASTHDR 0x40 /* enforce ipsec policy; last header */
|
||||
#define PR_CAPATTACH 0x80 /* socket can attach in cap mode */
|
||||
|
||||
/*
|
||||
* In earlier BSD network stacks, a single pr_usrreq() function pointer was
|
||||
@ -183,7 +184,6 @@ struct uio;
|
||||
* should eventually be merged back into struct protosw.
|
||||
*
|
||||
* Some fields initialized to defaults if they are NULL.
|
||||
* See uipc_domain.c:net_init_domain()
|
||||
*/
|
||||
struct pr_usrreqs {
|
||||
void (*pru_abort)(struct socket *so);
|
||||
|
Loading…
Reference in New Issue
Block a user