diff options
author | bmilekic <bmilekic@FreeBSD.org> | 2004-04-26 19:46:52 +0000 |
---|---|---|
committer | bmilekic <bmilekic@FreeBSD.org> | 2004-04-26 19:46:52 +0000 |
commit | 6bbcc9da29c8a05cfc4e9ea4b0c011a198f922f9 (patch) | |
tree | 01d32f484dd680de320e3aa8aa140e384e5651ce /sys | |
parent | 9d0355ed7f0bbf975788782707905c7d8e6af277 (diff) | |
download | FreeBSD-src-6bbcc9da29c8a05cfc4e9ea4b0c011a198f922f9.zip FreeBSD-src-6bbcc9da29c8a05cfc4e9ea4b0c011a198f922f9.tar.gz |
Give jail(8) the feature to allow raw sockets from within a
jail, which is less restrictive but allows for more flexible
jail usage (for those who are willing to make the sacrifice).
The default is off, but allowing raw sockets within jails can
now be accomplished by tuning security.jail.allow_raw_sockets
to 1.
Turning this on will allow you to use things like ping(8)
or traceroute(8) from within a jail.
The patch being committed is not identical to the patch
in the PR. The committed version is more friendly to
APIs which pjd is working on, so it should integrate
into his work quite nicely. This change has also been
presented and addressed on the freebsd-hackers mailing
list.
Submitted by: Christian S.J. Peron <maneo@bsdpro.com>
PR: kern/65800
Diffstat (limited to 'sys')
-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; |