# 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!