From: Greg Kroah-Hartman Date: Sat, 26 Aug 2023 16:20:10 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v6.1.49~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2049c1a44887231ffd86e9c9a3d6a659c08b0a90;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch ipvs-improve-robustness-to-the-ipvs-sysctl.patch --- diff --git a/queue-4.19/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch b/queue-4.19/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch new file mode 100644 index 00000000000..8852782b4c1 --- /dev/null +++ b/queue-4.19/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch @@ -0,0 +1,64 @@ +From 5310760af1d4fbea1452bfc77db5f9a680f7ae47 Mon Sep 17 00:00:00 2001 +From: Sishuai Gong +Date: Thu, 10 Aug 2023 15:12:42 -0400 +Subject: ipvs: fix racy memcpy in proc_do_sync_threshold + +From: Sishuai Gong + +commit 5310760af1d4fbea1452bfc77db5f9a680f7ae47 upstream. + +When two threads run proc_do_sync_threshold() in parallel, +data races could happen between the two memcpy(): + +Thread-1 Thread-2 +memcpy(val, valp, sizeof(val)); + memcpy(valp, val, sizeof(val)); + +This race might mess up the (struct ctl_table *) table->data, +so we add a mutex lock to serialize them. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Link: https://lore.kernel.org/netdev/B6988E90-0A1E-4B85-BF26-2DAF6D482433@gmail.com/ +Signed-off-by: Sishuai Gong +Acked-by: Simon Horman +Acked-by: Julian Anastasov +Signed-off-by: Florian Westphal +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipvs/ip_vs_ctl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -1690,6 +1690,7 @@ static int + proc_do_sync_threshold(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) + { ++ struct netns_ipvs *ipvs = table->extra2; + int *valp = table->data; + int val[2]; + int rc; +@@ -1699,6 +1700,7 @@ proc_do_sync_threshold(struct ctl_table + .mode = table->mode, + }; + ++ mutex_lock(&ipvs->sync_mutex); + memcpy(val, valp, sizeof(val)); + rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); + if (write) { +@@ -1708,6 +1710,7 @@ proc_do_sync_threshold(struct ctl_table + else + memcpy(valp, val, sizeof(val)); + } ++ mutex_unlock(&ipvs->sync_mutex); + return rc; + } + +@@ -3944,6 +3947,7 @@ static int __net_init ip_vs_control_net_ + ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD; + ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD; + tbl[idx].data = &ipvs->sysctl_sync_threshold; ++ tbl[idx].extra2 = ipvs; + tbl[idx++].maxlen = sizeof(ipvs->sysctl_sync_threshold); + ipvs->sysctl_sync_refresh_period = DEFAULT_SYNC_REFRESH_PERIOD; + tbl[idx++].data = &ipvs->sysctl_sync_refresh_period; diff --git a/queue-4.19/ipvs-improve-robustness-to-the-ipvs-sysctl.patch b/queue-4.19/ipvs-improve-robustness-to-the-ipvs-sysctl.patch new file mode 100644 index 00000000000..faa01ba5f7d --- /dev/null +++ b/queue-4.19/ipvs-improve-robustness-to-the-ipvs-sysctl.patch @@ -0,0 +1,141 @@ +From 1b90af292e71b20d03b837d39406acfbdc5d4b2a Mon Sep 17 00:00:00 2001 +From: Junwei Hu +Date: Thu, 1 Aug 2019 00:03:30 +0800 +Subject: ipvs: Improve robustness to the ipvs sysctl + +From: Junwei Hu + +commit 1b90af292e71b20d03b837d39406acfbdc5d4b2a upstream. + +The ipvs module parse the user buffer and save it to sysctl, +then check if the value is valid. invalid value occurs +over a period of time. +Here, I add a variable, struct ctl_table tmp, used to read +the value from the user buffer, and save only when it is valid. +I delete proc_do_sync_mode and use extra1/2 in table for the +proc_dointvec_minmax call. + +Fixes: f73181c8288f ("ipvs: add support for sync threads") +Signed-off-by: Junwei Hu +Acked-by: Julian Anastasov +Signed-off-by: Pablo Neira Ayuso +[Julian: Backport by changing SYSCTL_ZERO/SYSCTL_ONE to zero/one] +Signed-off-by: Julian Anastasov +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/ipvs/ip_vs_ctl.c | 70 +++++++++++++++++++++-------------------- + 1 file changed, 36 insertions(+), 34 deletions(-) + +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -1656,6 +1656,7 @@ static int ip_vs_zero_all(struct netns_i + #ifdef CONFIG_SYSCTL + + static int zero; ++static int one = 1; + static int three = 3; + + static int +@@ -1667,12 +1668,18 @@ proc_do_defense_mode(struct ctl_table *t + int val = *valp; + int rc; + +- rc = proc_dointvec(table, write, buffer, lenp, ppos); ++ struct ctl_table tmp = { ++ .data = &val, ++ .maxlen = sizeof(int), ++ .mode = table->mode, ++ }; ++ ++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); + if (write && (*valp != val)) { +- if ((*valp < 0) || (*valp > 3)) { +- /* Restore the correct value */ +- *valp = val; ++ if (val < 0 || val > 3) { ++ rc = -EINVAL; + } else { ++ *valp = val; + update_defense_level(ipvs); + } + } +@@ -1686,33 +1693,20 @@ proc_do_sync_threshold(struct ctl_table + int *valp = table->data; + int val[2]; + int rc; ++ struct ctl_table tmp = { ++ .data = &val, ++ .maxlen = table->maxlen, ++ .mode = table->mode, ++ }; + +- /* backup the value first */ + memcpy(val, valp, sizeof(val)); +- +- rc = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write && (valp[0] < 0 || valp[1] < 0 || +- (valp[0] >= valp[1] && valp[1]))) { +- /* Restore the correct value */ +- memcpy(valp, val, sizeof(val)); +- } +- return rc; +-} +- +-static int +-proc_do_sync_mode(struct ctl_table *table, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) +-{ +- int *valp = table->data; +- int val = *valp; +- int rc; +- +- rc = proc_dointvec(table, write, buffer, lenp, ppos); +- if (write && (*valp != val)) { +- if ((*valp < 0) || (*valp > 1)) { +- /* Restore the correct value */ +- *valp = val; +- } ++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); ++ if (write) { ++ if (val[0] < 0 || val[1] < 0 || ++ (val[0] >= val[1] && val[1])) ++ rc = -EINVAL; ++ else ++ memcpy(valp, val, sizeof(val)); + } + return rc; + } +@@ -1725,12 +1719,18 @@ proc_do_sync_ports(struct ctl_table *tab + int val = *valp; + int rc; + +- rc = proc_dointvec(table, write, buffer, lenp, ppos); ++ struct ctl_table tmp = { ++ .data = &val, ++ .maxlen = sizeof(int), ++ .mode = table->mode, ++ }; ++ ++ rc = proc_dointvec(&tmp, write, buffer, lenp, ppos); + if (write && (*valp != val)) { +- if (*valp < 1 || !is_power_of_2(*valp)) { +- /* Restore the correct value */ ++ if (val < 1 || !is_power_of_2(val)) ++ rc = -EINVAL; ++ else + *valp = val; +- } + } + return rc; + } +@@ -1790,7 +1790,9 @@ static struct ctl_table vs_vars[] = { + .procname = "sync_version", + .maxlen = sizeof(int), + .mode = 0644, +- .proc_handler = proc_do_sync_mode, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &one, + }, + { + .procname = "sync_ports", diff --git a/queue-4.19/series b/queue-4.19/series index d9c3e801625..4153df30cfc 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -116,3 +116,5 @@ igb-avoid-starting-unnecessary-workqueues.patch net-sched-fix-a-qdisc-modification-with-ambiguous-co.patch net-remove-bond_slave_has_mac_rcu.patch bonding-fix-macvlan-over-alb-bond-support.patch +ipvs-improve-robustness-to-the-ipvs-sysctl.patch +ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch