Skip to content

Commit 2664bc9

Browse files
committed
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/[email protected] [1] Link: https://lore.kernel.org/20250105211158.GL1977892@ZenIV [2] ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 92afd9f + 7f5611c commit 2664bc9

File tree

3 files changed

+49
-21
lines changed

3 files changed

+49
-21
lines changed

net/mptcp/ctrl.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,16 +102,15 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
102102
}
103103

104104
#ifdef CONFIG_SYSCTL
105-
static int mptcp_set_scheduler(const struct net *net, const char *name)
105+
static int mptcp_set_scheduler(char *scheduler, const char *name)
106106
{
107-
struct mptcp_pernet *pernet = mptcp_get_pernet(net);
108107
struct mptcp_sched_ops *sched;
109108
int ret = 0;
110109

111110
rcu_read_lock();
112111
sched = mptcp_sched_find(name);
113112
if (sched)
114-
strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX);
113+
strscpy(scheduler, name, MPTCP_SCHED_NAME_MAX);
115114
else
116115
ret = -ENOENT;
117116
rcu_read_unlock();
@@ -122,19 +121,19 @@ static int mptcp_set_scheduler(const struct net *net, const char *name)
122121
static int proc_scheduler(const struct ctl_table *ctl, int write,
123122
void *buffer, size_t *lenp, loff_t *ppos)
124123
{
125-
const struct net *net = current->nsproxy->net_ns;
124+
char (*scheduler)[MPTCP_SCHED_NAME_MAX] = ctl->data;
126125
char val[MPTCP_SCHED_NAME_MAX];
127126
struct ctl_table tbl = {
128127
.data = val,
129128
.maxlen = MPTCP_SCHED_NAME_MAX,
130129
};
131130
int ret;
132131

133-
strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX);
132+
strscpy(val, *scheduler, MPTCP_SCHED_NAME_MAX);
134133

135134
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
136135
if (write && ret == 0)
137-
ret = mptcp_set_scheduler(net, val);
136+
ret = mptcp_set_scheduler(*scheduler, val);
138137

139138
return ret;
140139
}
@@ -161,7 +160,9 @@ static int proc_blackhole_detect_timeout(const struct ctl_table *table,
161160
int write, void *buffer, size_t *lenp,
162161
loff_t *ppos)
163162
{
164-
struct mptcp_pernet *pernet = mptcp_get_pernet(current->nsproxy->net_ns);
163+
struct mptcp_pernet *pernet = container_of(table->data,
164+
struct mptcp_pernet,
165+
blackhole_timeout);
165166
int ret;
166167

167168
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
@@ -228,7 +229,7 @@ static struct ctl_table mptcp_sysctl_table[] = {
228229
{
229230
.procname = "available_schedulers",
230231
.maxlen = MPTCP_SCHED_BUF_MAX,
231-
.mode = 0644,
232+
.mode = 0444,
232233
.proc_handler = proc_available_schedulers,
233234
},
234235
{

net/rds/tcp.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ static atomic_t rds_tcp_unloading = ATOMIC_INIT(0);
6161

6262
static struct kmem_cache *rds_tcp_conn_slab;
6363

64-
static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
65-
void *buffer, size_t *lenp, loff_t *fpos);
64+
static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
65+
void *buffer, size_t *lenp, loff_t *fpos);
66+
static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
67+
void *buffer, size_t *lenp, loff_t *fpos);
6668

6769
static int rds_tcp_min_sndbuf = SOCK_MIN_SNDBUF;
6870
static int rds_tcp_min_rcvbuf = SOCK_MIN_RCVBUF;
@@ -74,7 +76,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
7476
/* data is per-net pointer */
7577
.maxlen = sizeof(int),
7678
.mode = 0644,
77-
.proc_handler = rds_tcp_skbuf_handler,
79+
.proc_handler = rds_tcp_sndbuf_handler,
7880
.extra1 = &rds_tcp_min_sndbuf,
7981
},
8082
#define RDS_TCP_RCVBUF 1
@@ -83,7 +85,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
8385
/* data is per-net pointer */
8486
.maxlen = sizeof(int),
8587
.mode = 0644,
86-
.proc_handler = rds_tcp_skbuf_handler,
88+
.proc_handler = rds_tcp_rcvbuf_handler,
8789
.extra1 = &rds_tcp_min_rcvbuf,
8890
},
8991
};
@@ -682,10 +684,10 @@ static void rds_tcp_sysctl_reset(struct net *net)
682684
spin_unlock_irq(&rds_tcp_conn_lock);
683685
}
684686

