Skip to content

Commit e864a31

Browse files
committed
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git
2 parents 15867a6 + 05bd6e0 commit e864a31

File tree

4 files changed

+89
-14
lines changed

4 files changed

+89
-14
lines changed

Diff for: Documentation/admin-guide/sysctl/kernel.rst

+11-3
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,9 @@ default (``MSGMNB``).
568568
``msgmni`` is the maximum number of IPC queues. 32000 by default
569569
(``MSGMNI``).
570570

571+
All of these parameters are set per ipc namespace. The maximum number of bytes
572+
in POSIX message queues is limited by ``RLIMIT_MSGQUEUE``. This limit is
573+
respected hierarchically in the each user namespace.
571574

572575
msg_next_id, sem_next_id, and shm_next_id (System V IPC)
573576
========================================================
@@ -1247,15 +1250,20 @@ are doing anyway :)
12471250
shmall
12481251
======
12491252

1250-
This parameter sets the total amount of shared memory pages that
1251-
can be used system wide. Hence, ``shmall`` should always be at least
1252-
``ceil(shmmax/PAGE_SIZE)``.
1253+
This parameter sets the total amount of shared memory pages that can be used
1254+
inside ipc namespace. The shared memory pages counting occurs for each ipc
1255+
namespace separately and is not inherited. Hence, ``shmall`` should always be at
1256+
least ``ceil(shmmax/PAGE_SIZE)``.
12531257

12541258
If you are not sure what the default ``PAGE_SIZE`` is on your Linux
12551259
system, you can run the following command::
12561260

12571261
# getconf PAGE_SIZE
12581262

1263+
To reduce or disable the ability to allocate shared memory, you must create a
1264+
new ipc namespace, set this parameter to the required value and prohibit the
1265+
creation of a new ipc namespace in the current user namespace or cgroups can
1266+
be used.
12591267

12601268
shmmax
12611269
======

Diff for: ipc/ipc_sysctl.c

+35-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/ipc_namespace.h>
1515
#include <linux/msg.h>
1616
#include <linux/slab.h>
17+
#include <linux/cred.h>
1718
#include "util.h"
1819

1920
static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
@@ -190,25 +191,57 @@ static int set_is_seen(struct ctl_table_set *set)
190191
return &current->nsproxy->ipc_ns->ipc_set == set;
191192
}
192193

194+
static void ipc_set_ownership(struct ctl_table_header *head,
195+
struct ctl_table *table,
196+
kuid_t *uid, kgid_t *gid)
197+
{
198+
struct ipc_namespace *ns =
199+
container_of(head->set, struct ipc_namespace, ipc_set);
200+
201+
kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
202+
kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
203+
204+
*uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
205+
*gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
206+
}
207+
193208
static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
194209
{
195210
int mode = table->mode;
196211

197212
#ifdef CONFIG_CHECKPOINT_RESTORE
198-
struct ipc_namespace *ns = current->nsproxy->ipc_ns;
213+
struct ipc_namespace *ns =
214+
container_of(head->set, struct ipc_namespace, ipc_set);
199215

200216
if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
201217
(table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
202218
(table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
203219
checkpoint_restore_ns_capable(ns->user_ns))
204220
mode = 0666;
221+
else
205222
#endif
206-
return mode;
223+
{
224+
kuid_t ns_root_uid;
225+
kgid_t ns_root_gid;
226+
227+
ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
228+
229+
if (uid_eq(current_euid(), ns_root_uid))
230+
mode >>= 6;
231+
232+
else if (in_egroup_p(ns_root_gid))
233+
mode >>= 3;
234+
}
235+
236+
mode &= 7;
237+
238+
return (mode << 6) | (mode << 3) | mode;
207239
}
208240

209241
static struct ctl_table_root set_root = {
210242
.lookup = set_lookup,
211243
.permissions = ipc_permissions,
244+
.set_ownership = ipc_set_ownership,
212245
};
213246

214247
bool setup_ipc_sysctls(struct ipc_namespace *ns)

Diff for: ipc/mq_sysctl.c

+36
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/stat.h>
1313
#include <linux/capability.h>
1414
#include <linux/slab.h>
15+
#include <linux/cred.h>
1516

1617
static int msg_max_limit_min = MIN_MSGMAX;
1718
static int msg_max_limit_max = HARD_MSGMAX;
@@ -76,8 +77,43 @@ static int set_is_seen(struct ctl_table_set *set)
7677
return &current->nsproxy->ipc_ns->mq_set == set;
7778
}
7879

80+
static void mq_set_ownership(struct ctl_table_header *head,
81+
struct ctl_table *table,
82+
kuid_t *uid, kgid_t *gid)
83+
{
84+
struct ipc_namespace *ns =
85+
container_of(head->set, struct ipc_namespace, mq_set);
86+
87+
kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
88+
kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
89+
90+
*uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
91+
*gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
92+
}
93+
94+
static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table)
95+
{
96+
int mode = table->mode;
97+
kuid_t ns_root_uid;
98+
kgid_t ns_root_gid;
99+
100+
mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
101+
102+
if (uid_eq(current_euid(), ns_root_uid))
103+
mode >>= 6;
104+
105+
else if (in_egroup_p(ns_root_gid))
106+
mode >>= 3;
107+
108+
mode &= 7;
109+
110+
return (mode << 6) | (mode << 3) | mode;
111+
}
112+
79113
static struct ctl_table_root set_root = {
80114
.lookup = set_lookup,
115+
.permissions = mq_permissions,
116+
.set_ownership = mq_set_ownership,
81117
};
82118

83119
bool setup_mq_sysctls(struct ipc_namespace *ns)

Diff for: kernel/ucount.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,16 @@ void put_ucounts(struct ucounts *ucounts)
213213
}
214214
}
215215

216-
static inline bool atomic_long_inc_below(atomic_long_t *v, int u)
216+
static inline bool atomic_long_inc_below(atomic_long_t *v, long u)
217217
{
218-
long c, old;
219-
c = atomic_long_read(v);
220-
for (;;) {
218+
long c = atomic_long_read(v);
219+
220+
do {
221221
if (unlikely(c >= u))
222222
return false;
223-
old = atomic_long_cmpxchg(v, c, c+1);
224-
if (likely(old == c))
225-
return true;
226-
c = old;
227-
}
223+
} while (!atomic_long_try_cmpxchg(v, &c, c+1));
224+
225+
return true;
228226
}
229227

230228
struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid,

0 commit comments

Comments
 (0)