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) ||
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to