The update_userdata() function constructs the complete userdata string in nt->extradata_complete and updates nt->userdata_length. This data is then read by write_msg() and write_ext_msg() when sending netconsole messages. However, update_userdata() was not holding target_list_lock during this process, allowing concurrent message transmission to read partially updated userdata.
This race condition could result in netconsole messages containing incomplete or inconsistent userdata - for example, reading the old userdata_length with new extradata_complete content, or vice versa, leading to truncated or corrupted output.
Fix this by acquiring target_list_lock with spin_lock_irqsave() before updating extradata_complete and userdata_length, and releasing it after both fields are fully updated. This ensures that readers see a consistent view of the userdata, preventing corruption during concurrent access.
The fix aligns with the existing locking pattern used throughout the netconsole code, where target_list_lock protects access to target fields including buf[] and msgcounter that are accessed during message transmission.
Fixes: df03f830d099 ("net: netconsole: cache userdata formatted string in netconsole_target") Signed-off-by: Gustavo Luiz Duarte gustavold@gmail.com --- drivers/net/netconsole.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 194570443493..1f9cf6b12dfc 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -888,6 +888,9 @@ static void update_userdata(struct netconsole_target *nt) { int complete_idx = 0, child_count = 0; struct list_head *entry; + unsigned long flags; + + spin_lock_irqsave(&target_list_lock, flags);
/* Clear the current string in case the last userdatum was deleted */ nt->userdata_length = 0; @@ -918,6 +921,8 @@ static void update_userdata(struct netconsole_target *nt) } nt->userdata_length = strnlen(nt->extradata_complete, sizeof(nt->extradata_complete)); + + spin_unlock_irqrestore(&target_list_lock, flags); }
static ssize_t userdatum_value_store(struct config_item *item, const char *buf,