summaryrefslogtreecommitdiffstats
path: root/sys/netinet/in.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-04-24 09:54:46 +0000
committerrwatson <rwatson@FreeBSD.org>2009-04-24 09:54:46 +0000
commit5eaa7f128c08a07ea6a9f514f712025d2ba2fad1 (patch)
tree79056bc706262cc40813daf7ff1618953e424daf /sys/netinet/in.c
parent9d122f9cbab9d826e0409d7b1934c5ed20f9af86 (diff)
downloadFreeBSD-src-5eaa7f128c08a07ea6a9f514f712025d2ba2fad1.zip
FreeBSD-src-5eaa7f128c08a07ea6a9f514f712025d2ba2fad1.tar.gz
Relocate permissions checking code in in_control() to before the body
of the implementation of ioctls. This makes the mapping of ioctls to specific privileges more explicit, and also simplifies the implementation by reducing the use of FALLTHROUGH handling in switch. While this is not intended to be a functional change, it does mean that certain privilege checks are now performed earlier, so EPERM might be returned in preference to EADDRNOTAVAIL for management ioctls that could have failed for both reasons. MFC after: 3 weeks
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r--sys/netinet/in.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index e9e9d61..8d5f946 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -280,6 +280,31 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
return (EADDRNOTAVAIL);
/*
+ * Security checks before we get involved in any work.
+ */
+ switch (cmd) {
+ case SIOCAIFADDR:
+ case SIOCSIFADDR:
+ case SIOCSIFBRDADDR:
+ case SIOCSIFNETMASK:
+ case SIOCSIFDSTADDR:
+ if (td != NULL) {
+ error = priv_check(td, PRIV_NET_ADDIFADDR);
+ if (error)
+ return (error);
+ }
+ break;
+
+ case SIOCDIFADDR:
+ if (td != NULL) {
+ error = priv_check(td, PRIV_NET_DELIFADDR);
+ if (error)
+ return (error);
+ }
+ break;
+ }
+
+ /*
* Find address for this interface, if it exists.
*
* If an alias address was specified, find that one instead of the
@@ -334,13 +359,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
case SIOCSIFADDR:
case SIOCSIFNETMASK:
case SIOCSIFDSTADDR:
- if (td != NULL) {
- error = priv_check(td, (cmd == SIOCDIFADDR) ?
- PRIV_NET_DELIFADDR : PRIV_NET_ADDIFADDR);
- if (error)
- return (error);
- }
-
if (ia == NULL) {
ia = (struct in_ifaddr *)
malloc(sizeof *ia, M_IFADDR, M_WAITOK | M_ZERO);
@@ -376,13 +394,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
break;
case SIOCSIFBRDADDR:
- if (td != NULL) {
- error = priv_check(td, PRIV_NET_ADDIFADDR);
- if (error)
- return (error);
- }
- /* FALLTHROUGH */
-
case SIOCGIFADDR:
case SIOCGIFNETMASK:
case SIOCGIFDSTADDR:
OpenPOWER on IntegriCloud