Subject: new sysctl - privilaged ports runtime option?
To: None <tech-kern@netbsd.org>
From: Joe Reed <jnr@po.cwru.edu>
List: tech-kern
Date: 08/06/2002 15:19:08
--------------Boundary-00=_W3VFASR6F7TGC74BXQ0R
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
hi
i've wondered for a while now why we have the <1024 privelaged port
restriction a compile-time option and not a runtime one. in my opinion,
there is no reason why one should have to compile a kernel of a freshly
installed system just to run processes like sendmail and httpd as a
unprivilaged user. we have net.inet{,6}.ip{,6}.{gateway,forwarding} as
runtime settings, why not the reserved ports?
i've added 2 new sysctl's net.inet.ip.reservedports and
net.inet6.ip6.reservedports which when set to 0, remove the <1024
restriction, and when set to 1 enforce it.
the kernel configuration option NOPRIVPORTS is used to set the default value
for these sysctl's.
since the change only affects the bind(2) operation, i don't believe this
will adversely affect the performance of the network operations.
i'd like some feedback on this before i send-pr it. i think i've got this
right, but i'd like to hear from people who know more than i:
1) is this a worthwhile change? are there other issues i have not
considered?
2) is this the correct implementation for what i'm trying to accomplish?
i've attached diffs of src/sys/netinet/ and src/sys/netinet6 which contain
all the changes for the implementation of the 2 sysctls.
--joe
-------------------------------------------------------
--------------Boundary-00=_W3VFASR6F7TGC74BXQ0R
Content-Type: text/plain;
charset="iso-8859-1";
name="netinet.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="netinet.diff"
Index: in.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in.h,v
retrieving revision 1.58
diff -u -r1.58 in.h
--- in.h 2002/05/13 13:34:32 1.58
+++ in.h 2002/08/06 17:28:44
@@ -379,7 +379,8 @@
#define IPCTL_LOWPORTMAX 17 /* maximum reserved port */
#define IPCTL_MAXFRAGPACKETS 18 /* max packets reassembly queue */
#define IPCTL_GRE_TTL 19 /* default TTL for gre encap packet */
-#define IPCTL_MAXID 20
+#define IPCTL_RESERVEDPORTS 20 /* reserved ports toggle */
+#define IPCTL_MAXID 21
#define IPCTL_NAMES { \
{ 0, 0 }, \
@@ -402,6 +403,7 @@
{ "lowportmax", CTLTYPE_INT }, \
{ "maxfragpackets", CTLTYPE_INT }, \
{ "grettl", CTLTYPE_INT }, \
+ { "reservedports", CTLTYPE_INT} , \
}
#endif /* !_POSIX_C_SOURCE && !_XOPEN_SOURCE */
Index: in_pcb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/in_pcb.c,v
retrieving revision 1.79
diff -u -r1.79 in_pcb.c
--- in_pcb.c 2002/06/11 19:39:59 1.79
+++ in_pcb.c 2002/08/06 17:28:44
@@ -223,9 +223,7 @@
struct sockaddr_in *sin;
u_int16_t lport = 0;
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
-#ifndef IPNOPRIVPORTS
int error;
-#endif
if (TAILQ_FIRST(&in_ifaddr) == 0)
return (EADDRNOTAVAIL);
@@ -264,12 +262,12 @@
}
if (lport) {
struct inpcb *t;
-#ifndef IPNOPRIVPORTS
- /* GROSS */
- if (ntohs(lport) < IPPORT_RESERVED &&
- (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))))
- return (EACCES);
-#endif
+
+ if (reservedports)
+ if (ntohs(lport) < IPPORT_RESERVED &&
+ (p == 0 || (error = suser(p->p_ucred, &p->p_acflag))))
+ return (EACCES);
+
if (so->so_uid && !IN_MULTICAST(sin->sin_addr.s_addr)) {
t = in_pcblookup_port(table, sin->sin_addr, lport, 1);
/*
@@ -298,10 +296,10 @@
u_int16_t *lastport;
if (inp->inp_flags & INP_LOWPORT) {
-#ifndef IPNOPRIVPORTS
- if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
- return (EACCES);
-#endif
+ if (reservedports)
+ if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
+ return (EACCES);
+
min = lowportmin;
max = lowportmax;
lastport = &table->inpt_lastlow;
Index: ip_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_input.c,v
retrieving revision 1.154
diff -u -r1.154 ip_input.c
--- ip_input.c 2002/06/30 22:40:34 1.154
+++ ip_input.c 2002/08/06 17:28:44
@@ -197,6 +197,12 @@
int ipprintfs = 0;
#endif
+#ifdef NOPRIVPORTS
+int reservedports = 0;
+#else
+int reservedports = 1;
+#endif
+
struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
extern struct domain inetdomain;
@@ -1833,9 +1839,7 @@
error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmin);
if (anonportmin >= anonportmax || anonportmin < 0
|| anonportmin > 65535
-#ifndef IPNOPRIVPORTS
- || anonportmin < IPPORT_RESERVED
-#endif
+ || ( reservedports && anonportmin < IPPORT_RESERVED)
) {
anonportmin = old;
return (EINVAL);
@@ -1846,9 +1850,7 @@
error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmax);
if (anonportmin >= anonportmax || anonportmax < 0
|| anonportmax > 65535
-#ifndef IPNOPRIVPORTS
- || anonportmax < IPPORT_RESERVED
-#endif
+ || ( reservedports && anonportmax < IPPORT_RESERVED)
) {
anonportmax = old;
return (EINVAL);
@@ -1889,8 +1891,9 @@
&ip_gre_ttl));
#endif
-#ifndef IPNOPRIVPORTS
case IPCTL_LOWPORTMIN:
+ if (reservedports == 0)
+ return (EOPNOTSUPP);
old = lowportmin;
error = sysctl_int(oldp, oldlenp, newp, newlen, &lowportmin);
if (lowportmin >= lowportmax
@@ -1902,6 +1905,8 @@
}
return (error);
case IPCTL_LOWPORTMAX:
+ if (reservedports == 0)
+ return (EOPNOTSUPP);
old = lowportmax;
error = sysctl_int(oldp, oldlenp, newp, newlen, &lowportmax);
if (lowportmin >= lowportmax
@@ -1912,11 +1917,13 @@
return (EINVAL);
}
return (error);
-#endif
case IPCTL_MAXFRAGPACKETS:
return (sysctl_int(oldp, oldlenp, newp, newlen,
&ip_maxfragpackets));
+
+ case IPCTL_RESERVEDPORTS:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &reservedports));
default:
return (EOPNOTSUPP);
Index: ip_var.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_var.h,v
retrieving revision 1.48
diff -u -r1.48 ip_var.h
--- ip_var.h 2002/06/30 22:40:35 1.48
+++ ip_var.h 2002/08/06 17:28:44
@@ -200,6 +200,7 @@
extern int anonportmax; /* maximum ephemeral port */
extern int lowportmin; /* minimum reserved port */
extern int lowportmax; /* maximum reserved port */
+extern int reservedports; /* reserved port toggle */
extern struct rttimer_queue *ip_mtudisc_timeout_q;
#ifdef GATEWAY
extern int ip_maxflows;
--------------Boundary-00=_W3VFASR6F7TGC74BXQ0R
Content-Type: text/plain;
charset="iso-8859-1";
name="netinet6.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="netinet6.diff"
Index: in6.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6.h,v
retrieving revision 1.41
diff -u -r1.41 in6.h
--- in6.h 2002/06/08 21:22:31 1.41
+++ in6.h 2002/08/06 17:30:42
@@ -544,7 +544,8 @@
#define IPV6CTL_MAXFRAGS 41 /* max fragments */
/* New entries should be added here from current IPV6CTL_MAXID value. */
/* to define items, should talk with KAME guys first, for *BSD compatibility */
-#define IPV6CTL_MAXID 42
+#define IPV6CTL_RESERVEDPORTS 42
+#define IPV6CTL_MAXID 43
#define IPV6CTL_NAMES { \
{ 0, 0 }, \
@@ -589,6 +590,7 @@
{ 0, 0 }, \
{ 0, 0 }, \
{ "maxfrags", CTLTYPE_INT }, \
+ { "reservedports", CTLTYPE_INT }, \
}
#endif /* !_POSIX_C_SOURCE && !_XOPEN_SOURCE */
Index: in6_pcb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_pcb.c,v
retrieving revision 1.49
diff -u -r1.49 in6_pcb.c
--- in6_pcb.c 2002/06/11 19:40:00 1.49
+++ in6_pcb.c 2002/08/06 17:30:42
@@ -237,18 +237,18 @@
}
}
if (lport) {
-#ifndef IPNOPRIVPORTS
- int priv;
-
- /*
- * NOTE: all operating systems use suser() for
- * privilege check! do not rewrite it into SS_PRIV.
- */
- priv = (p && !suser(p->p_ucred, &p->p_acflag)) ? 1 : 0;
- /* GROSS */
- if (ntohs(lport) < IPV6PORT_RESERVED && !priv)
- return(EACCES);
-#endif
+ if (ip6_reservedports) {
+ int priv;
+
+ /*
+ * NOTE: all operating systems use suser() for
+ * privilege check! do not rewrite it into SS_PRIV.
+ */
+ priv = (p && !suser(p->p_ucred, &p->p_acflag)) ? 1 : 0;
+ /* GROSS */
+ if (ntohs(lport) < IPV6PORT_RESERVED && !priv)
+ return(EACCES);
+ }
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
/* should check this but we can't ... */
Index: in6_proto.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_proto.c,v
retrieving revision 1.43
diff -u -r1.43 in6_proto.c
--- in6_proto.c 2002/06/09 14:43:12 1.43
+++ in6_proto.c 2002/08/06 17:30:42
@@ -254,6 +254,12 @@
#endif /* GATEWAY6 */
#endif /* !IPV6FORWARDING */
+#ifndef NOPRIVPORTS
+int ip6_reservedports = 1;
+#else
+int ip6_reservedports = 0;
+#endif
+
#ifndef IPV6_SENDREDIRECTS
#define IPV6_SENDREDIRECTS 1
#endif
Index: in6_src.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/in6_src.c,v
retrieving revision 1.13
diff -u -r1.13 in6_src.c
--- in6_src.c 2002/06/08 20:06:44 1.13
+++ in6_src.c 2002/08/06 17:30:42
@@ -353,12 +353,12 @@
wild = IN6PLOOKUP_WILDCARD;
if (in6p->in6p_flags & IN6P_LOWPORT) {
-#ifndef IPNOPRIVPORTS
- struct proc *p = curproc; /* XXX */
-
- if (p == 0 || (suser(p->p_ucred, &p->p_acflag) != 0))
- return (EACCES);
-#endif
+ if (ip6_reservedports) {
+ struct proc *p = curproc; /* XXX */
+
+ if (p == 0 || (suser(p->p_ucred, &p->p_acflag) != 0))
+ return (EACCES);
+ }
min = ip6_lowportmin;
max = ip6_lowportmax;
} else {
Index: ip6_input.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_input.c,v
retrieving revision 1.57
diff -u -r1.57 ip6_input.c
--- ip6_input.c 2002/06/30 22:40:39 1.57
+++ ip6_input.c 2002/08/06 17:30:42
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_input.c,v 1.57 2002/06/30 22:40:39 thorpej Exp $ */
+/* $NetBSD: ip6_input.c,v 1.56 2002/06/09 14:43:12 itojun Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.57 2002/06/30 22:40:39 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.56 2002/06/09 14:43:12 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@@ -1478,9 +1478,7 @@
&ip6_anonportmin);
if (ip6_anonportmin >= ip6_anonportmax || ip6_anonportmin < 0 ||
ip6_anonportmin > 65535
-#ifndef IPNOPRIVPORTS
- || ip6_anonportmin < IPV6PORT_RESERVED
-#endif
+ || (ip6_reservedports && ip6_anonportmin < IPV6PORT_RESERVED)
) {
ip6_anonportmin = old;
return (EINVAL);
@@ -1492,16 +1490,16 @@
&ip6_anonportmax);
if (ip6_anonportmin >= ip6_anonportmax || ip6_anonportmax < 0 ||
ip6_anonportmax > 65535
-#ifndef IPNOPRIVPORTS
- || ip6_anonportmax < IPV6PORT_RESERVED
-#endif
+ || (ip6_reservedports && ip6_anonportmax < IPV6PORT_RESERVED)
) {
ip6_anonportmax = old;
return (EINVAL);
}
return (error);
-#ifndef IPNOPRIVPORTS
case IPV6CTL_LOWPORTMIN:
+ if (ip6_reservedports == 0)
+ return (EOPNOTSUPP);
+
old = ip6_lowportmin;
error = sysctl_int(oldp, oldlenp, newp, newlen,
&ip6_lowportmin);
@@ -1513,6 +1511,9 @@
}
return (error);
case IPV6CTL_LOWPORTMAX:
+ if (ip6_reservedports == 0)
+ return (EOPNOTSUPP);
+
old = ip6_lowportmax;
error = sysctl_int(oldp, oldlenp, newp, newlen,
&ip6_lowportmax);
@@ -1523,9 +1524,11 @@
return (EINVAL);
}
return (error);
-#endif
case IPV6CTL_MAXFRAGS:
return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_maxfrags);
+ case IPV6CTL_RESERVEDPORTS:
+ return sysctl_int(oldp, oldlenp, newp, newlen,
+ &ip6_reservedports);
default:
return EOPNOTSUPP;
}
Index: ip6_var.h
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/ip6_var.h,v
retrieving revision 1.22
diff -u -r1.22 ip6_var.h
--- ip6_var.h 2002/06/30 22:40:40 1.22
+++ ip6_var.h 2002/08/06 17:30:44
@@ -1,4 +1,4 @@
-/* $NetBSD: ip6_var.h,v 1.22 2002/06/30 22:40:40 thorpej Exp $ */
+/* $NetBSD: ip6_var.h,v 1.21 2002/06/08 21:22:33 itojun Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@@ -222,6 +222,7 @@
extern int ip6_rr_prune; /* router renumbering prefix
* walk list every 5 sec. */
extern int ip6_v6only;
+extern int ip6_reservedports; /* reserved ports */
extern struct socket *ip6_mrouter; /* multicast routing daemon */
extern int ip6_sendredirects; /* send IP redirects when forwarding? */
--------------Boundary-00=_W3VFASR6F7TGC74BXQ0R--