From: Arnd Bergmann <arnd at arndb.de> This series is a follow-up to the series for removing compat_alloc_user_space() and copy_in_user() that has now been merged. I wanted to be sure I address all the ways that 'struct ifreq' is used in device drivers through .ndo_do_ioctl, originally to prove that my approach of changing the struct definition was correct, but then I discarded that approach and went on anyway. Roughly, the contents here are: - split out all the users of SIOCDEVPRIVATE ioctls into a separate ndo_siocdevprivate callback, to better see what gets used where - fix compat handling for those drivers that pass data directly inside of 'ifreq' rather than using an indirect ifr_data pointer - remove unreachable code in ndo_ioctl handlers that relies on command codes we never pass into that, in particular for wireless drivers - split out the ethernet specific ioctls into yet another ndo_eth_ioctl callback, as these are by far the most common use of ndo_do_ioctl today. I considered splitting them further into MII and timestamp controls, but went with the simpler change for now. - split out bonding and wandev ioctls into separate helpers - rework the bridge handling with a separate callback At this point, only a few oddball things remain in ndo_do_ioctl: appletalk and ieee802154 pass down SIOCSIFADDR/SIOCGIFADDR and some wireless drivers have completely dead code. I have thoroughly compile tested this on randconfig builds, but not done any notable runtime testing, so please review. All of it is also available as part of a larger branch at https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git \ compat-alloc-user-space-12 Changes since v2: - rebase to net-next - fix qeth regression - Cc driver maintainers for each patch and in cover letter Changes since v1: - rebase to linux-5.14-rc2 - add conversion for ndo_siowandev, bridge and bonding drivers - leave broken wifi drivers untouched for now Link: https://lore.kernel.org/netdev/20201106221743.3271965-14-arnd at kernel.org/ Arnd Bergmann (31): net: split out SIOCDEVPRIVATE handling from dev_ioctl staging: rtlwifi: use siocdevprivate staging: wlan-ng: use siocdevprivate hostap: use ndo_siocdevprivate bridge: use ndo_siocdevprivate phonet: use siocdevprivate tulip: use ndo_siocdevprivate bonding: use siocdevprivate appletalk: use ndo_siocdevprivate hamachi: use ndo_siocdevprivate tehuti: use ndo_siocdevprivate eql: use ndo_siocdevprivate fddi: use ndo_siocdevprivate net: usb: use ndo_siocdevprivate slip/plip: use ndo_siocdevprivate qeth: use ndo_siocdevprivate cxgb3: use ndo_siocdevprivate hamradio: use ndo_siocdevprivate airo: use ndo_siocdevprivate ip_tunnel: use ndo_siocdevprivate hippi: use ndo_siocdevprivate sb1000: use ndo_siocdevprivate ppp: use ndo_siocdevprivate wan: use ndo_siocdevprivate wan: cosa: remove dead cosa_net_ioctl() function dev_ioctl: pass SIOCDEVPRIVATE data separately dev_ioctl: split out ndo_eth_ioctl net: split out ndo_siowandev ioctl net: socket: return changed ifreq from SIOCDEVPRIVATE net: bridge: move bridge ioctls out of .ndo_do_ioctl net: bonding: move ioctl handling to private ndo operation Documentation/networking/netdevices.rst | 29 +++++ Documentation/networking/timestamping.rst | 6 +- drivers/char/pcmcia/synclink_cs.c | 23 ++-- drivers/infiniband/ulp/ipoib/ipoib_main.c | 8 +- drivers/net/appletalk/ipddp.c | 16 ++- drivers/net/bonding/bond_main.c | 74 ++++++++--- drivers/net/eql.c | 24 ++-- drivers/net/ethernet/3com/3c574_cs.c | 2 +- drivers/net/ethernet/3com/3c59x.c | 4 +- drivers/net/ethernet/8390/ax88796.c | 2 +- drivers/net/ethernet/8390/axnet_cs.c | 2 +- drivers/net/ethernet/8390/pcnet_cs.c | 2 +- drivers/net/ethernet/actions/owl-emac.c | 6 +- drivers/net/ethernet/adaptec/starfire.c | 2 +- drivers/net/ethernet/agere/et131x.c | 2 +- drivers/net/ethernet/allwinner/sun4i-emac.c | 2 +- drivers/net/ethernet/amd/amd8111e.c | 2 +- drivers/net/ethernet/amd/au1000_eth.c | 2 +- drivers/net/ethernet/amd/pcnet32.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 2 +- .../net/ethernet/aquantia/atlantic/aq_main.c | 2 +- drivers/net/ethernet/arc/emac_main.c | 2 +- drivers/net/ethernet/atheros/ag71xx.c | 2 +- drivers/net/ethernet/atheros/alx/main.c | 2 +- .../net/ethernet/atheros/atl1c/atl1c_main.c | 2 +- .../net/ethernet/atheros/atl1e/atl1e_main.c | 2 +- drivers/net/ethernet/atheros/atlx/atl1.c | 2 +- drivers/net/ethernet/atheros/atlx/atl2.c | 2 +- drivers/net/ethernet/broadcom/b44.c | 2 +- drivers/net/ethernet/broadcom/bcm63xx_enet.c | 4 +- drivers/net/ethernet/broadcom/bgmac.c | 2 +- drivers/net/ethernet/broadcom/bnx2.c | 2 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 2 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- .../net/ethernet/broadcom/genet/bcmgenet.c | 2 +- drivers/net/ethernet/broadcom/sb1250-mac.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 2 +- drivers/net/ethernet/cadence/macb_main.c | 4 +- .../net/ethernet/cavium/liquidio/lio_main.c | 2 +- .../ethernet/cavium/liquidio/lio_vf_main.c | 2 +- .../net/ethernet/cavium/octeon/octeon_mgmt.c | 2 +- .../net/ethernet/cavium/thunder/nicvf_main.c | 2 +- drivers/net/ethernet/chelsio/cxgb/cxgb2.c | 2 +- .../net/ethernet/chelsio/cxgb3/cxgb3_main.c | 14 +- .../net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- .../ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- drivers/net/ethernet/cirrus/ep93xx_eth.c | 2 +- drivers/net/ethernet/davicom/dm9000.c | 2 +- drivers/net/ethernet/dec/tulip/de4x5.c | 11 +- drivers/net/ethernet/dec/tulip/tulip_core.c | 2 +- drivers/net/ethernet/dec/tulip/winbond-840.c | 2 +- drivers/net/ethernet/dlink/dl2k.c | 2 +- drivers/net/ethernet/dlink/sundance.c | 2 +- drivers/net/ethernet/dnet.c | 2 +- drivers/net/ethernet/ethoc.c | 2 +- drivers/net/ethernet/faraday/ftgmac100.c | 2 +- drivers/net/ethernet/faraday/ftmac100.c | 2 +- drivers/net/ethernet/fealnx.c | 2 +- .../net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- .../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 2 +- .../net/ethernet/freescale/enetc/enetc_pf.c | 2 +- .../net/ethernet/freescale/enetc/enetc_vf.c | 2 +- drivers/net/ethernet/freescale/fec_main.c | 2 +- drivers/net/ethernet/freescale/fec_mpc52xx.c | 2 +- .../ethernet/freescale/fs_enet/fs_enet-main.c | 2 +- drivers/net/ethernet/freescale/gianfar.c | 2 +- drivers/net/ethernet/freescale/ucc_geth.c | 2 +- drivers/net/ethernet/hisilicon/hisi_femac.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_enet.c | 2 +- .../net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- drivers/net/ethernet/ibm/emac/core.c | 4 +- drivers/net/ethernet/ibm/ibmveth.c | 2 +- drivers/net/ethernet/intel/e100.c | 2 +- drivers/net/ethernet/intel/e1000/e1000_main.c | 2 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_main.c | 6 +- drivers/net/ethernet/intel/igb/igb_main.c | 2 +- drivers/net/ethernet/intel/igbvf/netdev.c | 2 +- drivers/net/ethernet/intel/igc/igc_main.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- drivers/net/ethernet/jme.c | 2 +- drivers/net/ethernet/korina.c | 2 +- drivers/net/ethernet/lantiq_etop.c | 2 +- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- drivers/net/ethernet/marvell/mvneta.c | 2 +- .../net/ethernet/marvell/mvpp2/mvpp2_main.c | 2 +- .../ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +- drivers/net/ethernet/marvell/pxa168_eth.c | 2 +- drivers/net/ethernet/marvell/skge.c | 2 +- drivers/net/ethernet/marvell/sky2.c | 4 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- drivers/net/ethernet/mediatek/mtk_star_emac.c | 2 +- .../net/ethernet/mellanox/mlx4/en_netdev.c | 2 +- .../net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 2 +- .../mellanox/mlx5/core/ipoib/ipoib_vlan.c | 2 +- .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 4 +- .../net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- drivers/net/ethernet/micrel/ks8851_common.c | 2 +- drivers/net/ethernet/micrel/ksz884x.c | 2 +- drivers/net/ethernet/microchip/lan743x_main.c | 2 +- drivers/net/ethernet/mscc/ocelot_net.c | 2 +- drivers/net/ethernet/natsemi/natsemi.c | 2 +- drivers/net/ethernet/neterion/s2io.c | 2 +- .../net/ethernet/neterion/vxge/vxge-main.c | 2 +- drivers/net/ethernet/nxp/lpc_eth.c | 2 +- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 2 +- drivers/net/ethernet/packetengines/hamachi.c | 63 +++++---- .../net/ethernet/packetengines/yellowfin.c | 2 +- .../net/ethernet/pensando/ionic/ionic_lif.c | 4 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 2 +- drivers/net/ethernet/qualcomm/emac/emac.c | 2 +- drivers/net/ethernet/rdc/r6040.c | 2 +- drivers/net/ethernet/realtek/8139cp.c | 2 +- drivers/net/ethernet/realtek/8139too.c | 2 +- drivers/net/ethernet/realtek/r8169_main.c | 2 +- drivers/net/ethernet/renesas/ravb_main.c | 2 +- drivers/net/ethernet/renesas/sh_eth.c | 4 +- .../net/ethernet/samsung/sxgbe/sxgbe_main.c | 2 +- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/ethernet/sfc/falcon/efx.c | 2 +- drivers/net/ethernet/sgi/ioc3-eth.c | 2 +- drivers/net/ethernet/sgi/meth.c | 2 +- drivers/net/ethernet/sis/sis190.c | 2 +- drivers/net/ethernet/sis/sis900.c | 2 +- drivers/net/ethernet/smsc/epic100.c | 2 +- drivers/net/ethernet/smsc/smc91c92_cs.c | 2 +- drivers/net/ethernet/smsc/smsc911x.c | 2 +- drivers/net/ethernet/smsc/smsc9420.c | 2 +- drivers/net/ethernet/socionext/netsec.c | 2 +- drivers/net/ethernet/socionext/sni_ave.c | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +- drivers/net/ethernet/sun/cassini.c | 2 +- drivers/net/ethernet/sun/niu.c | 2 +- drivers/net/ethernet/sun/sungem.c | 2 +- .../net/ethernet/synopsys/dwc-xlgmac-net.c | 2 +- drivers/net/ethernet/tehuti/tehuti.c | 18 +-- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 2 +- drivers/net/ethernet/ti/cpmac.c | 2 +- drivers/net/ethernet/ti/cpsw.c | 2 +- drivers/net/ethernet/ti/cpsw_new.c | 2 +- drivers/net/ethernet/ti/davinci_emac.c | 2 +- drivers/net/ethernet/ti/netcp_core.c | 2 +- drivers/net/ethernet/ti/tlan.c | 2 +- drivers/net/ethernet/toshiba/spider_net.c | 2 +- drivers/net/ethernet/toshiba/tc35815.c | 2 +- drivers/net/ethernet/tundra/tsi108_eth.c | 2 +- drivers/net/ethernet/via/via-rhine.c | 2 +- drivers/net/ethernet/via/via-velocity.c | 2 +- drivers/net/ethernet/xilinx/ll_temac_main.c | 2 +- .../net/ethernet/xilinx/xilinx_axienet_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_emaclite.c | 2 +- drivers/net/ethernet/xircom/xirc2ps_cs.c | 2 +- drivers/net/ethernet/xscale/ixp4xx_eth.c | 2 +- drivers/net/fddi/skfp/skfddi.c | 19 ++- drivers/net/hamradio/baycom_epp.c | 9 +- drivers/net/hamradio/baycom_par.c | 12 +- drivers/net/hamradio/baycom_ser_fdx.c | 12 +- drivers/net/hamradio/baycom_ser_hdx.c | 12 +- drivers/net/hamradio/bpqether.c | 9 +- drivers/net/hamradio/dmascc.c | 18 ++- drivers/net/hamradio/hdlcdrv.c | 20 +-- drivers/net/hamradio/scc.c | 13 +- drivers/net/hamradio/yam.c | 19 ++- drivers/net/hippi/rrunner.c | 11 +- drivers/net/hippi/rrunner.h | 3 +- drivers/net/macvlan.c | 8 +- drivers/net/phy/phy.c | 4 +- drivers/net/plip/plip.c | 12 +- drivers/net/ppp/ppp_generic.c | 6 +- drivers/net/sb1000.c | 20 +-- drivers/net/slip/slip.c | 13 +- drivers/net/usb/asix_devices.c | 6 +- drivers/net/usb/ax88172a.c | 2 +- drivers/net/usb/ax88179_178a.c | 2 +- drivers/net/usb/cdc-phonet.c | 5 +- drivers/net/usb/dm9601.c | 2 +- drivers/net/usb/lan78xx.c | 2 +- drivers/net/usb/mcs7830.c | 2 +- drivers/net/usb/pegasus.c | 5 +- drivers/net/usb/r8152.c | 2 +- drivers/net/usb/rtl8150.c | 5 +- drivers/net/usb/smsc75xx.c | 2 +- drivers/net/usb/smsc95xx.c | 2 +- drivers/net/usb/sr9700.c | 2 +- drivers/net/usb/sr9800.c | 2 +- drivers/net/wan/c101.c | 33 +++-- drivers/net/wan/cosa.c | 15 +-- drivers/net/wan/farsync.c | 123 ++++++++++-------- drivers/net/wan/fsl_ucc_hdlc.c | 19 ++- drivers/net/wan/hdlc.c | 9 +- drivers/net/wan/hdlc_cisco.c | 14 +- drivers/net/wan/hdlc_fr.c | 40 +++--- drivers/net/wan/hdlc_ppp.c | 8 +- drivers/net/wan/hdlc_raw.c | 14 +- drivers/net/wan/hdlc_raw_eth.c | 14 +- drivers/net/wan/hdlc_x25.c | 16 +-- drivers/net/wan/hostess_sv11.c | 7 +- drivers/net/wan/ixp4xx_hss.c | 19 ++- drivers/net/wan/lmc/lmc.h | 2 +- drivers/net/wan/lmc/lmc_main.c | 33 +++-- drivers/net/wan/lmc/lmc_proto.c | 7 - drivers/net/wan/lmc/lmc_proto.h | 1 - drivers/net/wan/n2.c | 32 +++-- drivers/net/wan/pc300too.c | 44 ++++--- drivers/net/wan/pci200syn.c | 32 +++-- drivers/net/wan/sbni.c | 15 ++- drivers/net/wan/sealevel.c | 10 +- drivers/net/wan/wanxl.c | 21 ++- drivers/net/wireless/cisco/airo.c | 15 ++- drivers/net/wireless/intersil/hostap/hostap.h | 3 +- .../wireless/intersil/hostap/hostap_ioctl.c | 30 ++++- .../wireless/intersil/hostap/hostap_main.c | 3 + drivers/s390/net/qeth_core.h | 5 +- drivers/s390/net/qeth_core_main.c | 35 +++-- drivers/s390/net/qeth_l2_main.c | 3 +- drivers/s390/net/qeth_l3_main.c | 12 +- drivers/staging/octeon/ethernet.c | 12 +- .../staging/rtl8188eu/include/osdep_intf.h | 2 + .../staging/rtl8188eu/include/rtw_android.h | 3 +- .../staging/rtl8188eu/os_dep/ioctl_linux.c | 3 - drivers/staging/rtl8188eu/os_dep/os_intfs.c | 1 + .../staging/rtl8188eu/os_dep/rtw_android.c | 14 +- .../staging/rtl8723bs/include/osdep_intf.h | 2 + .../staging/rtl8723bs/os_dep/ioctl_linux.c | 18 ++- drivers/staging/rtl8723bs/os_dep/os_intfs.c | 1 + drivers/staging/wlan-ng/p80211netdev.c | 76 ++--------- drivers/tty/synclink_gt.c | 19 ++- include/linux/hdlc.h | 4 +- include/linux/hdlcdrv.h | 2 +- include/linux/if_bridge.h | 7 +- include/linux/netdevice.h | 28 +++- include/net/dsa.h | 14 +- include/net/ip_tunnels.h | 3 +- net/8021q/vlan_dev.c | 6 +- net/bridge/br.c | 2 +- net/bridge/br_device.c | 2 +- net/bridge/br_ioctl.c | 52 ++++---- net/bridge/br_private.h | 7 +- net/core/dev_ioctl.c | 104 +++++++++++---- net/dsa/master.c | 6 +- net/dsa/slave.c | 2 +- net/ethtool/ioctl.c | 3 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_tunnel.c | 9 +- net/ipv4/ip_vti.c | 2 +- net/ipv4/ipip.c | 2 +- net/ipv6/ip6_gre.c | 17 +-- net/ipv6/ip6_tunnel.c | 21 +-- net/ipv6/ip6_vti.c | 21 +-- net/ipv6/sit.c | 35 ++--- net/phonet/pn_dev.c | 6 +- net/socket.c | 90 ++++++------- 254 files changed, 1134 insertions(+), 957 deletions(-) -- 2.29.2 Cc: "David S. Miller" <davem at davemloft.net> Cc: Jakub Kicinski <kuba at kernel.org> Cc: Jay Vosburgh <j.vosburgh at gmail.com> Cc: Veaceslav Falico <vfalico at gmail.com> Cc: Andy Gospodarek <andy at greyhouse.net> Cc: Raju Rangoju <rajur at chelsio.com> Cc: Thomas Sailer <t.sailer at alumni.ethz.ch> Cc: Joerg Reuter <jreuter at yaina.de> Cc: Jean-Paul Roubelat <jpr at f6fbb.org> Cc: Jes Sorensen <jes at trained-monkey.org> Cc: Krzysztof Halasa <khc at pm.waw.pl> Cc: "Jan \"Yenya\" Kasprzak" <kas at fi.muni.cz> Cc: Kevin Curtis <kevin.curtis at farsite.co.uk> Cc: Zhao Qiang <qiang.zhao at nxp.com> Cc: Martin Schiller <ms at dev.tdt.de> Cc: Kalle Valo <kvalo at codeaurora.org> Cc: Jouni Malinen <j at w1.fi> Cc: Julian Wiedmann <jwi at linux.ibm.com> Cc: Karsten Graul <kgraul at linux.ibm.com> Cc: Hideaki YOSHIFUJI <yoshfuji at linux-ipv6.org> Cc: David Ahern <dsahern at kernel.org> Cc: Roopa Prabhu <roopa at nvidia.com> Cc: Nikolay Aleksandrov <nikolay at nvidia.com> Cc: Steffen Klassert <steffen.klassert at secunet.com> Cc: Herbert Xu <herbert at gondor.apana.org.au> Cc: Remi Denis-Courmont <courmisch at gmail.com> Cc: Andrew Lunn <andrew at lunn.ch> Cc: Christoph Hellwig <hch at lst.de> Cc: netdev at vger.kernel.org Cc: linux-kernel at vger.kernel.org Cc: linux-parisc at vger.kernel.org Cc: linux-hams at vger.kernel.org Cc: linux-hippi at sunsite.dk Cc: linux-ppp at vger.kernel.org Cc: linux-usb at vger.kernel.org Cc: linux-x25 at vger.kernel.org Cc: linux-wireless at vger.kernel.org Cc: linux-s390 at vger.kernel.org Cc: bridge at lists.linux-foundation.org Cc: linux-arm-kernel at lists.infradead.org Cc: linux-mediatek at lists.infradead.org
Arnd Bergmann
2021-Jul-27  13:44 UTC
[Bridge] [PATCH net-next v3 05/31] bridge: use ndo_siocdevprivate
From: Arnd Bergmann <arnd at arndb.de>
The bridge driver has an old set of ioctls using the SIOCDEVPRIVATE
namespace that have never worked in compat mode and are explicitly
forbidden already.
Move them over to ndo_siocdevprivate and fix compat mode for these,
because we can.
Cc: Roopa Prabhu <roopa at nvidia.com>
Cc: Nikolay Aleksandrov <nikolay at nvidia.com>
Cc: bridge at lists.linux-foundation.org
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 net/bridge/br_device.c  |  1 +
 net/bridge/br_ioctl.c   | 37 +++++++++++++++++++++++++------------
 net/bridge/br_private.h |  2 ++
 3 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 00daf35f54d5..1952bb433ca7 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -455,6 +455,7 @@ static const struct net_device_ops br_netdev_ops = {
 	.ndo_change_rx_flags	 = br_dev_change_rx_flags,
 	.ndo_change_mtu		 = br_change_mtu,
 	.ndo_do_ioctl		 = br_dev_ioctl,
+	.ndo_siocdevprivate	 = br_dev_siocdevprivate,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_netpoll_setup	 = br_netpoll_setup,
 	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 2db800fc27ca..9f924fe43641 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -106,15 +106,32 @@ static int add_del_if(struct net_bridge *br, int ifindex,
int isadd)
  * This interface is deprecated because it was too difficult
  * to do the translation for 32/64bit ioctl compatibility.
  */
-static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq, void __user
*data, int cmd)
 {
 	struct net_bridge *br = netdev_priv(dev);
 	struct net_bridge_port *p = NULL;
 	unsigned long args[4];
+	void __user *argp;
 	int ret = -EOPNOTSUPP;
 
-	if (copy_from_user(args, rq->ifr_data, sizeof(args)))
-		return -EFAULT;
+	if (in_compat_syscall()) {
+		unsigned int cargs[4];
+
+		if (copy_from_user(cargs, data, sizeof(cargs)))
+			return -EFAULT;
+
+		args[0] = cargs[0];
+		args[1] = cargs[1];
+		args[2] = cargs[2];
+		args[3] = cargs[3];
+
+		argp = compat_ptr(args[1]);
+	} else {
+		if (copy_from_user(args, data, sizeof(args)))
+			return -EFAULT;
+
+		argp = (void __user *)args[1];
+	}
 
 	switch (args[0]) {
 	case BRCTL_ADD_IF:
@@ -171,7 +188,7 @@ static int old_dev_ioctl(struct net_device *dev, struct
ifreq *rq, int cmd)
 			return -ENOMEM;
 
 		get_port_ifindices(br, indices, num);
-		if (copy_to_user((void __user *)args[1], indices, num*sizeof(int)))
+		if (copy_to_user(argp, indices, num * sizeof(int)))
 			num =  -EFAULT;
 		kfree(indices);
 		return num;
@@ -232,7 +249,7 @@ static int old_dev_ioctl(struct net_device *dev, struct
ifreq *rq, int cmd)
 
 		rcu_read_unlock();
 
-		if (copy_to_user((void __user *)args[1], &p, sizeof(p)))
+		if (copy_to_user(argp, &p, sizeof(p)))
 			return -EFAULT;
 
 		return 0;
@@ -282,8 +299,7 @@ static int old_dev_ioctl(struct net_device *dev, struct
ifreq *rq, int cmd)
 	}
 
 	case BRCTL_GET_FDB_ENTRIES:
-		return get_fdb_entries(br, (void __user *)args[1],
-				       args[2], args[3]);
+		return get_fdb_entries(br, argp, args[2], args[3]);
 	}
 
 	if (!ret) {
@@ -320,7 +336,7 @@ static int old_deviceless(struct net *net, void __user
*uarg)
 
 		args[2] = get_bridge_ifindices(net, indices, args[2]);
 
-		ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))
+		ret = copy_to_user(uarg, indices, args[2]*sizeof(int))
 			? -EFAULT : args[2];
 
 		kfree(indices);
