Skip to content

Commit 493ffd6

Browse files
committed
Merge tag 'ucount-rlimits-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull ucounts update from Eric Biederman: "Split rlimit and ucount values and max values After the ucount rlimit code was merged a bunch of small but siginificant bugs were found and fixed. At the time it was realized that part of the problem was that while the ucount rlimits were very similar to the oridinary ucounts (in being nested counts with limits) the semantics were slightly different and the code would be less error prone if there was less sharing. This is the long awaited cleanup that should hopefully keep things more comprehensible and less error prone for whoever needs to touch that code next" * tag 'ucount-rlimits-cleanups-for-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: ucounts: Split rlimit and ucount values and max values
2 parents e572410 + de39923 commit 493ffd6

File tree

7 files changed

+51
-46
lines changed

7 files changed

+51
-46
lines changed

fs/exec.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1879,7 +1879,7 @@ static int do_execveat_common(int fd, struct filename *filename,
18791879
* whether NPROC limit is still exceeded.
18801880
*/
18811881
if ((current->flags & PF_NPROC_EXCEEDED) &&
1882-
is_ucounts_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
1882+
is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
18831883
retval = -EAGAIN;
18841884
goto out_ret;
18851885
}

fs/proc/array.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
279279
collect_sigign_sigcatch(p, &ignored, &caught);
280280
num_threads = get_nr_threads(p);
281281
rcu_read_lock(); /* FIXME: is this correct? */
282-
qsize = get_ucounts_value(task_ucounts(p), UCOUNT_RLIMIT_SIGPENDING);
282+
qsize = get_rlimit_value(task_ucounts(p), UCOUNT_RLIMIT_SIGPENDING);
283283
rcu_read_unlock();
284284
qlim = task_rlimit(p, RLIMIT_SIGPENDING);
285285
unlock_task_sighand(p, &flags);

include/linux/user_namespace.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@ enum ucount_type {
5454
UCOUNT_FANOTIFY_GROUPS,
5555
UCOUNT_FANOTIFY_MARKS,
5656
#endif
57+
UCOUNT_COUNTS,
58+
};
59+
60+
enum rlimit_type {
5761
UCOUNT_RLIMIT_NPROC,
5862
UCOUNT_RLIMIT_MSGQUEUE,
5963
UCOUNT_RLIMIT_SIGPENDING,
6064
UCOUNT_RLIMIT_MEMLOCK,
61-
UCOUNT_COUNTS,
65+
UCOUNT_RLIMIT_COUNTS,
6266
};
6367

64-
#define MAX_PER_NAMESPACE_UCOUNTS UCOUNT_RLIMIT_NPROC
65-
6668
struct user_namespace {
6769
struct uid_gid_map uid_map;
6870
struct uid_gid_map gid_map;
@@ -99,6 +101,7 @@ struct user_namespace {
99101
#endif
100102
struct ucounts *ucounts;
101103
long ucount_max[UCOUNT_COUNTS];
104+
long rlimit_max[UCOUNT_RLIMIT_COUNTS];
102105
} __randomize_layout;
103106

104107
struct ucounts {
@@ -107,6 +110,7 @@ struct ucounts {
107110
kuid_t uid;
108111
atomic_t count;
109112
atomic_long_t ucount[UCOUNT_COUNTS];
113+
atomic_long_t rlimit[UCOUNT_RLIMIT_COUNTS];
110114
};
111115

112116
extern struct user_namespace init_user_ns;
@@ -120,21 +124,26 @@ struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid);
120124
struct ucounts * __must_check get_ucounts(struct ucounts *ucounts);
121125
void put_ucounts(struct ucounts *ucounts);
122126

123-
static inline long get_ucounts_value(struct ucounts *ucounts, enum ucount_type type)
127+
static inline long get_rlimit_value(struct ucounts *ucounts, enum rlimit_type type)
124128
{
125-
return atomic_long_read(&ucounts->ucount[type]);
129+
return atomic_long_read(&ucounts->rlimit[type]);
126130
}
127131

128-
long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v);
129-
bool dec_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v);
130-
long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type);
131-
void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum ucount_type type);
132-
bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long max);
132+
long inc_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
133+
bool dec_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v);
134+
long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum rlimit_type type);
135+
void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum rlimit_type type);
136+
bool is_rlimit_overlimit(struct ucounts *ucounts, enum rlimit_type type, unsigned long max);
137+
138+
static inline long get_userns_rlimit_max(struct user_namespace *ns, enum rlimit_type type)
139+
{
140+
return READ_ONCE(ns->rlimit_max[type]);
141+
}
133142

