forked from Minki/linux
ipvs: move old_secure_tcp into struct netns_ipvs
syzbot reported the following issue :
BUG: KCSAN: data-race in update_defense_level / update_defense_level
read to 0xffffffff861a6260 of 4 bytes by task 3006 on cpu 1:
update_defense_level+0x621/0xb30 net/netfilter/ipvs/ip_vs_ctl.c:177
defense_work_handler+0x3d/0xd0 net/netfilter/ipvs/ip_vs_ctl.c:225
process_one_work+0x3d4/0x890 kernel/workqueue.c:2269
worker_thread+0xa0/0x800 kernel/workqueue.c:2415
kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
write to 0xffffffff861a6260 of 4 bytes by task 7333 on cpu 0:
update_defense_level+0xa62/0xb30 net/netfilter/ipvs/ip_vs_ctl.c:205
defense_work_handler+0x3d/0xd0 net/netfilter/ipvs/ip_vs_ctl.c:225
process_one_work+0x3d4/0x890 kernel/workqueue.c:2269
worker_thread+0xa0/0x800 kernel/workqueue.c:2415
kthread+0x1d4/0x200 drivers/block/aoe/aoecmd.c:1253
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:352
Reported by Kernel Concurrency Sanitizer on:
CPU: 0 PID: 7333 Comm: kworker/0:5 Not tainted 5.4.0-rc3+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: events defense_work_handler
Indeed, old_secure_tcp is currently a static variable, while it
needs to be a per netns variable.
Fixes: a0840e2e16
("IPVS: netns, ip_vs_ctl local vars moved to ipvs struct.")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
parent
62931f59ce
commit
c24b75e0f9
@ -889,6 +889,7 @@ struct netns_ipvs {
|
|||||||
struct delayed_work defense_work; /* Work handler */
|
struct delayed_work defense_work; /* Work handler */
|
||||||
int drop_rate;
|
int drop_rate;
|
||||||
int drop_counter;
|
int drop_counter;
|
||||||
|
int old_secure_tcp;
|
||||||
atomic_t dropentry;
|
atomic_t dropentry;
|
||||||
/* locks in ctl.c */
|
/* locks in ctl.c */
|
||||||
spinlock_t dropentry_lock; /* drop entry handling */
|
spinlock_t dropentry_lock; /* drop entry handling */
|
||||||
|
@ -93,7 +93,6 @@ static bool __ip_vs_addr_is_local_v6(struct net *net,
|
|||||||
static void update_defense_level(struct netns_ipvs *ipvs)
|
static void update_defense_level(struct netns_ipvs *ipvs)
|
||||||
{
|
{
|
||||||
struct sysinfo i;
|
struct sysinfo i;
|
||||||
static int old_secure_tcp = 0;
|
|
||||||
int availmem;
|
int availmem;
|
||||||
int nomem;
|
int nomem;
|
||||||
int to_change = -1;
|
int to_change = -1;
|
||||||
@ -174,35 +173,35 @@ static void update_defense_level(struct netns_ipvs *ipvs)
|
|||||||
spin_lock(&ipvs->securetcp_lock);
|
spin_lock(&ipvs->securetcp_lock);
|
||||||
switch (ipvs->sysctl_secure_tcp) {
|
switch (ipvs->sysctl_secure_tcp) {
|
||||||
case 0:
|
case 0:
|
||||||
if (old_secure_tcp >= 2)
|
if (ipvs->old_secure_tcp >= 2)
|
||||||
to_change = 0;
|
to_change = 0;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (nomem) {
|
if (nomem) {
|
||||||
if (old_secure_tcp < 2)
|
if (ipvs->old_secure_tcp < 2)
|
||||||
to_change = 1;
|
to_change = 1;
|
||||||
ipvs->sysctl_secure_tcp = 2;
|
ipvs->sysctl_secure_tcp = 2;
|
||||||
} else {
|
} else {
|
||||||
if (old_secure_tcp >= 2)
|
if (ipvs->old_secure_tcp >= 2)
|
||||||
to_change = 0;
|
to_change = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (nomem) {
|
if (nomem) {
|
||||||
if (old_secure_tcp < 2)
|
if (ipvs->old_secure_tcp < 2)
|
||||||
to_change = 1;
|
to_change = 1;
|
||||||
} else {
|
} else {
|
||||||
if (old_secure_tcp >= 2)
|
if (ipvs->old_secure_tcp >= 2)
|
||||||
to_change = 0;
|
to_change = 0;
|
||||||
ipvs->sysctl_secure_tcp = 1;
|
ipvs->sysctl_secure_tcp = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (old_secure_tcp < 2)
|
if (ipvs->old_secure_tcp < 2)
|
||||||
to_change = 1;
|
to_change = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
old_secure_tcp = ipvs->sysctl_secure_tcp;
|
ipvs->old_secure_tcp = ipvs->sysctl_secure_tcp;
|
||||||
if (to_change >= 0)
|
if (to_change >= 0)
|
||||||
ip_vs_protocol_timeout_change(ipvs,
|
ip_vs_protocol_timeout_change(ipvs,
|
||||||
ipvs->sysctl_secure_tcp > 1);
|
ipvs->sysctl_secure_tcp > 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user