@@ -335,7 +351,7 @@ static int old_deviceless(struct net *net, void __user
*uarg)
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
 
-		if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
+		if (copy_from_user(buf, uarg, IFNAMSIZ))
 			return -EFAULT;
 
 		buf[IFNAMSIZ-1] = 0;
@@ -383,9 +399,6 @@ int br_dev_ioctl(struct net_device *dev, struct ifreq *rq,
int cmd)
 	struct net_bridge *br = netdev_priv(dev);
 
 	switch (cmd) {
-	case SIOCDEVPRIVATE:
-		return old_dev_ioctl(dev, rq, cmd);
-
 	case SIOCBRADDIF:
 	case SIOCBRDELIF:
 		return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1c57877270f7..572c28ae41b8 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -852,6 +852,8 @@ br_port_get_check_rtnl(const struct net_device *dev)
 
 /* br_ioctl.c */
 int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
+			  void __user *data, int cmd);
 int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
 			     void __user *arg);
 
-- 
2.29.2
Arnd Bergmann
2021-Jul-27  13:45 UTC
[Bridge] [PATCH net-next v3 30/31] net: bridge: move bridge ioctls out of .ndo_do_ioctl
From: Arnd Bergmann <arnd at arndb.de>
Working towards obsoleting the .ndo_do_ioctl operation entirely,
stop passing the SIOCBRADDIF/SIOCBRDELIF device ioctl commands
into this callback.
My first attempt was to add another ndo_siocbr() callback, but
as there is only a single driver that takes these commands and
there is already a hook mechanism to call directly into this
driver, extend this hook instead, and use it for both the
deviceless and the device specific ioctl commands.
Cc: Roopa Prabhu <roopa at nvidia.com>
Cc: Nikolay Aleksandrov <nikolay at nvidia.com>
Cc: bridge at lists.linux-foundation.org
Signed-off-by: Arnd Bergmann <arnd at arndb.de>
---
 include/linux/if_bridge.h |  7 ++++++-
 net/bridge/br.c           |  2 +-
 net/bridge/br_device.c    |  1 -
 net/bridge/br_ioctl.c     | 15 +++------------
 net/bridge/br_private.h   |  5 ++---
 net/core/dev_ioctl.c      | 11 ++++++++---
 net/socket.c              | 33 +++++++++++++++++++++++----------
 7 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index b73b4ff749e1..21daed10322e 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -61,7 +61,12 @@ struct br_ip_list {
 
 #define BR_DEFAULT_AGEING_TIME	(300 * HZ)
 
-extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void
__user *));
+struct net_bridge;
+void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+			     unsigned int cmd, struct ifreq *ifr,
+			     void __user *uarg));
+int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+		  struct ifreq *ifr, void __user *uarg);
 
 #if IS_ENABLED(CONFIG_BRIDGE) &&
IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
 int br_multicast_list_adjacent(struct net_device *dev,
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 51f2e25c4cd6..8fb5dca5f8e0 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -359,7 +359,7 @@ static int __init br_init(void)
 	if (err)
 		goto err_out5;
 
-	brioctl_set(br_ioctl_deviceless_stub);
+	brioctl_set(br_ioctl_stub);
 
 #if IS_ENABLED(CONFIG_ATM_LANE)
 	br_fdb_test_addr_hook = br_fdb_test_addr;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 1952bb433ca7..8d6bab244c4a 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -454,7 +454,6 @@ static const struct net_device_ops br_netdev_ops = {
 	.ndo_set_rx_mode	 = br_dev_set_multicast_list,
 	.ndo_change_rx_flags	 = br_dev_change_rx_flags,
 	.ndo_change_mtu		 = br_change_mtu,
-	.ndo_do_ioctl		 = br_dev_ioctl,
 	.ndo_siocdevprivate	 = br_dev_siocdevprivate,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_netpoll_setup	 = br_netpoll_setup,
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 9f924fe43641..46a24c20e405 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -366,7 +366,8 @@ static int old_deviceless(struct net *net, void __user
*uarg)
 	return -EOPNOTSUPP;
 }
 
-int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user
*uarg)
+int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+		  struct ifreq *ifr, void __user *uarg)
 {
 	switch (cmd) {
 	case SIOCGIFBR:
@@ -390,21 +391,11 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int
cmd, void __user *uar
 
 		return br_del_bridge(net, buf);
 	}
-	}
-	return -EOPNOTSUPP;
-}
-
-int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-	struct net_bridge *br = netdev_priv(dev);
 
