diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c --- a/sys/kern/sys_socket.c +++ b/sys/kern/sys_socket.c @@ -271,7 +271,7 @@ 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); diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -112,6 +112,7 @@ #include #include +#include #include #include #include @@ -526,6 +527,9 @@ 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); diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -428,14 +428,15 @@ { .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 @@ * 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, }, diff --git a/sys/net/if.c b/sys/net/if.c --- a/sys/net/if.c +++ b/sys/net/if.c @@ -37,6 +37,7 @@ #include "opt_inet.h" #include +#include #include #include #include @@ -2967,6 +2968,15 @@ 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. */ diff --git a/sys/net/route.h b/sys/net/route.h --- a/sys/net/route.h +++ b/sys/net/route.h @@ -431,11 +431,13 @@ 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); diff --git a/sys/net/route.c b/sys/net/route.c --- a/sys/net/route.c +++ b/sys/net/route.c @@ -43,6 +43,7 @@ #include #include +#include #include #include #include @@ -245,8 +246,10 @@ * 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 diff --git a/sys/netinet/in.c b/sys/netinet/in.c --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -237,6 +238,9 @@ 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(). diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -112,6 +112,7 @@ .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 @@ .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 @@ .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 @@ .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, diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -69,6 +69,7 @@ #include "opt_inet6.h" #include +#include #include #include #include @@ -254,6 +255,9 @@ int error; u_long ocmd = cmd; + if (td != NULL && IN_CAPABILITY_MODE(td)) + return (ECAPMODE); + /* * Compat to make pre-10.x ifconfig(8) operable. */ diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -145,6 +145,7 @@ .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 @@ .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 @@ .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 @@ .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, diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -121,6 +121,7 @@ #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 @@ * 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);