mac_portacl and automatic port allocation

Michal Mertl mime at traveller.cz
Tue Nov 23 08:23:45 PST 2004


Robert Watson wrote(a):
> On Sun, 21 Nov 2004, Michal Mertl wrote:
> 
> 
>>I really like the idea behind mac_portacl but I find it difficult to use
>>it because of one issue. When an unprivileged program binds to high
>>automatic port with a call to bind(2) and port number set to 0 the
>>system chooses the port to bind to itself. This mechanismus is used by
>>number of programs, most commonly by ftp clients in active mode.
>>Unfortunately this 0 is checked by the mac_portacl(4) module and the
>>call to bind is refused. Rather simple fix would be to check if the
>>local port is 0 and user hasn't asked for IP_PORTRANGE_LOW and then
>>allow the call to trivially succeed. It can be controlled by a sysctl if
>>needed. 
>>
>>What do you think of the patch below?
> 
> 
> Seems like a good change to me.  Technically, there's probably a slight
> atomicity problem relating to threads, since one thread could change the
> flag while another thread is making the call to bind the socket.  I'm not
> sure that's easily fixed without a specific MAC check in the inet code,
> and what you propose is certainly a big improvement over what is there.

I noticed this potential problem. I don't think it's too serious. But it may 
possibly allow attacker to bind to low ports, potentially block legal use of 
them. That's why I offered the behavior in this case may be controlled by a 
sysctl.

Extended patch attached. Binding to zero is disabled by default.

> 
> I'll get this, sans the printf, merged sometime today.
> 

Thank you.

> Thanks!
> 
> Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
> robert at fledge.watson.org      Principal Research Scientist, McAfee Research
> 
> 
> 
> 

-------------- next part --------------
--- mac_portacl.c.orig	Tue Nov 23 17:02:05 2004
+++ mac_portacl.c	Tue Nov 23 17:08:39 2004
@@ -79,6 +79,7 @@
 #include <sys/sysctl.h>
 
 #include <netinet/in.h>
+#include <netinet/in_pcb.h>
 
 #include <vm/vm.h>
 
@@ -100,6 +101,12 @@
 TUNABLE_INT("security.mac.portacl.suser_exempt",
     &mac_portacl_suser_exempt);
 
+static int	mac_portacl_allow_bind_zero = 0;
+SYSCTL_INT(_security_mac_portacl, OID_AUTO, allow_bind_zero, CTLFLAG_RW,
+    &mac_portacl_allow_bind_zero, 0, "Whether binding to port 0 (system chooses the port automaticaly) is permitted");
+TUNABLE_INT("security.mac.portacl.allow_bind_zero",
+    &mac_portacl_allow_bind_zero);
+
 static int	mac_portacl_port_high = 1023;
 SYSCTL_INT(_security_mac_portacl, OID_AUTO, port_high, CTLFLAG_RW,
     &mac_portacl_port_high, 0, "Highest port to enforce for");
@@ -441,6 +448,7 @@
     struct label *socketlabel, struct sockaddr *sockaddr)
 {
 	struct sockaddr_in *sin;
+	struct inpcb *inp = sotoinpcb(so); 
 	int family, type;
 	u_int16_t port;
 
@@ -467,6 +475,11 @@
 	type = so->so_type;
 	sin = (struct sockaddr_in *) sockaddr;
 	port = ntohs(sin->sin_port);
+	/* If port == 0 and user hasn't asked for IP_PORTRANGELOW return
+	success */
+	if (mac_portacl_allow_bind_zero && port == 0 &&
+	    (inp->inp_flags & INP_LOWPORT) == 0)
+		return (0);
 
 	return (rules_check(cred, family, type, port));
 }


More information about the freebsd-security mailing list