-	switch (cmd) {
 	case SIOCBRADDIF:
 	case SIOCBRDELIF:
-		return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);
+		return add_del_if(br, ifr->ifr_ifindex, cmd == SIOCBRADDIF);
 
 	}
-
-	br_debug(br, "Bridge does not support ioctl 0x%x\n", cmd);
 	return -EOPNOTSUPP;
 }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 572c28ae41b8..f2d34ea1ea37 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -851,11 +851,10 @@ br_port_get_check_rtnl(const struct net_device *dev)
 }
 
 /* br_ioctl.c */
-int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int br_dev_siocdevprivate(struct net_device *dev, struct ifreq *rq,
 			  void __user *data, int cmd);
-int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd,
-			     void __user *arg);
+int br_ioctl_stub(struct net *net, struct net_bridge *br, unsigned int cmd,
+		  struct ifreq *ifr, void __user *uarg);
 
 /* br_multicast.c */
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 70a379cee5fd..3166f196b296 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -6,6 +6,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/net_tstamp.h>
 #include <linux/wireless.h>
+#include <linux/if_bridge.h>
 #include <net/dsa.h>
 #include <net/wext.h>
 
@@ -374,6 +375,12 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr,
void __user *data,
 	case SIOCWANDEV:
 		return dev_siocwandev(dev, &ifr->ifr_settings);
 
