mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
Merge branch 'net-sysctl-avoid-using-current-nsproxy'
Matthieu Baerts says: ==================== net: sysctl: avoid using current->nsproxy As pointed out by Al Viro and Eric Dumazet in [1], using the 'net' structure via 'current' is not recommended for different reasons: - Inconsistency: getting info from the reader's/writer's netns vs only from the opener's netns as it is usually done. This could cause unexpected issues when other operations are done on the wrong netns. - current->nsproxy can be NULL in some cases, resulting in an 'Oops' (null-ptr-deref), e.g. when the current task is exiting, as spotted by syzbot [1] using acct(2). The 'net' or 'pernet' structure can be obtained from the table->data using container_of(). Note that table->data could also be used directly in more places, but that would increase the size of this fix to replace all accesses via 'net'. Probably best to avoid that for fixes. Patches 2-9 remove access of net via current->nsproxy in sysfs handlers in MPTCP, SCTP and RDS. There are multiple patches doing almost the same thing, but the reason is to ease the backports. Patch 1 is not directly linked to this, but it is a small fix for MPTCP available_schedulers sysctl knob to explicitly mark it as read-only. Please note that this series does not address Al's comment [2]. In SCTP, some sysctl knobs set other sysfs-exposed variables for the min/max: two processes could then write two linked values at the same time, resulting in new values being outside the new boundaries. It would be great if SCTP developers can look at this problem. Link: https://lore.kernel.org/67769ecb.050a0220.3a8527.003f.GAE@google.com [1] Link: https://lore.kernel.org/20250105211158.GL1977892@ZenIV [2] ==================== Link: https://patch.msgid.link/20250108-net-sysctl-current-nsproxy-v1-0-5df34b2083e8@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2664bc9c7d
|
|
@ -102,16 +102,15 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
static int mptcp_set_scheduler(const struct net *net, const char *name)
|
||||
static int mptcp_set_scheduler(char *scheduler, const char *name)
|
||||
{
|
||||
struct mptcp_pernet *pernet = mptcp_get_pernet(net);
|
||||
struct mptcp_sched_ops *sched;
|
||||
int ret = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
sched = mptcp_sched_find(name);
|
||||
if (sched)
|
||||
strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX);
|
||||
strscpy(scheduler, name, MPTCP_SCHED_NAME_MAX);
|
||||
else
|
||||
ret = -ENOENT;
|
||||
rcu_read_unlock();
|
||||
|
|
@ -122,7 +121,7 @@ static int mptcp_set_scheduler(const struct net *net, const char *name)
|
|||
static int proc_scheduler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
const struct net *net = current->nsproxy->net_ns;
|
||||
char (*scheduler)[MPTCP_SCHED_NAME_MAX] = ctl->data;
|
||||
char val[MPTCP_SCHED_NAME_MAX];
|
||||
struct ctl_table tbl = {
|
||||
.data = val,
|
||||
|
|
@ -130,11 +129,11 @@ static int proc_scheduler(const struct ctl_table *ctl, int write,
|
|||
};
|
||||
int ret;
|
||||
|
||||
strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX);
|
||||
strscpy(val, *scheduler, MPTCP_SCHED_NAME_MAX);
|
||||
|
||||
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
|
||||
if (write && ret == 0)
|
||||
ret = mptcp_set_scheduler(net, val);
|
||||
ret = mptcp_set_scheduler(*scheduler, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -161,7 +160,9 @@ static int proc_blackhole_detect_timeout(const struct ctl_table *table,
|
|||
int write, void *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct mptcp_pernet *pernet = mptcp_get_pernet(current->nsproxy->net_ns);
|
||||
struct mptcp_pernet *pernet = container_of(table->data,
|
||||
struct mptcp_pernet,
|
||||
blackhole_timeout);
|
||||
int ret;
|
||||
|
||||
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||
|
|
@ -228,7 +229,7 @@ static struct ctl_table mptcp_sysctl_table[] = {
|
|||
{
|
||||
.procname = "available_schedulers",
|
||||
.maxlen = MPTCP_SCHED_BUF_MAX,
|
||||
.mode = 0644,
|
||||
.mode = 0444,
|
||||
.proc_handler = proc_available_schedulers,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,8 +61,10 @@ static atomic_t rds_tcp_unloading = ATOMIC_INIT(0);
|
|||
|
||||
static struct kmem_cache *rds_tcp_conn_slab;
|
||||
|
||||
static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos);
|
||||
static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos);
|
||||
static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos);
|
||||
|
||||
static int rds_tcp_min_sndbuf = SOCK_MIN_SNDBUF;
|
||||
static int rds_tcp_min_rcvbuf = SOCK_MIN_RCVBUF;
|
||||
|
|
@ -74,7 +76,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
|
|||
/* data is per-net pointer */
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = rds_tcp_skbuf_handler,
|
||||
.proc_handler = rds_tcp_sndbuf_handler,
|
||||
.extra1 = &rds_tcp_min_sndbuf,
|
||||
},
|
||||
#define RDS_TCP_RCVBUF 1
|
||||
|
|
@ -83,7 +85,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
|
|||
/* data is per-net pointer */
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = rds_tcp_skbuf_handler,
|
||||
.proc_handler = rds_tcp_rcvbuf_handler,
|
||||
.extra1 = &rds_tcp_min_rcvbuf,
|
||||
},
|
||||
};
|
||||
|
|
@ -682,10 +684,10 @@ static void rds_tcp_sysctl_reset(struct net *net)
|
|||
spin_unlock_irq(&rds_tcp_conn_lock);
|
||||
}
|
||||
|
||||
static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
|
||||
static int rds_tcp_skbuf_handler(struct rds_tcp_net *rtn,
|
||||
const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
int err;
|
||||
|
||||
err = proc_dointvec_minmax(ctl, write, buffer, lenp, fpos);
|
||||
|
|
@ -694,11 +696,34 @@ static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
|
|||
*(int *)(ctl->extra1));
|
||||
return err;
|
||||
}
|
||||
if (write)
|
||||
|
||||
if (write && rtn->rds_tcp_listen_sock && rtn->rds_tcp_listen_sock->sk) {
|
||||
struct net *net = sock_net(rtn->rds_tcp_listen_sock->sk);
|
||||
|
||||
rds_tcp_sysctl_reset(net);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos)
|
||||
{
|
||||
struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
|
||||
sndbuf_size);
|
||||
|
||||
return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
|
||||
}
|
||||
|
||||
static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *fpos)
|
||||
{
|
||||
struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
|
||||
rcvbuf_size);
|
||||
|
||||
return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
|
||||
}
|
||||
|
||||
static void rds_tcp_exit(void)
|
||||
{
|
||||
rds_tcp_set_unloading();
|
||||
|
|
|
|||
|
|
@ -387,7 +387,8 @@ static struct ctl_table sctp_net_table[] = {
|
|||
static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net,
|
||||
sctp.sctp_hmac_alg);
|
||||
struct ctl_table tbl;
|
||||
bool changed = false;
|
||||
char *none = "none";
|
||||
|
|
@ -432,7 +433,7 @@ static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
|
|||
static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net, sctp.rto_min);
|
||||
unsigned int min = *(unsigned int *) ctl->extra1;
|
||||
unsigned int max = *(unsigned int *) ctl->extra2;
|
||||
struct ctl_table tbl;
|
||||
|
|
@ -460,7 +461,7 @@ static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
|
|||
static int proc_sctp_do_rto_max(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net, sctp.rto_max);
|
||||
unsigned int min = *(unsigned int *) ctl->extra1;
|
||||
unsigned int max = *(unsigned int *) ctl->extra2;
|
||||
struct ctl_table tbl;
|
||||
|
|
@ -498,7 +499,7 @@ static int proc_sctp_do_alpha_beta(const struct ctl_table *ctl, int write,
|
|||
static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net, sctp.auth_enable);
|
||||
struct ctl_table tbl;
|
||||
int new_value, ret;
|
||||
|
||||
|
|
@ -527,7 +528,7 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
|
|||
static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net, sctp.udp_port);
|
||||
unsigned int min = *(unsigned int *)ctl->extra1;
|
||||
unsigned int max = *(unsigned int *)ctl->extra2;
|
||||
struct ctl_table tbl;
|
||||
|
|
@ -568,7 +569,8 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
|
|||
static int proc_sctp_do_probe_interval(const struct ctl_table *ctl, int write,
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
struct net *net = container_of(ctl->data, struct net,
|
||||
sctp.probe_interval);
|
||||
struct ctl_table tbl;
|
||||
int ret, new_value;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user