Date: Wed, 26 Mar 1997 00:07:51 -0600 (CST) From: tqbf@babel.enteract.com To: freebsd-security@freebsd.org Subject: Privileged ports... Message-ID: <19970326060751.3783.qmail@smtp.enteract.com>
next in thread | raw e-mail | index | archive | help
As part of a gradual effort to rid my kernel of suser() calls, I whipped up a quick patch to in_pcb.c that configurably removes the superuser restriction on binding privileged ports. This has the effect of removing the requirement for programs like rlogin and rsh to run with superuser privs, thus eliminating a few more SUID programs. In place of suser(), I've inserted two new sysctl OIDs under net.inet.ip - resv_uid and resv_gid. Any process running with an effective UID of "resv_uid" or belonging to group "resv_gid" can now bind low ports. The idea here is to set the system up so that a hole in "rlogin" or "rsh" no longer provides root access - instead, an attacker only has the ability to bind privileged ports. While this is a problem on some networks (obviously this breaks host trust), it's a benefit to networks that don't rely on the concept in the first place. Meanwhile, privileged ports are as restricted as they were before - the restrictions are just configurable. I'm interested in comments and suggestions regarding the implementation of more granularity in kernel-level privilege. Thanks to Guido van Rooij for showing me how FreeBSD's sysctl works. *** in_pcb.c-pre-tqbf Tue Mar 25 23:09:13 1997 --- in_pcb.c Tue Mar 25 23:39:34 1997 *************** *** 64,67 **** --- 64,69 ---- static void in_pcbinshash __P((struct inpcb *)); static void in_rtchange __P((struct inpcb *, int)); + static int in_okresvport __P((struct proc *)); + static int cred_isingroup __P((gid_t, struct proc *)); /* *************** *** 189,194 **** /* GROSS */ if (ntohs(lport) < IPPORT_RESERVED && ! (error = suser(p->p_ucred, &p->p_acflag))) ! return (EACCES); t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, sin->sin_addr, lport, wild); --- 191,197 ---- /* GROSS */ if (ntohs(lport) < IPPORT_RESERVED && ! !in_okresvport(p)) ! return (EACCES); ! t = in_pcblookup(inp->inp_pcbinfo, zeroin_addr, 0, sin->sin_addr, lport, wild); *************** *** 209,213 **** lastport = &inp->inp_pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { ! if (error = suser(p->p_ucred, &p->p_acflag)) return (EACCES); first = ipport_lowfirstauto; /* 1023 */ --- 212,216 ---- lastport = &inp->inp_pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { ! if (!in_okresvport(p)) return (EACCES); first = ipport_lowfirstauto; /* 1023 */ *************** *** 747,749 **** --- 750,801 ---- LIST_INSERT_HEAD(head, inp, inp_hash); splx(s); + } + + static int resv_uid; + static int resv_gid; + + SYSCTL_INT(_net_inet_ip, + IPCTL_RESVUID, + resv_uid, + CTLFLAG_RW, + &resv_uid, + 0, + ""); + + SYSCTL_INT(_net_inet_ip, + IPCTL_RESVGID, + resv_gid, + CTLFLAG_RW, + &resv_gid, + 0, + ""); + + static int in_okresvport(struct proc *prc) { + int error; + + error = suser(prc->p_ucred, &prc->p_acflag); + if(!error) + return(1); + + if(resv_uid && + prc->p_ucred->cr_uid == resv_uid) + return(1); + + if(resv_gid && + cred_isingroup((gid_t) resv_gid, prc)) + return(1); + + return(0); + } + + int cred_isingroup(gid_t gid, struct proc *prc) { + struct ucred *uc = prc->p_ucred; + short i; + + for(i = 0; i < uc->cr_ngroups; i++) { + if(gid == uc->cr_groups[i]) + return(1); + } + + return(0); } *** in.h-pre-tqbf Tue Mar 25 23:46:16 1997 --- in.h Tue Mar 25 23:48:51 1997 *************** *** 304,307 **** --- 304,309 ---- #define IPCTL_INTRQDROPS 11 /* number of netisr q drops */ #define IPCTL_MAXID 12 + #define IPCTL_RESVUID 20 /* UID to bind privileged ports */ + #define IPCTL_RESVGID 21 /* GID to bind privileged ports */ #define IPCTL_NAMES { \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970326060751.3783.qmail>