+	case SIOCBRADDIF:
+	case SIOCBRDELIF:
+		if (!netif_device_present(dev))
+			return -ENODEV;
+		return br_ioctl_call(net, netdev_priv(dev), cmd, ifr, NULL);
+
 	case SIOCSHWTSTAMP:
 		err = net_hwtstamp_validate(ifr);
 		if (err)
@@ -399,9 +406,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr,
void __user *data,
 		    cmd == SIOCBONDSETHWADDR ||
 		    cmd == SIOCBONDSLAVEINFOQUERY ||
 		    cmd == SIOCBONDINFOQUERY ||
-		    cmd == SIOCBONDCHANGEACTIVE ||
-		    cmd == SIOCBRADDIF ||
-		    cmd == SIOCBRDELIF) {
+		    cmd == SIOCBONDCHANGEACTIVE) {
 			err = dev_do_ioctl(dev, ifr, cmd);
 		} else
 			err = -EINVAL;
diff --git a/net/socket.c b/net/socket.c
index 48471a219c1d..42665bd99ea4 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1064,9 +1064,13 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct
iov_iter *from)
  */
 
 static DEFINE_MUTEX(br_ioctl_mutex);
-static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg);
+static int (*br_ioctl_hook)(struct net *net, struct net_bridge *br,
+			    unsigned int cmd, struct ifreq *ifr,
+			    void __user *uarg);
 
