From baf84f0ae5e25ae2d46fba3c9aafca24ba8e6074 Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Sun, 4 Nov 2018 17:55:53 +0800 Subject: [PATCH] net/if: Call if_ioctl() if the protocol didn't handle the ioctl This allows for a non-interface socket (like AF_LOCAL which ifconfig(8) now uses since commit d4e856128472e2e79172aebf65f19f527ac0010f) to use a broader class of interface ioctls. This fixes the regression in ifconfig(8) that is introduced by the above mentioned commit, which changed ifconfig(8) to use AF_LOCAL socket by default and thus caused some ioctls failures. For example: dfly# ifconfig tap0 create dfly# ifconfig tap0 up dfly# ifconfig bridge0 create dfly# ifconfig bridge0 addm tap0 [before] dfly# ifconfig bridge0 bridge0: flags=8002 mtu 1500 ether be:48:6d:6d:a6:1f groups: bridge [after] dfly# ifconfig bridge0 bridge0: flags=8002 mtu 1500 ether be:48:6d:6d:a6:1f priority 32768 hellotime 2 fwddelay 15 maxage 20 member: tap0 flags=3 groups: bridge Do not pass the SIOCSIF{ADDR,BRDADDR,DSTADDR,NETMASK} iotcls to the drivers because they may assume these ioctls come from an already privileged layer and thus skip credentials check and input validation. While there, improve a NULL check. Taken-from: FreeBSD (r190151, r255442) Reviewed-by: dillon, sephe --- sys/net/if.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/sys/net/if.c b/sys/net/if.c index 4a6af4e47c..f1e51723dc 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -2223,7 +2223,7 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) error = priv_check_cred(cred, PRIV_ROOT, 0); if (error) break; - if (ifp->if_ioctl == 0) { + if (ifp->if_ioctl == NULL) { error = EOPNOTSUPP; break; } @@ -2291,6 +2291,26 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct ucred *cred) } error = so_pru_control_direct(so, cmd, data, ifp); + /* + * If the socket control method returns EOPNOTSUPP, pass the + * request directly to the interface. + * + * Exclude the SIOCSIF{ADDR,BRDADDR,DSTADDR,NETMASK} ioctls, + * because drivers may trust these ioctls to come from an + * already privileged layer and thus do not perform credentials + * checks or input validation. + */ + if (error == EOPNOTSUPP && + ifp->if_ioctl != NULL && + cmd != SIOCSIFADDR && + cmd != SIOCSIFBRDADDR && + cmd != SIOCSIFDSTADDR && + cmd != SIOCSIFNETMASK) { + ifnet_serialize_all(ifp); + error = ifp->if_ioctl(ifp, cmd, data, cred); + ifnet_deserialize_all(ifp); + } + if ((oif_flags ^ ifp->if_flags) & IFF_UP) { #ifdef INET6 DELAY(100);/* XXX: temporary workaround for fxp issue*/ -- 2.41.0