Skip to content

Commit 2349541

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

File tree

4 files changed

+89
-14
lines changed

4 files changed

+89
-14
lines changed

Documentation/admin-guide/sysctl/kernel.rst

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,9 @@ default (``MSGMNB``).
594594
``msgmni`` is the maximum number of IPC queues. 32000 by default
595595
(``MSGMNI``).
596596

597+
All of these parameters are set per ipc namespace. The maximum number of bytes
598+
in POSIX message queues is limited by ``RLIMIT_MSGQUEUE``. This limit is
599+
respected hierarchically in the each user namespace.
597600

598601
msg_next_id, sem_next_id, and shm_next_id (System V IPC)
599602
========================================================
@@ -1274,15 +1277,20 @@ are doing anyway :)
12741277
shmall
12751278
======
12761279

1277-
This parameter sets the total amount of shared memory pages that
1278-
can be used system wide. Hence, ``shmall`` should always be at least
1279-
``ceil(shmmax/PAGE_SIZE)``.
1280+
This parameter sets the total amount of shared memory pages that can be used
1281+
inside ipc namespace. The shared memory pages counting occurs for each ipc
1282+
namespace separately and is not inherited. Hence, ``shmall`` should always be at
1283+
least ``ceil(shmmax/PAGE_SIZE)``.
12801284

12811285
If you are not sure what the default ``PAGE_SIZE`` is on your Linux
12821286
system, you can run the following command::
12831287

12841288
# getconf PAGE_SIZE
12851289

1290+
To reduce or disable the ability to allocate shared memory, you must create a
1291+
new ipc namespace, set this parameter to the required value and prohibit the
1292+
creation of a new ipc namespace in the current user namespace or cgroups can
1293+
be used.
12861294

12871295
shmmax
12881296
======

ipc/ipc_sysctl.c

Lines changed: 35 additions & 2 deletions
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)

ipc/mq_sysctl.c

Lines changed: 36 additions & 0 deletions
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)

kernel/ucount.c

Lines changed: 7 additions & 9 deletions
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)