[patch] Raw sockets in jails
Christian S.J. Peron
cperon-list at seccuris.com
Thu Apr 22 11:35:26 PDT 2004
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 <net/raw_cb.h>
#include <net/route.h>
+#include <netinet/in.h>
+
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 <sys/param.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mac.h>
@@ -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) ||
More information about the freebsd-hackers
mailing list