On Tue, Apr 18, 2023 at 10:44:36PM +0000, Klemens Nanni wrote:
> On Sat, Apr 15, 2023 at 01:48:02PM +0000, Klemens Nanni wrote:
> > On Fri, Apr 14, 2023 at 11:33:18PM +0000, Klemens Nanni wrote:
> > > All cases do the same check up first, so merge it before the switch.
> 
> Committed.
> 
> > > It could be hoisted further in both in_ioctl() and 
> > > in_ioctl_change_ifaddr(),
> > > but that meant a change in errno return semantic, so leave it for now.
> > 
> > in6.c already has the privilege check as early as possible, so here's a diff
> > that simplifies in.c to match in6.c.
> > 
> > I can't think of a scenario where returning EPERM (this diff) instead of
> > whatever errno the currently earlier sanity checks yield would break.
> > 
> > It is an unprivileged ioctl call in the first place, so EPERM as soon as
> > possible makes sense to me.
> 
> Better and rebased diff, no locks taken for unprivileged calls that *will*
> fail, EPERM is returned first in IPv4 like IPv6 already does, nicely syncing
> the ioctl handlers.
> 
> Feedback? OK?

Ping.  Rebased onto the error cleanup.


Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.183
diff -u -p -r1.183 in.c
--- netinet/in.c        21 Apr 2023 00:41:13 -0000      1.183
+++ netinet/in.c        23 Apr 2023 23:31:00 -0000
@@ -84,8 +84,8 @@
 
 void in_socktrim(struct sockaddr_in *);
 
-int in_ioctl_set_ifaddr(u_long, caddr_t, struct ifnet *, int);
-int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *, int);
+int in_ioctl_set_ifaddr(u_long, caddr_t, struct ifnet *);
+int in_ioctl_change_ifaddr(u_long, caddr_t, struct ifnet *);
 int in_ioctl_get(u_long, caddr_t, struct ifnet *);
 void in_purgeaddr(struct ifaddr *);
 int in_addhost(struct in_ifaddr *, struct sockaddr_in *);
@@ -199,9 +199,8 @@ in_sa2sin(struct sockaddr *sa, struct so
 int
 in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
 {
-       int privileged;
+       int privileged = 0;
 
-       privileged = 0;
        if ((so->so_state & SS_PRIV) != 0)
                privileged++;
 
@@ -235,10 +234,14 @@ in_ioctl(u_long cmd, caddr_t data, struc
        case SIOCGIFBRDADDR:
                return in_ioctl_get(cmd, data, ifp);
        case SIOCSIFADDR:
-               return in_ioctl_set_ifaddr(cmd, data, ifp, privileged);
+               if (!privileged)
+                       return (EPERM);
+               return in_ioctl_set_ifaddr(cmd, data, ifp);
        case SIOCAIFADDR:
        case SIOCDIFADDR:
-               return in_ioctl_change_ifaddr(cmd, data, ifp, privileged);
+               if (!privileged)
+                       return (EPERM);
+               return in_ioctl_change_ifaddr(cmd, data, ifp);
        case SIOCSIFNETMASK:
        case SIOCSIFDSTADDR:
        case SIOCSIFBRDADDR:
@@ -247,6 +250,9 @@ in_ioctl(u_long cmd, caddr_t data, struc
                return (EOPNOTSUPP);
        }
 
+       if (!privileged)
+               return (EPERM);
+
        if (ifr->ifr_addr.sa_family == AF_INET) {
                error = in_sa2sin(&ifr->ifr_addr, &sin);
                if (error)
@@ -275,11 +281,6 @@ in_ioctl(u_long cmd, caddr_t data, struc
                goto err;
        }
 
-       if (!privileged) {
-               error = EPERM;
-               goto err;
-       }
-
        switch (cmd) {
        case SIOCSIFDSTADDR:
                if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
@@ -335,8 +336,7 @@ err:
 }
 
 int
-in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp,
-    int privileged)
+in_ioctl_set_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
 {
        struct ifreq *ifr = (struct ifreq *)data;
        struct ifaddr *ifa;
@@ -348,9 +348,6 @@ in_ioctl_set_ifaddr(u_long cmd, caddr_t 
        if (cmd != SIOCSIFADDR)
                panic("%s: invalid ioctl %lu", __func__, cmd);
 
-       if (!privileged)
-               return (EPERM);
-
        error = in_sa2sin(&ifr->ifr_addr, &sin);
        if (error)
                return (error);
@@ -395,8 +392,7 @@ in_ioctl_set_ifaddr(u_long cmd, caddr_t 
 }
 
 int
-in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp,
-    int privileged)
+in_ioctl_change_ifaddr(u_long cmd, caddr_t data, struct ifnet *ifp)
 {
        struct ifaddr *ifa;
        struct in_ifaddr *ia = NULL;
@@ -411,9 +407,6 @@ in_ioctl_change_ifaddr(u_long cmd, caddr
                if (error)
                        return (error);
        }
-
-       if (!privileged)
-               return (EPERM);
 
        KERNEL_LOCK();
        NET_LOCK();
Index: netinet6/in6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.261
diff -u -p -r1.261 in6.c
--- netinet6/in6.c      21 Apr 2023 00:41:13 -0000      1.261
+++ netinet6/in6.c      23 Apr 2023 23:31:35 -0000
@@ -196,9 +196,8 @@ in6_sa2sin6(struct sockaddr *sa, struct 
 int
 in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
 {
-       int privileged;
+       int privileged = 0;
 
-       privileged = 0;
        if ((so->so_state & SS_PRIV) != 0)
                privileged++;
 

Reply via email to