|
12 | 12 | #include <linux/stat.h>
|
13 | 13 | #include <linux/capability.h>
|
14 | 14 | #include <linux/slab.h>
|
| 15 | +#include <linux/cred.h> |
15 | 16 |
|
16 | 17 | static int msg_max_limit_min = MIN_MSGMAX;
|
17 | 18 | static int msg_max_limit_max = HARD_MSGMAX;
|
@@ -76,8 +77,43 @@ static int set_is_seen(struct ctl_table_set *set)
|
76 | 77 | return ¤t->nsproxy->ipc_ns->mq_set == set;
|
77 | 78 | }
|
78 | 79 |
|
| 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 | + if (in_egroup_p(ns_root_gid)) |
| 106 | + mode >>= 3; |
| 107 | + |
| 108 | + mode &= 7; |
| 109 | + |
| 110 | + return (mode << 6) | (mode << 3) | mode; |
| 111 | +} |
| 112 | + |
79 | 113 | static struct ctl_table_root set_root = {
|
80 | 114 | .lookup = set_lookup,
|
| 115 | + .permissions = mq_permissions, |
| 116 | + .set_ownership = mq_set_ownership, |
81 | 117 | };
|
82 | 118 |
|
83 | 119 | bool setup_mq_sysctls(struct ipc_namespace *ns)
|
|
0 commit comments