From owner-freebsd-security@FreeBSD.ORG Thu Apr 22 11:35:26 2004 Return-Path: Delivered-To: freebsd-security@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 26A6E16A4CF for ; Thu, 22 Apr 2004 11:35:26 -0700 (PDT) Received: from staff.seccuris.com (staff.seccuris.com [204.112.0.40]) by mx1.FreeBSD.org (Postfix) with SMTP id 2067143D45 for ; Thu, 22 Apr 2004 11:35:25 -0700 (PDT) (envelope-from cperon-list@seccuris.com) Received: (qmail 24252 invoked by uid 1006); 22 Apr 2004 18:35:24 -0000 Date: Thu, 22 Apr 2004 18:35:24 +0000 From: "Christian S.J. Peron" To: Poul-Henning Kamp Message-ID: <20040422183523.A22252@staff.seccuris.com> References: <20040420200027.A51891@staff.seccuris.com> <23453.1082492678@critter.freebsd.dk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <23453.1082492678@critter.freebsd.dk>; from phk@phk.freebsd.dk on Tue, Apr 20, 2004 at 10:24:38PM +0200 cc: freebsd-hackers@freebsd.org cc: freebsd-security@freebsd.org Subject: Re: [patch] Raw sockets in jails X-BeenThere: freebsd-security@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Security issues [members-only posting] List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Apr 2004 18:35:26 -0000 I discovered the reason why traceroute breaks without -s with the most recent patches I posted to the list. When traceroute can not figure out what its source IP address is, it generates a RTM_GET routing request through a routing socket and extracts the source address of the route given the destination. I have created a new set of patches, the only real difference is I modified the routing code so that when it receives a RTM_GET request from a jailed process, it re-defines the source address of the route so that it corresponds with the prisons IP. I have tested these patches and they appear to work, however I ask for people to test and scrutinize these patches. Feedback/comments are welcome. Regards Christian S.J. Peron --------> new and improved patch <----------- --- sys/kern/kern_jail.c.bak Mon Apr 19 16:55:40 2004 +++ sys/kern/kern_jail.c Mon Apr 19 17:56:03 2004 @@ -53,6 +53,11 @@ &jail_sysvipc_allowed, 0, "Processes in jail can use System V IPC primitives"); +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; --- sys/net/rtsock.c.bak Wed Apr 21 03:09:41 2004 +++ sys/net/rtsock.c Thu Apr 22 17:37:42 2004 @@ -52,6 +52,8 @@ #include #include +#include + MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables"); /* NB: these are not modified */ @@ -289,6 +291,7 @@ int len, error = 0; struct ifnet *ifp = 0; struct ifaddr *ifa = 0; + struct sockaddr_in jail; #define senderr(e) { error = e; goto flush;} if (m == 0 || ((m->m_len < sizeof(long)) && @@ -400,8 +403,14 @@ ifp = rt->rt_ifp; if (ifp) { info.rti_info[RTAX_IFP] = TAILQ_FIRST(&ifp->if_addrhead)->ifa_addr; - info.rti_info[RTAX_IFA] = - rt->rt_ifa->ifa_addr; + if (so->so_cred->cr_prison) { + jail.sin_family = PF_INET; + jail.sin_len = sizeof(jail); + jail.sin_addr.s_addr = htonl(so->so_cred->cr_prison->pr_ip); + 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; --- sys/netinet/raw_ip.c.b Mon Apr 19 16:23:57 2004 +++ sys/netinet/raw_ip.c Thu Apr 22 18:30:42 2004 @@ -40,6 +40,7 @@ #include "opt_random_ip_id.h" #include +#include #include #include #include @@ -215,6 +216,10 @@ if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) goto docontinue; + if (inp->inp_socket->so_cred->cr_prison) + if (htonl(inp->inp_socket->so_cred->cr_prison->pr_ip) + != ip->ip_dst.s_addr) + goto docontinue; if (last) { struct mbuf *n; @@ -270,7 +275,11 @@ 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 (inp->inp_socket->so_cred->cr_prison) + ip->ip_src.s_addr = + htonl(inp->inp_socket->so_cred->cr_prison->pr_ip); + else + ip->ip_src = inp->inp_laddr; ip->ip_dst.s_addr = dst; ip->ip_ttl = inp->inp_ip_ttl; } else { @@ -279,6 +288,13 @@ return(EMSGSIZE); } ip = mtod(m, struct ip *); + if (inp->inp_socket->so_cred->cr_prison) { + if (ip->ip_src.s_addr != + htonl(inp->inp_socket->so_cred->cr_prison->pr_ip)) { + 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)) @@ -505,6 +521,7 @@ } } +extern int jail_allow_raw_sockets; u_long rip_sendspace = RIPSNDQ; u_long rip_recvspace = RIPRCVQ; @@ -527,7 +544,11 @@ 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; } @@ -626,6 +647,15 @@ if (nam->sa_len != sizeof(*addr)) return EINVAL; + + if (td->td_ucred->cr_prison) { + if (addr->sin_addr.s_addr == INADDR_ANY) + addr->sin_addr.s_addr = + htonl(td->td_ucred->cr_prison->pr_ip); + if (htonl(td->td_ucred->cr_prison->pr_ip) + != addr->sin_addr.s_addr) + return (EADDRNOTAVAIL); + } if (TAILQ_EMPTY(&ifnet) || (addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||