From nobody Wed Apr 1 22:36:13 2026 Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D18EF3822BC for ; Thu, 5 Mar 2026 11:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772709014; cv=none; b=nQYEVjqs8Q2W08B8fJ53tCvYfdx4e5gaIZdvexmWHg8pMQr8nPPQEO+vgWRUJnt/qxJS+9n5D44OQfsBpL4lo7F3bqMLue/t0/xtjTmRZlzLrnE59EEY4RS4brjEhebujgabng905kGwsauGhgF1Sg5FBXCqAwYY9JKNtj7WxRo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772709014; c=relaxed/simple; bh=x0d+Wu02y+l5RGSc94GT+Dvd2idg4Yr3hzETsqoCJJ8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Io+NyDuQKfGkAUvVjmGRysdPESkP80vlLwdFS7p2tRj8zYTmqGVgIwdxfk9DmQMsFFIFhY0vLRz5D9oRKvzSm4FNmmrgsDZ+lHpBlBskAPiSqDYWxJkFzogZmz7cyM2x5nZjHG0Rt7nnTG4TRFvGrV+O6gveg3RP5kv/9A39VCU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmo-cybersecurity.com; spf=pass smtp.mailfrom=gmo-cybersecurity.com; dkim=pass (2048-bit key) header.d=gmo-cybersecurity.com header.i=@gmo-cybersecurity.com header.b=erX9PcWp; arc=none smtp.client-ip=209.85.215.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmo-cybersecurity.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmo-cybersecurity.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmo-cybersecurity.com header.i=@gmo-cybersecurity.com header.b="erX9PcWp" Received: by mail-pg1-f181.google.com with SMTP id 41be03b00d2f7-bde0f62464cso2804297a12.2 for ; Thu, 05 Mar 2026 03:10:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmo-cybersecurity.com; s=google; t=1772709012; x=1773313812; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=eQZNtnLYKtNFjePC1tTguFNpzwwlyU97MLzkI1UYxwc=; b=erX9PcWpi9kIRflxQSZzZr+oNnVgLBfq9tOHLT1QFAF4JG3N1FKbwwpIjx1BqcFffK XAK1Ez+vSamqo9JowGS0GGmke/Jbe3BQWNmT334A2EMnLAEitNJt6drluWMCPAp6CDLo NdRZbkU87zoqmE7ApQ3IxDlsSLPDL107iQMIwyCMgKSvAkad9VHZ1eNjFbix+EZG7RWS vgo6FpcmkH4/JmdzjDGiR7lnfK6wdb2PJ0KPAUrVuDUZbKsbeoTl0VobwrLpmesGbEO8 GgS3uiDgDm3IR0HEnBPlsfFx+fjNc4/FFxwNsp7IK3i8h5DS7QFbxgZFqPYs+u2iOtNV fEAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772709012; x=1773313812; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=eQZNtnLYKtNFjePC1tTguFNpzwwlyU97MLzkI1UYxwc=; b=FXmWGsUaj7G5Ky8P1UTk8ZchtbgVpjrY8hDtJB/bmj2dS1ZMoFGpDPK53TSSDBx8FR +IfVuq/8z0Yo7AyyYf4myCo0TmUqUOmJYAUCJwptNikGIqqm88sW5bXdfC6Y2M4T4CRx AM5VIK+0MnsJ7FlwmQSqr+qBRzznT/9zolVMmhS6ezzH8g5lPPRbRFtL4Maevckvb1bC bOz/+ATXGUFzQl0erCbbHk1eKr7+QIK0lKTZvLpCcduf259S/QCkCqxvmzk5nOSKcd9r CXKAT65PVXZEz5EcBrEOBF4C0HFU/A/CyEFRLfIbYrgLu9Rv2Y7bP9iZwaqdpJqq64hx auHA== X-Forwarded-Encrypted: i=1; AJvYcCVvMUSL6a9+mT/Cd66fJYQGMS4LkCarffZxVoEQ6046NE6FUKpREcw9iDzt4AgpU5X+PDAUdvyGVsDe5c4=@vger.kernel.org X-Gm-Message-State: AOJu0YwIUJxOZFJN+ReHlh+CqWFzwSGNwAvpHFhnjdM4bFLqI8GBe6Kl 8NEMohsOwnrA5/IV8Gurx2Kx3Ex+3XeJ6DIVJZpbNkGHhVL00BoksKoRObohymJBe7s= X-Gm-Gg: ATEYQzy9ASjVXKihOX4eQpxrHR3RTcEHFcPVk9v1QSUa4Z8nG9EJwpHdW7ltHw4kauk 2HQiAudOwf38ZBOWZuJrddbtoL7K6zVYLP322g3qaTu68+javiFrpglmNUytf68l7ucTaqQuclX 64iouKpAYVc0YiPu4N3xbQzj52ADq8gABc5z0orB3V63VJ+jYGr2ji/rvqTU8ryu0RJEwXWvKET fmGaUUvrRJxQfnGPavrXUeewiMno1gB5U9+rBbdjTELtFeHjbm9Q0hB5a0QLdDbIa9ut1kSrHrC sAP3S7l046Re39CC4RJJF9X+3yYirT0Xsd9mbLB0UA3M+lNjivDq4MVuhVl4WZcVoWwzmP0GpDY AF18LfjLPwz0bybisrrDDB+qZJrqkuSLxPPozzyrT8t9BgFEiMziFSVE4rB5cyD2tFwy6wkytwN M8k6ZKZZv/mutbrl+yOP+P63enoTP8MLqD8dkJJeyoQb7oSW2ZudLMytaF9oVliT7MPxD1MgYfj ZhdumYrYtnPMdNWvrQenuE= X-Received: by 2002:a17:902:db09:b0:2ae:3cf0:3aa1 with SMTP id d9443c01a7336-2ae6aaa73c6mr56519505ad.37.1772709012059; Thu, 05 Mar 2026 03:10:12 -0800 (PST) Received: from cachyos.camel-monitor.ts.net (akacd-04p3-188.ppp11.odn.ad.jp. [210.237.248.188]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ae3e4e34fesm153501155ad.28.2026.03.05.03.10.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Mar 2026 03:10:11 -0800 (PST) From: Kota Toda To: Jeff Garzik , Jay Vosburgh , Jay Vosburgh , Andy Gospodarek , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: Kota Toda , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Yuki Koike Subject: [PATCH v4 1/2] net: bonding: fix type-confusion in bonding header_ops Date: Thu, 5 Mar 2026 20:07:48 +0900 Message-ID: <20260305110751.167489-2-kota.toda@gmo-cybersecurity.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260305110751.167489-1-kota.toda@gmo-cybersecurity.com> References: <20260305110751.167489-1-kota.toda@gmo-cybersecurity.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable In bond_setup_by_slave(), the slave=E2=80=99s header_ops are unconditionally copied into the bonding device. As a result, the bonding device may invoke the slave-specific header operations on itself, causing netdev_priv(bond_dev) (a struct bonding) to be incorrectly interpreted as the slave's private-data type. This type-confusion bug can lead to out-of-bounds writes into the skb, resulting in memory corruption. This patch stores the slave's header_ops in struct bonding and sets wrapper callbacks in bond_In bond_setup_by_slave(), the slave=E2=80=99s header_ops are unconditionally copied into the bonding device. As a result, the bonding device may invoke the slave-specific header operations on itself, causing netdev_priv(bond_dev) (a struct bonding) to be incorrectly interpreted as the slave's private-data type. Fixes: 1284cd3a2b74 ("bonding: two small fixes for IPoIB support") Signed-off-by: Kota Toda Co-developed-by: Yuki Koike Signed-off-by: Yuki Koike --- drivers/net/bonding/bond_main.c | 67 ++++++++++++++++++++++++++++++++- include/net/bonding.h | 5 +++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_mai= n.c index f17a170d1..14d3e5298 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1616,14 +1616,71 @@ static void bond_compute_features(struct bonding *b= ond) netdev_change_features(bond_dev); } =20 +static int bond_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len) +{ + struct bonding *bond =3D netdev_priv(dev); + struct net_device *slave_dev; + + slave_dev =3D bond->header_slave_dev; + + return dev_hard_header(skb, slave_dev, type, daddr, saddr, len); +} + +static void bond_header_cache_update(struct hh_cache *hh, const +struct net_device *dev, + const unsigned char *haddr) +{ + const struct bonding *bond =3D netdev_priv(dev); + void (*cache_update)(struct hh_cache *hh, + const struct net_device *dev, + const unsigned char *haddr); + struct net_device *slave_dev; + + slave_dev =3D bond->header_slave_dev; + if (!slave_dev->header_ops) + return; + cache_update =3D READ_ONCE(slave_dev->header_ops->cache_update); + if (!cache_update) + return; + cache_update(hh, slave_dev, haddr); +} + static void bond_setup_by_slave(struct net_device *bond_dev, struct net_device *slave_dev) { + struct bonding *bond =3D netdev_priv(bond_dev); bool was_up =3D !!(bond_dev->flags & IFF_UP); =20 dev_close(bond_dev); =20 - bond_dev->header_ops =3D slave_dev->header_ops; + /* Some functions are given dev as an argument + * while others not. When dev is not given, we cannot + * find out what is the slave device through struct bonding + * (the private data of bond_dev). Therefore, we need a raw + * header_ops variable instead of its pointer to const header_ops + * and assign slave's functions directly. + * For the other case, we set the wrapper functions that pass + * slave_dev to the wrapped functions. + */ + bond->bond_header_ops.create =3D bond_hard_header; + bond->bond_header_ops.cache_update =3D bond_header_cache_update; + if (slave_dev->header_ops) { + WRITE_ONCE(bond->bond_header_ops.parse, slave_dev->header_ops->parse); + WRITE_ONCE(bond->bond_header_ops.cache, slave_dev->header_ops->cache); + WRITE_ONCE(bond->bond_header_ops.validate, slave_dev->header_ops->valida= te); + WRITE_ONCE(bond->bond_header_ops.parse_protocol, + slave_dev->header_ops->parse_protocol); + } else { + WRITE_ONCE(bond->bond_header_ops.parse, NULL); + WRITE_ONCE(bond->bond_header_ops.cache, NULL); + WRITE_ONCE(bond->bond_header_ops.validate, NULL); + WRITE_ONCE(bond->bond_header_ops.parse_protocol, NULL); + } + + WRITE_ONCE(bond_dev->header_ops, &bond->bond_header_ops); + bond->header_slave_dev =3D slave_dev; =20 bond_dev->type =3D slave_dev->type; bond_dev->hard_header_len =3D slave_dev->hard_header_len; @@ -2682,6 +2739,14 @@ static int bond_release_and_destroy(struct net_devic= e *bond_dev, struct bonding *bond =3D netdev_priv(bond_dev); int ret; =20 + /* If slave_dev is the earliest registered one, we must clear + * the variables related to header_ops to avoid dangling pointer. + */ + if (bond->header_slave_dev =3D=3D slave_dev) { + WRITE_ONCE(bond_dev->header_ops, NULL); + bond->header_slave_dev =3D NULL; + } + ret =3D __bond_release_one(bond_dev, slave_dev, false, true); if (ret =3D=3D 0 && !bond_has_slaves(bond) && bond_dev->reg_state !=3D NETREG_UNREGISTERING) { diff --git a/include/net/bonding.h b/include/net/bonding.h index 95f67b308..cf8206187 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -215,6 +215,11 @@ struct bond_ipsec { */ struct bonding { struct net_device *dev; /* first - useful for panic debug */ + struct net_device *header_slave_dev; /* slave net_device for header_op= s */ + /* maintained as a non-const variable + * because bond's header_ops should change depending on slaves. + */ + struct header_ops bond_header_ops; struct slave __rcu *curr_active_slave; struct slave __rcu *current_arp_slave; struct slave __rcu *primary_slave; --=20 2.53.0 From nobody Wed Apr 1 22:36:13 2026 Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 268293822BC for ; Thu, 5 Mar 2026 11:10:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772709020; cv=none; b=joBM1SYkTIk4asxdObeUgMwEd8UrzQRbuJ4q/lJVnxaR7wA78fBV8s0waN3gU8e3cMgIhYnDQQVl1pcU8lTmuVsfEXC5rmBqU55vurM3udFQigY4CB+bKZSFLghbcUXnSGnlqEqMPCeLBaVgDgRL+NbBw/deiOVzUv2eS53W+yI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772709020; c=relaxed/simple; bh=iILJccyDyJaNfe5/O36ZoRk8XcC4XvtVI+KNgSJv2Nc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YMt6td1zkBg404Jt7Ynrc6+0TUvkA02YbcFPHEPvWdtxbZkb32JGnJpOVuO840wYcqiqlhsI3C4n0GahMDsP7bL3rpPr3dzehwsutdQ2YnHTpGZm2EoAy145fDWfyso5lyAjWEa0ps7ljQM1QWJZP5Qxki2reSoP5NS7tN3LbIo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmo-cybersecurity.com; spf=pass smtp.mailfrom=gmo-cybersecurity.com; dkim=pass (2048-bit key) header.d=gmo-cybersecurity.com header.i=@gmo-cybersecurity.com header.b=DVW6TfxG; arc=none smtp.client-ip=209.85.215.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=gmo-cybersecurity.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmo-cybersecurity.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmo-cybersecurity.com header.i=@gmo-cybersecurity.com header.b="DVW6TfxG" Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-c73967cf77aso27757a12.3 for ; Thu, 05 Mar 2026 03:10:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmo-cybersecurity.com; s=google; t=1772709018; x=1773313818; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8Uah3KJlZJ0YDkhXOPrfMLRnjC77tql+fRjEzdTgsKU=; b=DVW6TfxGI3iG/7wYkWj8BG2PVC1BcETzqH1s2iQr/tDZ0XYDtmlfMnGCr1bUq5UxGJ 8dCfYy8Rc9qhoX55TBHO3FUL/prPI4EKzu5ukTCNUSAGzMlrc/346feltegVNMo41GM5 fVLJk4K6SjwqvgyRg8TYOWQbtPdgbnMn1xtguH9Vfpkg61dV6HovyVllwVppzg6HC8VP GMY+YYcUfH1bSDQT11RBwQh0/BOVnBbvMfbD2jC2c5i3irw0YJTetfLFoTPd2wJgXimb Xoq21EK7vHaOKPMpecQIjigkrdL5hR2fIYYszktzGTOsy7ZRc0a8fVBMYzPEOqxvGS9Q D0Qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772709018; x=1773313818; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=8Uah3KJlZJ0YDkhXOPrfMLRnjC77tql+fRjEzdTgsKU=; b=uo2cqm6dOQf+CUvKSItNIx10+bgAcKK0yPZuUraFIViP9ZHlg1rYLf0n8GsaMs1v+6 5/9QiGr1DW4qfrgN7l+2HH2QNzQR0FeGmyp4w7H7U38yNJ6u8GS+1ZHZWwOjvWfHTDcW EJjdTqp6U28uvyCIjGK/BjJgnXNZl8fuY+WYzPxXpVGJwDHj0pzv4ssxrJXXBX/ZAX2S aDubFlO6p4v2LZJW8ZZ12fzZrLeJeCcD2CxEGtsK60YFb72vFCoOg1P07c0n4+WCyMeb YIXxgZVMCpvhg6Rbk41pC02Q6T/OECffGMwfezRiZ3RDKZ83Z81FZk0YD92ABLD6dk9z o3Ww== X-Forwarded-Encrypted: i=1; AJvYcCVcZrA8a1snKHn8+lS+dYet1N4RGfEID5w+WHOKm/3Nae9nyTxg/7wqNgkZvbbIwRlhLvmdaMqnCfDZ4Q8=@vger.kernel.org X-Gm-Message-State: AOJu0YzZWw4JLxJuLfc422SlMH4keTfGBubKwLVWHZSzzfvRO1nsFNYD ExII1/DK55Zx6RfoTj2Cw/kqlHUqpinArYdzJBviHlS5iUNCRH5eTFdX77z0cnkQDM8= X-Gm-Gg: ATEYQzy3o84GvMMGAXRJMKswzLYzZPGZU4a8pObQGTw5KXdzd7kBr6aZ8KnWr8hdtFl Et52g9en3v8Pqod8ThZ3dvimolng1nyAQxhUSMXTWIV6H1Kx5dk2JGxRRK6wvNmeEZrBw+c6Sf3 /h80mJhuDpR4Sbl8dzsRji40t/Ka6798DUGK6rMMINWpbdARx9fbx/yEP16ZtjXaI1OVY3XE7G9 P1YYjqbmRJeNJzUemArrzDc0lj+cNGBHBGDTQMFw7Wf5SBhRespWdBoq9n4lX7Gx0GYg/uKF5XO M9HpLk9phnS7DGuCLOBThQhwC/HM7KO3l/WJwKda+S60X0ouAWZDIsZ312WJF143NxJrGLW5ah+ 0nBtF8L0EQALU/2nUVVlYSYuAMG+Bn4fxZzkgx4QDZ7jZjHqxXxXM1smjTgv6cgTY80HGVmZgbU san9pPEcjI1/ZyYGFRaD7j4NXgW+aLY0u31tUmMEpvJTygc6bsZsi+Uc/VCNc6A3ig9f5Q1X//p 51AimInX9hJUVUNMlb+jTs= X-Received: by 2002:a17:902:db0f:b0:2ad:6e26:abbb with SMTP id d9443c01a7336-2ae6ab9ecd3mr48315825ad.54.1772709018409; Thu, 05 Mar 2026 03:10:18 -0800 (PST) Received: from cachyos.camel-monitor.ts.net (akacd-04p3-188.ppp11.odn.ad.jp. [210.237.248.188]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2ae3e4e34fesm153501155ad.28.2026.03.05.03.10.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Mar 2026 03:10:18 -0800 (PST) From: Kota Toda To: Jeff Garzik , Jay Vosburgh , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Alexander Aring , Stefan Schmidt , Miquel Raynal , David Ahern Cc: Kota Toda , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Yuki Koike , linux-wpan@vger.kernel.org Subject: [PATCH v4 2/2] net: read header_ops callbacks with READ_ONCE() Date: Thu, 5 Mar 2026 20:07:49 +0900 Message-ID: <20260305110751.167489-3-kota.toda@gmo-cybersecurity.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260305110751.167489-1-kota.toda@gmo-cybersecurity.com> References: <20260305110751.167489-1-kota.toda@gmo-cybersecurity.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Bonding now updates its header_ops callbacks at runtime, so lockless readers can observe concurrent callback updates. This patch loads header_ops callbacks with READ_ONCE() and=20 call the loaded function pointer, instead of=20 re-reading through dev->header_ops. Signed-off-by: Kota Toda Co-developed-by: Yuki Koike Signed-off-by: Yuki Koike --- include/linux/netdevice.h | 41 +++++++++++++++++++++++++++------------ include/net/cfg802154.h | 2 +- net/core/neighbour.c | 6 +++--- net/ipv4/arp.c | 2 +- net/ipv6/ndisc.c | 2 +- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 77a99c8ab..79fb0864a 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3150,35 +3150,50 @@ static inline int dev_hard_header(struct sk_buff *s= kb, struct net_device *dev, const void *daddr, const void *saddr, unsigned int len) { - if (!dev->header_ops || !dev->header_ops->create) - return 0; + int (*create)(struct sk_buff *skb, struct net_device *dev, + unsigned short type, const void *daddr, + const void *saddr, unsigned int len); =20 - return dev->header_ops->create(skb, dev, type, daddr, saddr, len); + if (!dev->header_ops) + return 0; + create =3D READ_ONCE(dev->header_ops->create); + if (!create) + return 0; + return create(skb, dev, type, daddr, saddr, len); } =20 static inline int dev_parse_header(const struct sk_buff *skb, unsigned char *haddr) { + int (*parse)(const struct sk_buff *skb, unsigned char *haddr); const struct net_device *dev =3D skb->dev; =20 - if (!dev->header_ops || !dev->header_ops->parse) + if (!dev->header_ops) return 0; - return dev->header_ops->parse(skb, haddr); + parse =3D READ_ONCE(dev->header_ops->parse); + if (!parse) + return 0; + return parse(skb, haddr); } =20 static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) { + __be16 (*parse_protocol)(const struct sk_buff *skb); const struct net_device *dev =3D skb->dev; =20 - if (!dev->header_ops || !dev->header_ops->parse_protocol) + if (!dev->header_ops) + return 0; + parse_protocol =3D READ_ONCE(dev->header_ops->parse_protocol); + if (!parse_protocol) return 0; - return dev->header_ops->parse_protocol(skb); + return parse_protocol(skb); } =20 /* ll_header must have at least hard_header_len allocated */ static inline bool dev_validate_header(const struct net_device *dev, char *ll_header, int len) { + bool (*validate)(const char *ll_header, unsigned int len); if (likely(len >=3D dev->hard_header_len)) return true; if (len < dev->min_header_len) @@ -3189,15 +3204,17 @@ static inline bool dev_validate_header(const struct= net_device *dev, return true; } =20 - if (dev->header_ops && dev->header_ops->validate) - return dev->header_ops->validate(ll_header, len); - - return false; + if (!dev->header_ops) + return false; + validate =3D READ_ONCE(dev->header_ops->validate); + if (!validate) + return false; + return validate(ll_header, len); } =20 static inline bool dev_has_header(const struct net_device *dev) { - return dev->header_ops && dev->header_ops->create; + return dev->header_ops && READ_ONCE(dev->header_ops->create); } =20 /* diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 76d2cd2e2..dec638763 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -522,7 +522,7 @@ wpan_dev_hard_header(struct sk_buff *skb, struct net_de= vice *dev, { struct wpan_dev *wpan_dev =3D dev->ieee802154_ptr; =20 - return wpan_dev->header_ops->create(skb, dev, daddr, saddr, len); + return READ_ONCE(wpan_dev->header_ops->create)(skb, dev, daddr, saddr, le= n); } #endif =20 diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 96786016d..ff948e35e 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1270,7 +1270,7 @@ static void neigh_update_hhs(struct neighbour *neigh) =3D NULL; =20 if (neigh->dev->header_ops) - update =3D neigh->dev->header_ops->cache_update; + update =3D READ_ONCE(neigh->dev->header_ops->cache_update); =20 if (update) { hh =3D &neigh->hh; @@ -1540,7 +1540,7 @@ static void neigh_hh_init(struct neighbour *n) * hh_cache entry. */ if (!hh->hh_len) - dev->header_ops->cache(n, hh, prot); + READ_ONCE(dev->header_ops->cache)(n, hh, prot); =20 write_unlock_bh(&n->lock); } @@ -1556,7 +1556,7 @@ int neigh_resolve_output(struct neighbour *neigh, str= uct sk_buff *skb) struct net_device *dev =3D neigh->dev; unsigned int seq; =20 - if (dev->header_ops->cache && !READ_ONCE(neigh->hh.hh_len)) + if (READ_ONCE(dev->header_ops->cache) && !READ_ONCE(neigh->hh.hh_len)) neigh_hh_init(neigh); =20 do { diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 7822b2144..421bea6eb 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -278,7 +278,7 @@ static int arp_constructor(struct neighbour *neigh) memcpy(neigh->ha, dev->broadcast, dev->addr_len); } =20 - if (dev->header_ops->cache) + if (READ_ONCE(dev->header_ops->cache)) neigh->ops =3D &arp_hh_ops; else neigh->ops =3D &arp_generic_ops; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index d961e6c2d..d81f509ec 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -361,7 +361,7 @@ static int ndisc_constructor(struct neighbour *neigh) neigh->nud_state =3D NUD_NOARP; memcpy(neigh->ha, dev->broadcast, dev->addr_len); } - if (dev->header_ops->cache) + if (READ_ONCE(dev->header_ops->cache)) neigh->ops =3D &ndisc_hh_ops; else neigh->ops =3D &ndisc_generic_ops; --=20 2.53.0