-void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
+void brioctl_set(int (*hook)(struct net *net, struct net_bridge *br,
+			     unsigned int cmd, struct ifreq *ifr,
+			     void __user *uarg))
 {
 	mutex_lock(&br_ioctl_mutex);
 	br_ioctl_hook = hook;
@@ -1074,6 +1078,22 @@ void brioctl_set(int (*hook) (struct net *, unsigned int,
void __user *))
 }
 EXPORT_SYMBOL(brioctl_set);
 
+int br_ioctl_call(struct net *net, struct net_bridge *br, unsigned int cmd,
+		  struct ifreq *ifr, void __user *uarg)
+{
+	int err = -ENOPKG;
+
+	if (!br_ioctl_hook)
+		request_module("bridge");
+
+	mutex_lock(&br_ioctl_mutex);
+	if (br_ioctl_hook)
+		err = br_ioctl_hook(net, br, cmd, ifr, uarg);
+	mutex_unlock(&br_ioctl_mutex);
+
+	return err;
+}
+
 static DEFINE_MUTEX(vlan_ioctl_mutex);
 static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
 
@@ -1162,14 +1182,7 @@ static long sock_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
 		case SIOCSIFBR:
 		case SIOCBRADDBR:
 		case SIOCBRDELBR:
-			err = -ENOPKG;
-			if (!br_ioctl_hook)
-				request_module("bridge");
-
-			mutex_lock(&br_ioctl_mutex);
-			if (br_ioctl_hook)
-				err = br_ioctl_hook(net, cmd, argp);
-			mutex_unlock(&br_ioctl_mutex);
+			err = br_ioctl_call(net, NULL, cmd, NULL, argp);
 			break;
 		case SIOCGIFVLAN:
 		case SIOCSIFVLAN:
