Skip to content

Commit 54e1011

Browse files
legionusebiederm
authored andcommitted
sysctl: Allow change system v ipc sysctls inside ipc namespace
Rootless containers are not allowed to modify kernel IPC parameters. All default limits are set to such high values that in fact there are no limits at all. All limits are not inherited and are initialized to default values when a new ipc_namespace is created. For new ipc_namespace: size_t ipc_ns.shm_ctlmax = SHMMAX; // (ULONG_MAX - (1UL << 24)) size_t ipc_ns.shm_ctlall = SHMALL; // (ULONG_MAX - (1UL << 24)) int ipc_ns.shm_ctlmni = IPCMNI; // (1 << 15) int ipc_ns.shm_rmid_forced = 0; unsigned int ipc_ns.msg_ctlmax = MSGMAX; // 8192 unsigned int ipc_ns.msg_ctlmni = MSGMNI; // 32000 unsigned int ipc_ns.msg_ctlmnb = MSGMNB; // 16384 The shm_tot (total amount of shared pages) has also ceased to be global, it is located in ipc_namespace and is not inherited from anywhere. In such conditions, it cannot be said that these limits limit anything. The real limiter for them is cgroups. If we allow rootless containers to change these parameters, then it can only be reduced. Signed-off-by: Alexey Gladkov <legion@kernel.org> Link: https://lkml.kernel.org/r/e2d84d3ec0172cfff759e6065da84ce0cc2736f8.1663756794.git.legion@kernel.org Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
1 parent f76349c commit 54e1011

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

ipc/ipc_sysctl.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,25 +190,57 @@ static int set_is_seen(struct ctl_table_set *set)
190190
return &current->nsproxy->ipc_ns->ipc_set == set;
191191
}
192192

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

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

200215
if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
201216
(table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
202217
(table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
203218
checkpoint_restore_ns_capable(ns->user_ns))
204219
mode = 0666;
220+
else
205221
#endif
206-
return mode;
222+
{
223+
kuid_t ns_root_uid;
224+
kgid_t ns_root_gid;
225+
226+
ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
227+
228+
if (uid_eq(current_euid(), ns_root_uid))
229+
mode >>= 6;
230+
231+
else if (in_egroup_p(ns_root_gid))
232+
mode >>= 3;
233+
}
234+
235+
mode &= 7;
236+
237+
return (mode << 6) | (mode << 3) | mode;
207238
}
208239

209240
static struct ctl_table_root set_root = {
210241
.lookup = set_lookup,
211242
.permissions = ipc_permissions,
243+
.set_ownership = ipc_set_ownership,
212244
};
213245

214246
bool setup_ipc_sysctls(struct ipc_namespace *ns)

0 commit comments

Comments
 (0)