134-
static inline void set_rlimit_ucount_max(struct user_namespace *ns,
135-
enum ucount_type type, unsigned long max)
143+
static inline void set_userns_rlimit_max(struct user_namespace *ns,
144+
enum rlimit_type type, unsigned long max)
136145
{
137-
ns->ucount_max[type] = max <= LONG_MAX ? max : LONG_MAX;
146+
ns->rlimit_max[type] = max <= LONG_MAX ? max : LONG_MAX;
138147
}
139148

140149
#ifdef CONFIG_USER_NS

kernel/fork.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -925,13 +925,13 @@ void __init fork_init(void)
925925
init_task.signal->rlim[RLIMIT_SIGPENDING] =
926926
init_task.signal->rlim[RLIMIT_NPROC];
927927

928-
for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++)
928+
for (i = 0; i < UCOUNT_COUNTS; i++)
929929
init_user_ns.ucount_max[i] = max_threads/2;
930930

931-
set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY);
932-
set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY);
933-
set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY);
934-
set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY);
931+
set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, RLIM_INFINITY);
932+
set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, RLIM_INFINITY);
933+
set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY);
934+
set_userns_rlimit_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, RLIM_INFINITY);
935935

936936
#ifdef CONFIG_VMAP_STACK
937937
cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache",
@@ -2117,7 +2117,7 @@ static __latent_entropy struct task_struct *copy_process(
21172117
goto bad_fork_free;
21182118

21192119
retval = -EAGAIN;
2120-
if (is_ucounts_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
2120+
if (is_rlimit_overlimit(task_ucounts(p), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) {
21212121
if (p->real_cred->user != INIT_USER &&
21222122
!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
21232123
goto bad_fork_cleanup_count;

kernel/sys.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ static void flag_nproc_exceeded(struct cred *new)
496496
* for programs doing set*uid()+execve() by harmlessly deferring the
497497
* failure to the execve() stage.
498498
*/
499-
if (is_ucounts_overlimit(new->ucounts, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)) &&
499+
if (is_rlimit_overlimit(new->ucounts, UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC)) &&
500500
new->user != INIT_USER)
501501
current->flags |= PF_NPROC_EXCEEDED;
502502
else

kernel/ucount.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,6 @@ static struct ctl_table user_table[] = {
8787
UCOUNT_ENTRY("max_fanotify_groups"),
8888
UCOUNT_ENTRY("max_fanotify_marks"),
8989
#endif
90-
{ },
91-
{ },
92-
{ },
93-
{ },
9490
{ }
9591
};
9692
#endif /* CONFIG_SYSCTL */
@@ -263,29 +259,29 @@ void dec_ucount(struct ucounts *ucounts, enum ucount_type type)
263259
put_ucounts(ucounts);
264260
}
265261

266-
long inc_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
262+
long inc_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v)
267263
{
268264
struct ucounts *iter;
269265
long max = LONG_MAX;
270266
long ret = 0;
271267

272268
for (iter = ucounts; iter; iter = iter->ns->ucounts) {
273-
long new = atomic_long_add_return(v, &iter->ucount[type]);
269+
long new = atomic_long_add_return(v, &iter->rlimit[type]);
274270
if (new < 0 || new > max)
275271
ret = LONG_MAX;
276272
else if (iter == ucounts)
277273
ret = new;
278-
max = READ_ONCE(iter->ns->ucount_max[type]);
274+
max = get_userns_rlimit_max(iter->ns, type);
279275
}
280276
return ret;
281277
}
282278

283-
bool dec_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
279+
bool dec_rlimit_ucounts(struct ucounts *ucounts, enum rlimit_type type, long v)
284280
{
285281
struct ucounts *iter;
286282
long new = -1; /* Silence compiler warning */
287283
for (iter = ucounts; iter; iter = iter->ns->ucounts) {
288-
long dec = atomic_long_sub_return(v, &iter->ucount[type]);
284+
long dec = atomic_long_sub_return(v, &iter->rlimit[type]);
289285
WARN_ON_ONCE(dec < 0);
290286
if (iter == ucounts)
291287
new = dec;
@@ -294,37 +290,37 @@ bool dec_rlimit_ucounts(struct ucounts *ucounts, enum ucount_type type, long v)
294290
}
295291

296292
static void do_dec_rlimit_put_ucounts(struct ucounts *ucounts,
297-
struct ucounts *last, enum ucount_type type)
293+
struct ucounts *last, enum rlimit_type type)
298294
{
299295
struct ucounts *iter, *next;
300296
for (iter = ucounts; iter != last; iter = next) {
301-
long dec = atomic_long_sub_return(1, &iter->ucount[type]);
297+
long dec = atomic_long_sub_return(1, &iter->rlimit[type]);
302298
WARN_ON_ONCE(dec < 0);
303299
next = iter->ns->ucounts;
304300
if (dec == 0)
305301
put_ucounts(iter);
306302
}
307303
}
308304

309-
void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum ucount_type type)
305+
void dec_rlimit_put_ucounts(struct ucounts *ucounts, enum rlimit_type type)
310306
{
311307
do_dec_rlimit_put_ucounts(ucounts, NULL, type);
312308
}
313309

314-
long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
310+
long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum rlimit_type type)
315311
{
316312
/* Caller must hold a reference to ucounts */
317313
struct ucounts *iter;
318314
long max = LONG_MAX;
319315
long dec, ret = 0;
320316

321317
for (iter = ucounts; iter; iter = iter->ns->ucounts) {
322-
long new = atomic_long_add_return(1, &iter->ucount[type]);
318+
long new = atomic_long_add_return(1, &iter->rlimit[type]);
323319
if (new < 0 || new > max)
324320
goto unwind;
325321
if (iter == ucounts)
326322
ret = new;
327-
max = READ_ONCE(iter->ns->ucount_max[type]);
323+
max = get_userns_rlimit_max(iter->ns, type);
328324
/*
329325
* Grab an extra ucount reference for the caller when
330326
* the rlimit count was previously 0.
@@ -336,24 +332,24 @@ long inc_rlimit_get_ucounts(struct ucounts *ucounts, enum ucount_type type)
336332
}
337333
return ret;
338334
dec_unwind:
339-
dec = atomic_long_sub_return(1, &iter->ucount[type]);
335+
dec = atomic_long_sub_return(1, &iter->rlimit[type]);
340336
WARN_ON_ONCE(dec < 0);
341337
unwind:
342338
do_dec_rlimit_put_ucounts(ucounts, iter, type);
343339
return 0;
344340
}
345341

346-
bool is_ucounts_overlimit(struct ucounts *ucounts, enum ucount_type type, unsigned long rlimit)
342+
bool is_rlimit_overlimit(struct ucounts *ucounts, enum rlimit_type type, unsigned long rlimit)
347343
{
348344
struct ucounts *iter;
349345
long max = rlimit;
350346
if (rlimit > LONG_MAX)
351347
max = LONG_MAX;
352348
for (iter = ucounts; iter; iter = iter->ns->ucounts) {
353-
long val = get_ucounts_value(iter, type);
349+
long val = get_rlimit_value(iter, type);
354350
if (val < 0 || val > max)
355351
return true;
356-
max = READ_ONCE(iter->ns->ucount_max[type]);
352+
max = get_userns_rlimit_max(iter->ns, type);
357353
}
358354
return false;
359355
}

kernel/user_namespace.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,13 @@ int create_user_ns(struct cred *new)
136136
ns->owner = owner;
137137
ns->group = group;
138138
INIT_WORK(&ns->work, free_user_ns);
139-
for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++) {
139+
for (i = 0; i < UCOUNT_COUNTS; i++) {
140140
ns->ucount_max[i] = INT_MAX;
141141
}
142-
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_NPROC, enforced_nproc_rlimit());
143-
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE));
144-
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING));
145-
set_rlimit_ucount_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK));
142+
set_userns_rlimit_max(ns, UCOUNT_RLIMIT_NPROC, enforced_nproc_rlimit());
143+
set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MSGQUEUE, rlimit(RLIMIT_MSGQUEUE));
144+
set_userns_rlimit_max(ns, UCOUNT_RLIMIT_SIGPENDING, rlimit(RLIMIT_SIGPENDING));
145+
set_userns_rlimit_max(ns, UCOUNT_RLIMIT_MEMLOCK, rlimit(RLIMIT_MEMLOCK));
146146
ns->ucounts = ucounts;
147147

148148
/* Inherit USERNS_SETGROUPS_ALLOWED from our parent */

0 commit comments

Comments
 (0)