diff options
-rw-r--r-- | sys/kern/kern_jail.c | 5 | ||||
-rw-r--r-- | sys/net/rtsock.c | 15 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 33 | ||||
-rw-r--r-- | sys/sys/jail.h | 1 |
4 files changed, 50 insertions, 4 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 0b8febe..712bae2 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -59,6 +59,11 @@ SYSCTL_INT(_security_jail, OID_AUTO, getfsstate_getfsstatroot_only, CTLFLAG_RW, &jail_getfsstatroot_only, 0, "Processes see only their root file system in getfsstat()"); +int jail_allow_raw_sockets = 0; +SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW, + &jail_allow_raw_sockets, 0, + "Prison root can create raw sockets"); + /* allprison, lastprid, and prisoncount are protected by allprison_mtx. */ struct prisonlist allprison; struct mtx allprison_mtx; diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 9dc8202..7094bf7 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -48,6 +48,8 @@ #include <net/raw_cb.h> #include <net/route.h> +#include <netinet/in.h> + MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); /* NB: these are not modified */ @@ -287,6 +289,7 @@ route_output(struct mbuf *m, struct socket *so) int len, error = 0; struct ifnet *ifp = NULL; struct ifaddr *ifa = NULL; + struct sockaddr_in jail; #define senderr(e) { error = e; goto flush;} if (m == NULL || ((m->m_len < sizeof(long)) && @@ -400,8 +403,16 @@ route_output(struct mbuf *m, struct socket *so) if (ifp) { info.rti_info[RTAX_IFP] = ifaddr_byindex(ifp->if_index)->ifa_addr; - info.rti_info[RTAX_IFA] = - rt->rt_ifa->ifa_addr; + if (jailed(so->so_cred)) { + jail.sin_family = PF_INET; + jail.sin_len = sizeof(jail); + jail.sin_addr.s_addr = + htonl(prison_getip(so->so_cred)); + info.rti_info[RTAX_IFA] = + (struct sockaddr *)&jail; + } else + info.rti_info[RTAX_IFA] = + rt->rt_ifa->ifa_addr; if (ifp->if_flags & IFF_POINTOPOINT) info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr; diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 25078b0..f4eb92c 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -36,6 +36,7 @@ #include "opt_random_ip_id.h" #include <sys/param.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/mac.h> @@ -206,6 +207,10 @@ rip_input(struct mbuf *m, int off) if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) goto docontinue; + if (jailed(inp->inp_socket->so_cred)) + if (htonl(prison_getip(inp->inp_socket->so_cred)) + != ip->ip_dst.s_addr) + goto docontinue; if (last) { struct mbuf *n; @@ -261,7 +266,11 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) ip->ip_off = 0; ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; - ip->ip_src = inp->inp_laddr; + if (jailed(inp->inp_socket->so_cred)) + ip->ip_src.s_addr = + htonl(prison_getip(inp->inp_socket->so_cred)); + else + ip->ip_src = inp->inp_laddr; ip->ip_dst.s_addr = dst; ip->ip_ttl = inp->inp_ip_ttl; } else { @@ -270,6 +279,13 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) return(EMSGSIZE); } ip = mtod(m, struct ip *); + if (jailed(inp->inp_socket->so_cred)) { + if (ip->ip_src.s_addr != + htonl(prison_getip(inp->inp_socket->so_cred))) { + m_freem(m); + return (EPERM); + } + } /* don't allow both user specified and setsockopt options, and don't allow packet length sizes that will crash */ if (((ip->ip_hl != (sizeof (*ip) >> 2)) @@ -518,7 +534,11 @@ rip_attach(struct socket *so, int proto, struct thread *td) INP_INFO_WUNLOCK(&ripcbinfo); return EINVAL; } - if (td && (error = suser(td)) != 0) { + if (td && jailed(td->td_ucred) && !jail_allow_raw_sockets) { + INP_INFO_WUNLOCK(&ripcbinfo); + return (EPERM); + } + if (td && (error = suser_cred(td->td_ucred, PRISON_ROOT)) != 0) { INP_INFO_WUNLOCK(&ripcbinfo); return error; } @@ -618,6 +638,15 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td) if (nam->sa_len != sizeof(*addr)) return EINVAL; + if (jailed(td->td_ucred)) { + if (addr->sin_addr.s_addr == INADDR_ANY) + addr->sin_addr.s_addr = + htonl(prison_getip(td->td_ucred)); + if (htonl(prison_getip(td->td_ucred)) + != addr->sin_addr.s_addr) + return (EADDRNOTAVAIL); + } + if (TAILQ_EMPTY(&ifnet) || (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) || (addr->sin_addr.s_addr && diff --git a/sys/sys/jail.h b/sys/sys/jail.h index 576d2fd..605b5a5 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -82,6 +82,7 @@ extern int jail_set_hostname_allowed; extern int jail_socket_unixiproute_only; extern int jail_sysvipc_allowed; extern int jail_getfsstat_jailrootonly; +extern int jail_allow_raw_sockets; LIST_HEAD(prisonlist, prison); extern struct prisonlist allprison; |