summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_jail.c5
-rw-r--r--sys/net/rtsock.c15
-rw-r--r--sys/netinet/raw_ip.c33
-rw-r--r--sys/sys/jail.h1
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;
OpenPOWER on IntegriCloud