提交 ff5e92c1 编写于 作者: D Daniel Borkmann 提交者: David S. Miller

net: sctp: propagate sysctl errors from proc_do* properly

sysctl handler proc_sctp_do_hmac_alg(), proc_sctp_do_rto_min() and
proc_sctp_do_rto_max() do not properly reflect some error cases
when writing values via sysctl from internal proc functions such
as proc_dointvec() and proc_dostring().

In all these cases we pass the test for write != 0 and partially
do additional work just to notice that additional sanity checks
fail and we return with hard-coded -EINVAL while proc_do*
functions might also return different errors. So fix this up by
simply testing a successful return of proc_do* right after
calling it.

This also allows to propagate its return value onwards to the user.
While touching this, also fix up some minor style issues.

Fixes: 4f3fdf3b ("sctp: add check rto_min and rto_max in sysctl")
Fixes: 3c68198e ("sctp: Make hmac algorithm selection for cookie generation dynamic")
Signed-off-by: NDaniel Borkmann <dborkman@redhat.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 d36a4f4b
...@@ -321,41 +321,40 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write, ...@@ -321,41 +321,40 @@ static int proc_sctp_do_hmac_alg(struct ctl_table *ctl, int write,
loff_t *ppos) loff_t *ppos)
{ {
struct net *net = current->nsproxy->net_ns; struct net *net = current->nsproxy->net_ns;
char tmp[8];
struct ctl_table tbl; struct ctl_table tbl;
int ret; bool changed = false;
int changed = 0;
char *none = "none"; char *none = "none";
char tmp[8];
int ret;
memset(&tbl, 0, sizeof(struct ctl_table)); memset(&tbl, 0, sizeof(struct ctl_table));
if (write) { if (write) {
tbl.data = tmp; tbl.data = tmp;
tbl.maxlen = 8; tbl.maxlen = sizeof(tmp);
} else { } else {
tbl.data = net->sctp.sctp_hmac_alg ? : none; tbl.data = net->sctp.sctp_hmac_alg ? : none;
tbl.maxlen = strlen(tbl.data); tbl.maxlen = strlen(tbl.data);
} }
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
if (write) { ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
if (write && ret == 0) {
#ifdef CONFIG_CRYPTO_MD5 #ifdef CONFIG_CRYPTO_MD5
if (!strncmp(tmp, "md5", 3)) { if (!strncmp(tmp, "md5", 3)) {
net->sctp.sctp_hmac_alg = "md5"; net->sctp.sctp_hmac_alg = "md5";
changed = 1; changed = true;
} }
#endif #endif
#ifdef CONFIG_CRYPTO_SHA1 #ifdef CONFIG_CRYPTO_SHA1
if (!strncmp(tmp, "sha1", 4)) { if (!strncmp(tmp, "sha1", 4)) {
net->sctp.sctp_hmac_alg = "sha1"; net->sctp.sctp_hmac_alg = "sha1";
changed = 1; changed = true;
} }
#endif #endif
if (!strncmp(tmp, "none", 4)) { if (!strncmp(tmp, "none", 4)) {
net->sctp.sctp_hmac_alg = NULL; net->sctp.sctp_hmac_alg = NULL;
changed = 1; changed = true;
} }
if (!changed) if (!changed)
ret = -EINVAL; ret = -EINVAL;
} }
...@@ -368,11 +367,10 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, ...@@ -368,11 +367,10 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
loff_t *ppos) loff_t *ppos)
{ {
struct net *net = current->nsproxy->net_ns; struct net *net = current->nsproxy->net_ns;
int new_value;
struct ctl_table tbl;
unsigned int min = *(unsigned int *) ctl->extra1; unsigned int min = *(unsigned int *) ctl->extra1;
unsigned int max = *(unsigned int *) ctl->extra2; unsigned int max = *(unsigned int *) ctl->extra2;
int ret; struct ctl_table tbl;
int ret, new_value;
memset(&tbl, 0, sizeof(struct ctl_table)); memset(&tbl, 0, sizeof(struct ctl_table));
tbl.maxlen = sizeof(unsigned int); tbl.maxlen = sizeof(unsigned int);
...@@ -381,12 +379,15 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, ...@@ -381,12 +379,15 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
tbl.data = &new_value; tbl.data = &new_value;
else else
tbl.data = &net->sctp.rto_min; tbl.data = &net->sctp.rto_min;
ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
if (write) { if (write && ret == 0) {
if (ret || new_value > max || new_value < min) if (new_value > max || new_value < min)
return -EINVAL; return -EINVAL;
net->sctp.rto_min = new_value; net->sctp.rto_min = new_value;
} }
return ret; return ret;
} }
...@@ -395,11 +396,10 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, ...@@ -395,11 +396,10 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
loff_t *ppos) loff_t *ppos)
{ {
struct net *net = current->nsproxy->net_ns; struct net *net = current->nsproxy->net_ns;
int new_value;
struct ctl_table tbl;
unsigned int min = *(unsigned int *) ctl->extra1; unsigned int min = *(unsigned int *) ctl->extra1;
unsigned int max = *(unsigned int *) ctl->extra2; unsigned int max = *(unsigned int *) ctl->extra2;
int ret; struct ctl_table tbl;
int ret, new_value;
memset(&tbl, 0, sizeof(struct ctl_table)); memset(&tbl, 0, sizeof(struct ctl_table));
tbl.maxlen = sizeof(unsigned int); tbl.maxlen = sizeof(unsigned int);
...@@ -408,12 +408,15 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, ...@@ -408,12 +408,15 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
tbl.data = &new_value; tbl.data = &new_value;
else else
tbl.data = &net->sctp.rto_max; tbl.data = &net->sctp.rto_max;
ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); ret = proc_dointvec(&tbl, write, buffer, lenp, ppos);
if (write) { if (write && ret == 0) {
if (ret || new_value > max || new_value < min) if (new_value > max || new_value < min)
return -EINVAL; return -EINVAL;
net->sctp.rto_max = new_value; net->sctp.rto_max = new_value;
} }
return ret; return ret;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册