diff options
author | Eduardo Blanco <ejblanco@google.com> | 2010-10-19 05:26:47 -0400 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2010-10-19 11:13:16 -0400 |
commit | d86bef73b4a24e59e7c1f896a72bbf38430ac2c6 (patch) | |
tree | 724097038b8d5bf76da75b55af13de23b46365f1 /net/netfilter | |
parent | 714f095f74582764d629785f03b459a3d0503624 (diff) |
Fixed race condition at ip_vs.ko module init.
Lists were initialized after the module was registered. Multiple ipvsadm
processes at module load triggered a race condition that resulted in a null
pointer dereference in do_ip_vs_get_ctl(). As a result, __ip_vs_mutex
was left locked preventing all further ipvsadm commands.
Signed-off-by: Eduardo J. Blanco <ejblanco@google.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'net/netfilter')
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index a697591d0e2..0b884d3e192 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -3400,6 +3400,16 @@ int __init ip_vs_control_init(void) | |||
3400 | 3400 | ||
3401 | EnterFunction(2); | 3401 | EnterFunction(2); |
3402 | 3402 | ||
3403 | /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */ | ||
3404 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | ||
3405 | INIT_LIST_HEAD(&ip_vs_svc_table[idx]); | ||
3406 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | ||
3407 | } | ||
3408 | for(idx = 0; idx < IP_VS_RTAB_SIZE; idx++) { | ||
3409 | INIT_LIST_HEAD(&ip_vs_rtable[idx]); | ||
3410 | } | ||
3411 | smp_wmb(); | ||
3412 | |||
3403 | ret = nf_register_sockopt(&ip_vs_sockopts); | 3413 | ret = nf_register_sockopt(&ip_vs_sockopts); |
3404 | if (ret) { | 3414 | if (ret) { |
3405 | pr_err("cannot register sockopt.\n"); | 3415 | pr_err("cannot register sockopt.\n"); |
@@ -3418,15 +3428,6 @@ int __init ip_vs_control_init(void) | |||
3418 | 3428 | ||
3419 | sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars); | 3429 | sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars); |
3420 | 3430 | ||
3421 | /* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */ | ||
3422 | for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | ||
3423 | INIT_LIST_HEAD(&ip_vs_svc_table[idx]); | ||
3424 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | ||
3425 | } | ||
3426 | for(idx = 0; idx < IP_VS_RTAB_SIZE; idx++) { | ||
3427 | INIT_LIST_HEAD(&ip_vs_rtable[idx]); | ||
3428 | } | ||
3429 | |||
3430 | ip_vs_new_estimator(&ip_vs_stats); | 3431 | ip_vs_new_estimator(&ip_vs_stats); |
3431 | 3432 | ||
3432 | /* Hook the defense timer */ | 3433 | /* Hook the defense timer */ |