Thursday, May 28, 2009

MAC_PORTACL and no love

OK, starting to get a bit frustrated. Running 7.2 on a Xen system at RootBSD. I am trying to test MAC portacl with some user-ran jail scenarios. To get it running, since 7.2 does not come with options MAC enabled by default was to rebuild the kernel. I did the following:

# MAC kernel config
grep -v '^#' /usr/src/sys/i386/conf/MAC

include GENERIC
ident MACWO

options MAC

# compile & install
cd /usr/src
make buildkernel KERNCONF=MAC
make installkernel KERNCONF=MAC KODIR=/boot/mac

# loader changes
cat /boot/loader.conf
kern.hz="100"
mac_portacl_load="YES"

# and reboot
nextboot -k mac
reboot



Everything compiled successfully and the reboot occurred. Here's the next steps:

[2136] ~> uname -i
MACWO
[2136] ~> kldstat
Id Refs Address Size Name
1 5 0xc0400000 a11198 kernel
2 1 0xc0e12000 3ad8 mac_portacl.ko
3 1 0xc27fe000 4000 nullfs.ko
4 1 0xc2834000 4000 fdescfs.ko
[2136] ~> sysctl -a security.mac
security.mac.max_slots: 4
security.mac.version: 3
security.mac.mmap_revocation_via_cow: 0
security.mac.mmap_revocation: 1
security.mac.portacl.rules:
security.mac.portacl.port_high: 1023
security.mac.portacl.autoport_exempt: 1
security.mac.portacl.suser_exempt: 1
security.mac.portacl.enabled: 1


So, it seems the correct kernel is in use, the portacl module is loaded, and some default sysctl are enabled. Now, let's get a new rule setup to allow my account to run something on 80/TCP:

[2136] ~> id
uid=1001(foo) gid=0(wheel) groups=0(wheel)
[2136] ~> sudo sysctl security.mac.portacl.rules=uid:1001:tcp:80
Password:
security.mac.portacl.rules: -> uid:1001:tcp:80


I ran netstat to see if anything else was bound to 80/TCP, but nothing showed up. And, now for the test!

[2136] ~> nc -l 80
nc: Permission denied


:-(

While I don't document it here, I tried also running sshd on port 80 with debugging. It spit out a permission denied, too. For kicks, I tried to compile in the module.

[2136] ~> grep -v '^#' /usr/src/sys/i386/conf/MAC

include GENERIC
ident MACWI

options MAC

options MAC_PORTACL # Network port access control policy

# compile & install (same)

# loader changes
cat /boot/loader.conf
kern.hz="100"

# and reboot
nextboot -k mac
reboot


Let's verify again:

[2136] ~> uname -i
MACWI
[2136] ~> kldstat
Id Refs Address Size Name
1 3 0xc0400000 a12e94 kernel
2 1 0xc2825000 4000 nullfs.ko
3 1 0xc285a000 4000 fdescfs.ko
[2136] ~> sysctl -a security.mac
security.mac.max_slots: 4
security.mac.version: 3
security.mac.mmap_revocation_via_cow: 0
security.mac.mmap_revocation: 1
security.mac.portacl.rules:
security.mac.portacl.port_high: 1023
security.mac.portacl.autoport_exempt: 1
security.mac.portacl.suser_exempt: 1
security.mac.portacl.enabled: 1


This looks promising. Let's create the rule:

[2136] ~> id
uid=1001(foo) gid=0(wheel) groups=0(wheel)
[2136] ~> sudo sysctl security.mac.portacl.rules=uid:1001:tcp:80
Password:
security.mac.portacl.rules: -> uid:1001:tcp:80


And, now for the test...

[2136] ~> nc -l 80
nc: Permission denied


Same error again. What gives?

UPDATE:
@sourcehosting suggested the following:
truss -fa -o /tmp/nc.log /usr/bin/nc -l 80

Which revealed this:
1564: socket(PF_INET,SOCK_STREAM,6) = 4 (0x4)
1564: setsockopt(0x4,0xffff,0x200,0xbfbfc9f4,0x4,0x6c) = 0 (0x0)
1564: bind(4,{ AF_INET 0.0.0.0:80 },16) ERR#13 'Permission denied'
1564: close(4) = 0 (0x0)
1564: write(2,"nc: ",4) = 4 (0x4)
1564: write(2,"Permission denied\n",18) = 18 (0x12)


So, I dunno if the 0.0.0.0 address is a problem or not...

UPDATE 2 (WITH FIX!):
@sourcehosting came in with the win!

The man page and handbook both mentioned disabling the high and low reserved port ranges.

portacl(4):
In order to enable the mac_portacl policy, MAC policy must be enforced on
sockets (see mac(4)), and the port(s) protected by mac_portacl must not
be included in the range specified by the
net.inet.ip.portrange.reservedlow and net.inet.ip.portrange.reservedhigh
sysctl(8) MIBs.


MAC portacl Handbook:
By default, on UNIX®-like systems, ports fewer than 1024 can only be used by/bound to privileged processes, i.e. those run as root. For mac_portacl(4) to allow non-privileged processes to bind to ports below 1024 this standard UNIX restriction has to be disabled. This can be accomplished by setting the sysctl(8) variables net.inet.ip.portrange.reservedlow and net.inet.ip.portrange.reservedhigh to zero.


Here's what I had:

[2136] ~> sysctl -a net.inet.ip.portrange | grep resernet.inet.ip.portrange.reservedlow: 0
net.inet.ip.portrange.reservedhigh: 1023


And, here's the fix:

[2136] ~> sudo sysctl net.inet.ip.portrange.reservedlow=0 net.inet.ip.portrange.reservedhigh=0
Password:
net.inet.ip.portrange.reservedlow: 0 -> 0
net.inet.ip.portrange.reservedhigh: 1023 -> 0


And, test:

# other terminal connecting to IP on 80, typing 'hello'
[2136] ~> nc -l 80
hello


WHOOP!

Blog Archive