685-
static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
687+
static int rds_tcp_skbuf_handler(struct rds_tcp_net *rtn,
688+
const struct ctl_table *ctl, int write,
686689
void *buffer, size_t *lenp, loff_t *fpos)
687690
{
688-
struct net *net = current->nsproxy->net_ns;
689691
int err;
690692

691693
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,
694696
*(int *)(ctl->extra1));
695697
return err;
696698
}
697-
if (write)
699+
700+
if (write && rtn->rds_tcp_listen_sock && rtn->rds_tcp_listen_sock->sk) {
701+
struct net *net = sock_net(rtn->rds_tcp_listen_sock->sk);
702+
698703
rds_tcp_sysctl_reset(net);
704+
}
705+
699706
return 0;
700707
}
701708

709+
static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
710+
void *buffer, size_t *lenp, loff_t *fpos)
711+
{
712+
struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
713+
sndbuf_size);
714+
715+
return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
716+
}
717+
718+
static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
719+
void *buffer, size_t *lenp, loff_t *fpos)
720+
{
721+
struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
722+
rcvbuf_size);
723+
724+
return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
725+
}
726+
702727
static void rds_tcp_exit(void)
703728
{
704729
rds_tcp_set_unloading();

net/sctp/sysctl.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,8 @@ static struct ctl_table sctp_net_table[] = {
387387
static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
388388
void *buffer, size_t *lenp, loff_t *ppos)
389389
{
390-
struct net *net = current->nsproxy->net_ns;
390+
struct net *net = container_of(ctl->data, struct net,
391+
sctp.sctp_hmac_alg);
391392
struct ctl_table tbl;
392393
bool changed = false;
393394
char *none = "none";
@@ -432,7 +433,7 @@ static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
432433
static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
433434
void *buffer, size_t *lenp, loff_t *ppos)
434435
{
435-
struct net *net = current->nsproxy->net_ns;
436+
struct net *net = container_of(ctl->data, struct net, sctp.rto_min);
436437
unsigned int min = *(unsigned int *) ctl->extra1;
437438
unsigned int max = *(unsigned int *) ctl->extra2;
438439
struct ctl_table tbl;
@@ -460,7 +461,7 @@ static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
460461
static int proc_sctp_do_rto_max(const struct ctl_table *ctl, int write,
461462
void *buffer, size_t *lenp, loff_t *ppos)
462463
{
463-
struct net *net = current->nsproxy->net_ns;
464+
struct net *net = container_of(ctl->data, struct net, sctp.rto_max);
464465
unsigned int min = *(unsigned int *) ctl->extra1;
465466
unsigned int max = *(unsigned int *) ctl->extra2;
466467
struct ctl_table tbl;
@@ -498,7 +499,7 @@ static int proc_sctp_do_alpha_beta(const struct ctl_table *ctl, int write,
498499
static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
499500
void *buffer, size_t *lenp, loff_t *ppos)
500501
{
501-
struct net *net = current->nsproxy->net_ns;
502+
struct net *net = container_of(ctl->data, struct net, sctp.auth_enable);
502503
struct ctl_table tbl;
503504
int new_value, ret;
504505

@@ -527,7 +528,7 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
527528
static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
528529
void *buffer, size_t *lenp, loff_t *ppos)
529530
{
530-
struct net *net = current->nsproxy->net_ns;
531+
struct net *net = container_of(ctl->data, struct net, sctp.udp_port);
531532
unsigned int min = *(unsigned int *)ctl->extra1;
532533
unsigned int max = *(unsigned int *)ctl->extra2;
533534
struct ctl_table tbl;
@@ -568,7 +569,8 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
568569
static int proc_sctp_do_probe_interval(const struct ctl_table *ctl, int write,
569570
void *buffer, size_t *lenp, loff_t *ppos)
570571
{
571-
struct net *net = current->nsproxy->net_ns;
572+
struct net *net = container_of(ctl->data, struct net,
573+
sctp.probe_interval);
572574
struct ctl_table tbl;
573575
int ret, new_value;
574576

0 commit comments

Comments
 (0)