From d38c94c534edf32d648b4ff3f2181a29cd325718 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 26 Aug 2023 18:19:59 +0200 Subject: [PATCH] 4.14-stable patches added patches: ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch ipvs-improve-robustness-to-the-ipvs-sysctl.patch --- ...acy-memcpy-in-proc_do_sync_threshold.patch | 64 ++++++++ ...mprove-robustness-to-the-ipvs-sysctl.patch | 141 ++++++++++++++++++ queue-4.14/series | 2 + 3 files changed, 207 insertions(+) create mode 100644 queue-4.14/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch create mode 100644 queue-4.14/ipvs-improve-robustness-to-the-ipvs-sysctl.patch diff --git a/queue-4.14/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch b/queue-4.14/ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch new file mode 100644 index 00000000000..2b326973b2d --- /dev/null +++ b/queue-4.14/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 +@@ -1682,6 +1682,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; +@@ -1691,6 +1692,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) { +@@ -1700,6 +1702,7 @@ proc_do_sync_threshold(struct ctl_table + else + memcpy(valp, val, sizeof(val)); + } ++ mutex_unlock(&ipvs->sync_mutex); + return rc; + } + +@@ -3976,6 +3979,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.14/ipvs-improve-robustness-to-the-ipvs-sysctl.patch b/queue-4.14/ipvs-improve-robustness-to-the-ipvs-sysctl.patch new file mode 100644 index 00000000000..ae853300ea0 --- /dev/null +++ b/queue-4.14/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 +@@ -1648,6 +1648,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 +@@ -1659,12 +1660,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); + } + } +@@ -1678,33 +1685,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; + } +@@ -1717,12 +1711,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; + } +@@ -1782,7 +1782,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.14/series b/queue-4.14/series index 7931e178510..c61bb91eeb9 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -41,3 +41,5 @@ net-phy-broadcom-stub-c45-read-write-for-54810.patch tracing-fix-memleak-due-to-race-between-current_trac.patch sock-annotate-data-races-around-prot-memory_pressure.patch igb-avoid-starting-unnecessary-workqueues.patch +ipvs-improve-robustness-to-the-ipvs-sysctl.patch +ipvs-fix-racy-memcpy-in-proc_do_sync_threshold.patch -- 2.47.3