The ancient and outdated concept of "privileged ports" in UNIX-type

OSes has probably caused more problems than it ever solved. Allow the
user to retire the old behavior by specifying their own privileged
range with,

  net.inet.ip.portrange.reservedhigh  default = IPPORT_RESERVED - 1
  net.inet.ip.portrange.reservedlo    default = 0

Now you can run that webserver without ever needing root at all. Or
just imagine, an ftpd that can really drop privileges, rather than
just set the euid, and still do PORT data transfers from 20/tcp.

Two edge cases to note,

  # sysctl net.inet.ip.portrange.reservedhigh=0

Opens all ports to everyone, and,

  # sysctl net.inet.ip.portrange.reservedhigh=65535

Locks all network activity to root only (which could actually have
been achieved before with ipfw(8), but is somewhat more
complicated).

For those who stick to the old religion that 0-1023 belong to root and
root alone, don't touch the knobs (or even lock them by raising
securelevel(8)), and nothing changes.
This commit is contained in:
Crist J. Clark 2003-02-21 05:28:27 +00:00
parent 0bc8118778
commit b0d226932e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=111205

View File

@ -96,6 +96,14 @@ int ipport_lastauto = IPPORT_HILASTAUTO; /* 65535 */
int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 49152 */
int ipport_hilastauto = IPPORT_HILASTAUTO; /* 65535 */
/*
* Reserved ports accessible only to root. There are significant
* security considerations that must be accounted for when changing these,
* but the security benefits can be great. Please be careful.
*/
int ipport_reservedhigh = IPPORT_RESERVED - 1; /* 1023 */
int ipport_reservedlow = 0;
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
@ -132,6 +140,10 @@ SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hifirst, CTLTYPE_INT|CTLFLAG_RW,
&ipport_hifirstauto, 0, &sysctl_net_ipport_check, "I", "");
SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW,
&ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", "");
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedhigh,
CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedhigh, 0, "");
SYSCTL_INT(_net_inet_ip_portrange, OID_AUTO, reservedlow,
CTLFLAG_RW|CTLFLAG_SECURE, &ipport_reservedlow, 0, "");
/*
* in_pcb.c: manage the Protocol Control Blocks.
@ -288,8 +300,9 @@ in_pcbbind_setup(inp, nam, laddrp, lportp, td)
if (lport) {
struct inpcb *t;
/* GROSS */
if (ntohs(lport) < IPPORT_RESERVED && td &&
suser_cred(td->td_ucred, PRISON_ROOT))
if (ntohs(lport) <= ipport_reservedhigh &&
ntohs(lport) >= ipport_reservedlow &&
td && suser_cred(td->td_ucred, PRISON_ROOT))
return (EACCES);
if (td && jailed(td->td_ucred))
prison = 1;