-- 
2.29.2
patchwork-bot+netdevbpf at kernel.org
2021-Jul-27  20:00 UTC
[Bridge] [PATCH net-next v3 00/31] ndo_ioctl rework
Hello: This series was applied to netdev/net-next.git (refs/heads/master): On Tue, 27 Jul 2021 15:44:46 +0200 you wrote:> From: Arnd Bergmann <arnd at arndb.de> > > This series is a follow-up to the series for removing > compat_alloc_user_space() and copy_in_user() that has now > been merged. > > I wanted to be sure I address all the ways that 'struct ifreq' is used > in device drivers through .ndo_do_ioctl, originally to prove that > my approach of changing the struct definition was correct, but then > I discarded that approach and went on anyway. > > [...]Here is the summary with links: - [net-next,v3,01/31] net: split out SIOCDEVPRIVATE handling from dev_ioctl https://git.kernel.org/netdev/net-next/c/b9067f5dc4a0 - [net-next,v3,02/31] staging: rtlwifi: use siocdevprivate https://git.kernel.org/netdev/net-next/c/89939e890605 - [net-next,v3,03/31] staging: wlan-ng: use siocdevprivate https://git.kernel.org/netdev/net-next/c/3343c49a959d - [net-next,v3,04/31] hostap: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/3f3fa5340745 - [net-next,v3,05/31] bridge: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/561d8352818f - [net-next,v3,06/31] phonet: use siocdevprivate https://git.kernel.org/netdev/net-next/c/4747c1a8bc50 - [net-next,v3,07/31] tulip: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/029a4fef6b22 - [net-next,v3,08/31] bonding: use siocdevprivate https://git.kernel.org/netdev/net-next/c/232ec98ec35d - [net-next,v3,09/31] appletalk: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/dbecb011eb78 - [net-next,v3,10/31] hamachi: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/99b78a37a371 - [net-next,v3,11/31] tehuti: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/32d05468c462 - [net-next,v3,12/31] eql: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/d92f7b59d32b - [net-next,v3,13/31] fddi: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/043393d8b478 - [net-next,v3,14/31] net: usb: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/ef1b5b0c30bc - [net-next,v3,15/31] slip/plip: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/76b5878cffab - [net-next,v3,16/31] qeth: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/18787eeebd71 - [net-next,v3,17/31] cxgb3: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/ebb4a911e09a - [net-next,v3,18/31] hamradio: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/25ec92fbdd23 - [net-next,v3,19/31] airo: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/ae6af0120dda - [net-next,v3,20/31] ip_tunnel: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/3e7a1c7c561e - [net-next,v3,21/31] hippi: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/81a68110a22a - [net-next,v3,22/31] sb1000: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/cc0aa831a0d9 - [net-next,v3,23/31] ppp: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/34f7cac07c4e - [net-next,v3,24/31] wan: use ndo_siocdevprivate https://git.kernel.org/netdev/net-next/c/73d74f61a559 - [net-next,v3,25/31] wan: cosa: remove dead cosa_net_ioctl() function https://git.kernel.org/netdev/net-next/c/8fb75b79cd98 - [net-next,v3,26/31] dev_ioctl: pass SIOCDEVPRIVATE data separately https://git.kernel.org/netdev/net-next/c/a554bf96b49d - [net-next,v3,27/31] dev_ioctl: split out ndo_eth_ioctl https://git.kernel.org/netdev/net-next/c/a76053707dbf - [net-next,v3,28/31] net: split out ndo_siowandev ioctl https://git.kernel.org/netdev/net-next/c/ad7eab2ab014 - [net-next,v3,29/31] net: socket: return changed ifreq from SIOCDEVPRIVATE https://git.kernel.org/netdev/net-next/c/88fc023f7de2 - [net-next,v3,30/31] net: bridge: move bridge ioctls out of .ndo_do_ioctl https://git.kernel.org/netdev/net-next/c/ad2f99aedf8f - [net-next,v3,31/31] net: bonding: move ioctl handling to private ndo operation https://git.kernel.org/netdev/net-next/c/3d9d00bd1885 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html