Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 005261c5 authored by Junwei Hu's avatar Junwei Hu Committed by Greg Kroah-Hartman
Browse files

ipvs: Improve robustness to the ipvs sysctl



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: f73181c8 ("ipvs: add support for sync threads")
Signed-off-by: default avatarJunwei Hu <hujunwei4@huawei.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
[Julian: Backport by changing SYSCTL_ZERO/SYSCTL_ONE to zero/one]
Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f916e598
Loading
Loading
Loading
Loading
+36 −34
Original line number Diff line number Diff line
@@ -1656,6 +1656,7 @@ static int ip_vs_zero_all(struct netns_ipvs *ipvs)
#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 *table, int write,
	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,37 +1693,24 @@ proc_do_sync_threshold(struct ctl_table *table, int write,
	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 */
	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;
}

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;
		}
	}
	return rc;
}

static int
proc_do_sync_ports(struct ctl_table *table, int write,
		   void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -1725,13 +1719,19 @@ proc_do_sync_ports(struct ctl_table *table, int write,
	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",