* [PATCH batadv] batman-adv: mark functions inheriting critical sections
@ 2026-10-15 7:08 Sven Eckelmann
[not found] ` <sashiko-outbox-172395@kernel.org>
0 siblings, 1 reply; 2+ messages in thread
From: Sven Eckelmann @ 2026-10-15 7:08 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
Various functions are not taking a lock themselves but are expecting the
caller to take care of holding the lock/RCU critical section. These are a
perfect use case for Compiler-Based Context Analysis.
For now, just mark these functions as preparation for __guarded_by().
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
The __guarded_by and also need following line at the beginning of
net/batman-adv/Makefile before it is possible to enable
`CONFIG_WARN_CONTEXT_ANALYSIS=y` with clang-23
CONTEXT_ANALYSIS := y
But I am not sure at the moment how to correctly handle some of the corner
cases of __guarded_by and thus didn't submit this part (yet).
---
net/batman-adv/bat_iv_ogm.c | 3 +++
net/batman-adv/bat_v.c | 2 ++
net/batman-adv/bat_v_ogm.c | 4 ++++
net/batman-adv/fragmentation.c | 1 +
net/batman-adv/fragmentation.h | 1 +
net/batman-adv/gateway_client.c | 1 +
net/batman-adv/multicast.c | 14 ++++++++++++++
net/batman-adv/translation-table.c | 4 ++++
net/batman-adv/tvlv.c | 3 +++
9 files changed, 33 insertions(+)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 85e99506..2ff2e446 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -893,6 +893,7 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
* @hard_iface: interface whose ogm buffer should be transmitted
*/
static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
+ __must_hold(&hard_iface->bat_iv.ogm_buff_mutex)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
struct batadv_ogm_buf *ogm_buff = &hard_iface->bat_iv.ogm_buff;
@@ -2105,6 +2106,7 @@ batadv_iv_ogm_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing,
struct batadv_orig_node *orig_node, int *sub_s)
+ __must_hold_shared(RCU)
{
struct batadv_neigh_node *neigh_node_best;
struct batadv_neigh_node *neigh_node;
@@ -2331,6 +2333,7 @@ batadv_iv_ogm_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_priv *bat_priv,
struct batadv_hard_iface *hard_iface,
int *idx_s)
+ __must_hold_shared(RCU)
{
struct batadv_hardif_neigh_node *hardif_neigh;
int idx = 0;
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index 596889b3..9aea526d 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -210,6 +210,7 @@ batadv_v_neigh_dump_hardif(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_priv *bat_priv,
struct batadv_hard_iface *hard_iface,
int *idx_s)
+ __must_hold_shared(RCU)
{
struct batadv_hardif_neigh_node *hardif_neigh;
int idx = 0;
@@ -365,6 +366,7 @@ batadv_v_orig_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing,
struct batadv_orig_node *orig_node, int *sub_s)
+ __must_hold_shared(RCU)
{
struct batadv_neigh_node *neigh_node_best;
struct batadv_neigh_node *neigh_node;
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index 70846c99..1427f055 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -162,6 +162,7 @@ static unsigned int batadv_v_ogm_len(struct sk_buff *skb)
*/
static bool batadv_v_ogm_queue_left(struct sk_buff *skb,
struct batadv_hard_iface *hard_iface)
+ __must_hold(&hard_iface->bat_v.aggr_list.lock)
{
unsigned int max = min_t(unsigned int, hard_iface->net_dev->mtu,
BATADV_MAX_AGGREGATION_BYTES);
@@ -181,6 +182,7 @@ static bool batadv_v_ogm_queue_left(struct sk_buff *skb,
* Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
*/
static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
+ __must_hold(&hard_iface->bat_v.aggr_list.lock)
{
lockdep_assert_held(&hard_iface->bat_v.aggr_list.lock);
@@ -200,6 +202,7 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)
* Caller needs to hold the hard_iface->bat_v.aggr_list.lock.
*/
static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)
+ __must_hold(&hard_iface->bat_v.aggr_list.lock)
{
unsigned int aggr_len = hard_iface->bat_v.aggr_len;
struct sk_buff *skb_aggr;
@@ -268,6 +271,7 @@ static void batadv_v_ogm_queue_on_if(struct sk_buff *skb,
* @bat_priv: the bat priv with all the mesh interface information
*/
static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
+ __must_hold(&bat_priv->bat_v.ogm_buff_mutex)
{
struct batadv_ogm2_packet *ogm_packet;
struct batadv_hard_iface *hard_iface;
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index 493af309..ac0478ed 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -107,6 +107,7 @@ static size_t batadv_frag_size_limit(void)
*/
static bool batadv_frag_init_chain(struct batadv_frag_table_entry *chain,
u16 seqno)
+ __must_hold(&chain->lock)
{
lockdep_assert_held(&chain->lock);
diff --git a/net/batman-adv/fragmentation.h b/net/batman-adv/fragmentation.h
index 51e28102..0b687fd2 100644
--- a/net/batman-adv/fragmentation.h
+++ b/net/batman-adv/fragmentation.h
@@ -35,6 +35,7 @@ int batadv_frag_send_packet(struct sk_buff *skb,
*/
static inline bool
batadv_frag_check_entry(struct batadv_frag_table_entry *frags_entry)
+ __must_hold(&frags_entry->lock)
{
if (!hlist_empty(&frags_entry->fragment_list) &&
batadv_has_timed_out(frags_entry->timestamp, BATADV_FRAG_TIMEOUT))
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index e6e97c04..51234e4f 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -333,6 +333,7 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
static void batadv_gw_node_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
struct batadv_tvlv_gateway_data *gateway)
+ __must_hold(&bat_priv->gw.list_lock)
{
struct batadv_gw_node *gw_node;
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index 22dd28d5..6ebab4eb 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -108,6 +108,7 @@ static struct net_device *batadv_mcast_get_bridge(struct net_device *mesh_iface)
* Return: BATADV_NO_FLAGS if present, BATADV_MCAST_WANT_NO_RTR4 otherwise.
*/
static u8 batadv_mcast_mla_rtr_flags_meshif_get_ipv4(struct net_device *dev)
+ __must_hold_shared(RCU)
{
struct in_device *in_dev = __in_dev_get_rcu(dev);
@@ -130,6 +131,7 @@ static u8 batadv_mcast_mla_rtr_flags_meshif_get_ipv4(struct net_device *dev)
*/
#if IS_ENABLED(CONFIG_IPV6_MROUTE)
static u8 batadv_mcast_mla_rtr_flags_meshif_get_ipv6(struct net_device *dev)
+ __must_hold_shared(RCU)
{
struct inet6_dev *in6_dev = __in6_dev_get(dev);
@@ -683,6 +685,7 @@ static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
*/
static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
@@ -713,6 +716,7 @@ static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
*/
static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv,
struct hlist_head *mcast_list)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
struct batadv_hw_addr *mcast_entry;
struct hlist_node *tmp;
@@ -761,6 +765,7 @@ static void
batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
struct batadv_mcast_querier_state *old_state,
struct batadv_mcast_querier_state *new_state)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
if (!old_state->exists && new_state->exists)
batadv_info(bat_priv->mesh_iface, "%s Querier appeared\n",
@@ -806,6 +811,7 @@ batadv_mcast_querier_log(struct batadv_priv *bat_priv, char *str_proto,
static void
batadv_mcast_bridge_log(struct batadv_priv *bat_priv,
struct batadv_mcast_mla_flags *new_flags)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
struct batadv_mcast_mla_flags *old_flags = &bat_priv->mcast.mla_flags;
@@ -835,6 +841,7 @@ batadv_mcast_bridge_log(struct batadv_priv *bat_priv,
* should be used to notify userspace about the change.
*/
static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
bool old_enabled = bat_priv->mcast.mla_flags.enabled;
u8 old_flags = bat_priv->mcast.mla_flags.tvlv_flags;
@@ -870,6 +877,7 @@ static void batadv_mcast_flags_log(struct batadv_priv *bat_priv, u8 flags)
static void
batadv_mcast_mla_flags_update(struct batadv_priv *bat_priv,
struct batadv_mcast_mla_flags *flags)
+ __must_hold(&bat_priv->mcast.mla_lock)
{
struct batadv_tvlv_mcast_data mcast_data;
@@ -1612,6 +1620,7 @@ int batadv_mcast_forw_send(struct batadv_priv *bat_priv, struct sk_buff *skb,
static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
struct hlist_head *head = &bat_priv->mcast.want_all_unsnoopables_list;
struct hlist_node *node = &orig->mcast_want_all_unsnoopables_node;
@@ -1657,6 +1666,7 @@ static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv,
static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
struct hlist_head *head = &bat_priv->mcast.want_all_ipv4_list;
struct hlist_node *node = &orig->mcast_want_all_ipv4_node;
@@ -1702,6 +1712,7 @@ static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv,
static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
struct hlist_head *head = &bat_priv->mcast.want_all_ipv6_list;
struct hlist_node *node = &orig->mcast_want_all_ipv6_node;
@@ -1747,6 +1758,7 @@ static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv,
static void batadv_mcast_want_rtr4_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
struct hlist_head *head = &bat_priv->mcast.want_all_rtr4_list;
struct hlist_node *node = &orig->mcast_want_all_rtr4_node;
@@ -1792,6 +1804,7 @@ static void batadv_mcast_want_rtr4_update(struct batadv_priv *bat_priv,
static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
struct hlist_head *head = &bat_priv->mcast.want_all_rtr6_list;
struct hlist_node *node = &orig->mcast_want_all_rtr6_node;
@@ -1835,6 +1848,7 @@ static void batadv_mcast_want_rtr6_update(struct batadv_priv *bat_priv,
static void batadv_mcast_have_mc_ptype_update(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig,
u8 mcast_flags)
+ __must_hold(&orig->mcast_handler_lock)
{
lockdep_assert_held(&orig->mcast_handler_lock);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index e46040fd..2b9e9fd2 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -2357,6 +2357,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
static struct batadv_tt_orig_list_entry *
batadv_transtable_best_orig(struct batadv_priv *bat_priv,
struct batadv_tt_global_entry *tt_global_entry)
+ __must_hold_shared(RCU)
{
struct batadv_tt_orig_list_entry *best_entry = NULL;
struct batadv_algo_ops *bao = bat_priv->algo_ops;
@@ -2470,6 +2471,7 @@ static int
batadv_tt_global_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
struct batadv_priv *bat_priv,
struct batadv_tt_common_entry *common, int *sub_s)
+ __must_hold_shared(RCU)
{
struct batadv_tt_orig_list_entry *orig_entry;
struct batadv_tt_orig_list_entry *best_entry;
@@ -2610,6 +2612,7 @@ int batadv_tt_global_dump(struct sk_buff *msg, struct netlink_callback *cb)
static void
_batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry,
struct batadv_tt_orig_list_entry *orig_entry)
+ __must_hold(&tt_global_entry->list_lock)
{
lockdep_assert_held(&tt_global_entry->list_lock);
@@ -4464,6 +4467,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
* Caller must hold tt->commit_lock.
*/
static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv)
+ __must_hold(&bat_priv->tt.commit_lock)
{
lockdep_assert_held(&bat_priv->tt.commit_lock);
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index 93492d39..d1e402e2 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -134,6 +134,7 @@ static void batadv_tvlv_container_put(struct batadv_tvlv_container *tvlv)
*/
static struct batadv_tvlv_container *
batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
+ __must_hold(&bat_priv->tvlv.container_list_lock)
{
struct batadv_tvlv_container *tvlv = NULL;
struct batadv_tvlv_container *tvlv_tmp;
@@ -166,6 +167,7 @@ batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)
* Return: size of all currently registered tvlv containers in bytes.
*/
static size_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
+ __must_hold(&bat_priv->tvlv.container_list_lock)
{
struct batadv_tvlv_container *tvlv;
size_t tvlv_len = 0;
@@ -191,6 +193,7 @@ static size_t batadv_tvlv_container_list_size(struct batadv_priv *bat_priv)
*/
static void batadv_tvlv_container_remove(struct batadv_priv *bat_priv,
struct batadv_tvlv_container *tvlv)
+ __must_hold(&bat_priv->tvlv.container_list_lock)
{
lockdep_assert_held(&bat_priv->tvlv.container_list_lock);
---
base-commit: 0eaac0f4187bc9b69b41d90998fd7b93ab07e53e
change-id: 20261015-must_hold-92c4ef54c668
Best regards,
--
Sven Eckelmann <sven@narfation.org>
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH batadv] batman-adv: mark functions inheriting critical sections
[not found] ` <sashiko-outbox-172395@kernel.org>
@ 2026-10-15 7:26 ` Sven Eckelmann
0 siblings, 0 replies; 2+ messages in thread
From: Sven Eckelmann @ 2026-10-15 7:26 UTC (permalink / raw)
To: sashiko-reviews; +Cc: marek.lindner, sw, antonio, b.a.t.m.a.n
[-- Attachment #1: Type: text/plain, Size: 1829 bytes --]
On Thursday, 15 October 2026 09:22:30 CEST sashiko-bot@kernel.org wrote:
[...]
> [Severity: Low]
> Does adding this capability annotation break the type signature when passed
> as a function pointer?
>
> In net/batman-adv/originator.c, batadv_frag_check_entry() is passed as the
> check_cb argument to batadv_frag_purge_orig():
>
> batadv_frag_purge_orig(orig_node,
> batadv_frag_check_entry);
>
> Because the check_cb function pointer definition lacks the corresponding
> capability annotation, this creates a capability type mismatch that leads to
> a static analysis warning or error during context analysis.
No, it doesn't in my tests.
>
> [ ... ]
>
> > diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
> > index 22dd28d5e1abc..6ebab4eb1382e 100644
> > --- a/net/batman-adv/multicast.c
> > +++ b/net/batman-adv/multicast.c
> > @@ -683,6 +685,7 @@ static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list)
> > */
> > static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv,
> > struct hlist_head *mcast_list)
> > + __must_hold(&bat_priv->mcast.mla_lock)
> > {
>
> [Severity: Low]
> Is it possible this annotation is violated during teardown?
>
> In batadv_mcast_free(), the code intentionally skips acquiring mla_lock
> because it relies on implicit serialization after the worker is canceled:
>
> /* safely calling outside of worker, as worker was canceled above */
> batadv_mcast_mla_tt_retract(bat_priv, NULL);
>
> However, batadv_mcast_mla_tt_retract() is now strictly annotated to require
> the lock, which will cause a build warning or error when compiled with
> CONFIG_WARN_CONTEXT_ANALYSIS=y. Is this one of the corner cases preventing
> the enablement of CONTEXT_ANALYSIS := y?
Yes, it is one one of the corner cases.
Regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-15 7:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-15 7:08 [PATCH batadv] batman-adv: mark functions inheriting critical sections Sven Eckelmann
[not found] ` <sashiko-outbox-172395@kernel.org>
2026-10-15 7:26 ` Sven Eckelmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox