|
14 | 14 | #include <linux/ipc_namespace.h>
|
15 | 15 | #include <linux/msg.h>
|
16 | 16 | #include <linux/slab.h>
|
| 17 | +#include <linux/cred.h> |
17 | 18 | #include "util.h"
|
18 | 19 |
|
19 | 20 | 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)
|
190 | 191 | return ¤t->nsproxy->ipc_ns->ipc_set == set;
|
191 | 192 | }
|
192 | 193 |
|
| 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 | + |
193 | 208 | static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
|
194 | 209 | {
|
195 | 210 | int mode = table->mode;
|
196 | 211 |
|
197 | 212 | #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); |
199 | 215 |
|
200 | 216 | if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
|
201 | 217 | (table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
|
202 | 218 | (table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
|
203 | 219 | checkpoint_restore_ns_capable(ns->user_ns))
|
204 | 220 | mode = 0666;
|
| 221 | + else |
205 | 222 | #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; |
207 | 239 | }
|
208 | 240 |
|
209 | 241 | static struct ctl_table_root set_root = {
|
210 | 242 | .lookup = set_lookup,
|
211 | 243 | .permissions = ipc_permissions,
|
| 244 | + .set_ownership = ipc_set_ownership, |
212 | 245 | };
|
213 | 246 |
|
214 | 247 | bool setup_ipc_sysctls(struct ipc_namespace *ns)
|
|
0 commit comments