aboutsummaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/.gitignore1
-rw-r--r--security/apparmor/domain.c4
-rw-r--r--security/apparmor/file.c12
-rw-r--r--security/apparmor/include/audit.h2
-rw-r--r--security/apparmor/include/file.h4
-rw-r--r--security/apparmor/lsm.c2
-rw-r--r--security/capability.c2
-rw-r--r--security/device_cgroup.c9
-rw-r--r--security/integrity/evm/evm_crypto.c4
-rw-r--r--security/integrity/ima/ima_audit.c5
-rw-r--r--security/integrity/ima/ima_policy.c14
-rw-r--r--security/keys/gc.c8
-rw-r--r--security/keys/internal.h6
-rw-r--r--security/keys/key.c25
-rw-r--r--security/keys/keyctl.c52
-rw-r--r--security/keys/keyring.c4
-rw-r--r--security/keys/permission.c14
-rw-r--r--security/keys/proc.c44
-rw-r--r--security/keys/process_keys.c15
-rw-r--r--security/keys/request_key.c6
-rw-r--r--security/security.c2
-rw-r--r--security/selinux/netlink.c5
-rw-r--r--security/selinux/selinuxfs.c6
-rw-r--r--security/selinux/ss/services.c2
-rw-r--r--security/tomoyo/audit.c23
-rw-r--r--security/tomoyo/common.c4
-rw-r--r--security/tomoyo/common.h4
-rw-r--r--security/tomoyo/condition.c20
-rw-r--r--security/tomoyo/tomoyo.c12
29 files changed, 164 insertions, 147 deletions
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 4d995aeaebc..9cdec70d72b 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -1,6 +1,5 @@
#
# Generated include files
#
-af_names.h
capability_names.h
rlim_names.h
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index b81ea10a17a..60f0c76a27d 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -721,7 +721,7 @@ audit:
if (!permtest)
error = aa_audit_file(profile, &perms, GFP_KERNEL,
OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
- target, 0, info, error);
+ target, GLOBAL_ROOT_UID, info, error);
out:
aa_put_profile(hat);
@@ -848,7 +848,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
audit:
if (!permtest)
error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
- name, hname, 0, info, error);
+ name, hname, GLOBAL_ROOT_UID, info, error);
aa_put_namespace(ns);
aa_put_profile(target);
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index cf19d4093ca..cd21ec5b90a 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -65,7 +65,7 @@ static void audit_file_mask(struct audit_buffer *ab, u32 mask)
static void file_audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
- uid_t fsuid = current_fsuid();
+ kuid_t fsuid = current_fsuid();
if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " requested_mask=");
@@ -76,8 +76,10 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
audit_file_mask(ab, sa->aad->fs.denied);
}
if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
- audit_log_format(ab, " fsuid=%d", fsuid);
- audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid);
+ audit_log_format(ab, " fsuid=%d",
+ from_kuid(&init_user_ns, fsuid));
+ audit_log_format(ab, " ouid=%d",
+ from_kuid(&init_user_ns, sa->aad->fs.ouid));
}
if (sa->aad->fs.target) {
@@ -103,7 +105,7 @@ static void file_audit_cb(struct audit_buffer *ab, void *va)
*/
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
gfp_t gfp, int op, u32 request, const char *name,
- const char *target, uid_t ouid, const char *info, int error)
+ const char *target, kuid_t ouid, const char *info, int error)
{
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
@@ -201,7 +203,7 @@ static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
*/
perms.kill = 0;
- if (current_fsuid() == cond->uid) {
+ if (uid_eq(current_fsuid(), cond->uid)) {
perms.allow = map_old_perms(dfa_user_allow(dfa, state));
perms.audit = map_old_perms(dfa_user_audit(dfa, state));
perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 4b7e18951ae..69d8cae634e 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -125,7 +125,7 @@ struct apparmor_audit_data {
const char *target;
u32 request;
u32 denied;
- uid_t ouid;
+ kuid_t ouid;
} fs;
};
};
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index f98fd4701d8..967b2deda37 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -71,7 +71,7 @@ struct path;
/* need to make conditional which ones are being set */
struct path_cond {
- uid_t uid;
+ kuid_t uid;
umode_t mode;
};
@@ -146,7 +146,7 @@ static inline u16 dfa_map_xindex(u16 mask)
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
gfp_t gfp, int op, u32 request, const char *name,
- const char *target, uid_t ouid, const char *info, int error);
+ const char *target, kuid_t ouid, const char *info, int error);
/**
* struct aa_file_rules - components used for file rule permissions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 8ea39aabe94..8c2a7f6b35e 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -352,7 +352,7 @@ static int apparmor_path_chmod(struct path *path, umode_t mode)
return common_perm_mnt_dentry(OP_CHMOD, path->mnt, path->dentry, AA_MAY_CHMOD);
}
-static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
+static int apparmor_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
struct path_cond cond = { path->dentry->d_inode->i_uid,
path->dentry->d_inode->i_mode
diff --git a/security/capability.c b/security/capability.c
index 61095df8b89..a40aac677c7 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -284,7 +284,7 @@ static int cap_path_chmod(struct path *path, umode_t mode)
return 0;
}
-static int cap_path_chown(struct path *path, uid_t uid, gid_t gid)
+static int cap_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
return 0;
}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 442204cc22d..4b877a92a7e 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -457,6 +457,15 @@ struct cgroup_subsys devices_subsys = {
.destroy = devcgroup_destroy,
.subsys_id = devices_subsys_id,
.base_cftypes = dev_cgroup_files,
+
+ /*
+ * While devices cgroup has the rudimentary hierarchy support which
+ * checks the parent's restriction, it doesn't properly propagates
+ * config changes in ancestors to their descendents. A child
+ * should only be allowed to add more restrictions to the parent's
+ * configuration. Fix it and remove the following.
+ */
+ .broken_hierarchy = true,
};
int __devcgroup_inode_permission(struct inode *inode, int mask)
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 49a464f5595..dfb26918699 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -106,8 +106,8 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
memset(&hmac_misc, 0, sizeof hmac_misc);
hmac_misc.ino = inode->i_ino;
hmac_misc.generation = inode->i_generation;
- hmac_misc.uid = inode->i_uid;
- hmac_misc.gid = inode->i_gid;
+ hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid);
+ hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
hmac_misc.mode = inode->i_mode;
crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
crypto_shash_final(desc, digest);
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c
index 7a57f6769e9..c586faae8fd 100644
--- a/security/integrity/ima/ima_audit.c
+++ b/security/integrity/ima/ima_audit.c
@@ -39,8 +39,9 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno);
audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u",
- current->pid, current_cred()->uid,
- audit_get_loginuid(current),
+ current->pid,
+ from_kuid(&init_user_ns, current_cred()->uid),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_task_context(ab);
audit_log_format(ab, " op=");
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 1a9583008aa..c84df05180c 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -39,7 +39,7 @@ struct ima_measure_rule_entry {
enum ima_hooks func;
int mask;
unsigned long fsmagic;
- uid_t uid;
+ kuid_t uid;
struct {
void *rule; /* LSM file metadata specific */
int type; /* audit type */
@@ -71,7 +71,7 @@ static struct ima_measure_rule_entry default_rules[] = {
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
- {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0,
+ {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
.flags = IMA_FUNC | IMA_MASK | IMA_UID},
};
@@ -112,7 +112,7 @@ static bool ima_match_rules(struct ima_measure_rule_entry *rule,
if ((rule->flags & IMA_FSMAGIC)
&& rule->fsmagic != inode->i_sb->s_magic)
return false;
- if ((rule->flags & IMA_UID) && rule->uid != cred->uid)
+ if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
@@ -277,7 +277,7 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_INTEGRITY_RULE);
- entry->uid = -1;
+ entry->uid = INVALID_UID;
entry->action = UNKNOWN;
while ((p = strsep(&rule, " \t")) != NULL) {
substring_t args[MAX_OPT_ARGS];
@@ -361,15 +361,15 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry)
case Opt_uid:
ima_log_string(ab, "uid", args[0].from);
- if (entry->uid != -1) {
+ if (uid_valid(entry->uid)) {
result = -EINVAL;
break;
}
result = strict_strtoul(args[0].from, 10, &lnum);
if (!result) {
- entry->uid = (uid_t) lnum;
- if (entry->uid != lnum)
+ entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
+ if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
result = -EINVAL;
else
entry->flags |= IMA_UID;
diff --git a/security/keys/gc.c b/security/keys/gc.c
index 61ab7c82ebb..d67c97bb102 100644
--- a/security/keys/gc.c
+++ b/security/keys/gc.c
@@ -62,7 +62,7 @@ void key_schedule_gc(time_t gc_at)
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) {
kdebug("IMMEDIATE");
- queue_work(system_nrt_wq, &key_gc_work);
+ schedule_work(&key_gc_work);
} else if (gc_at < key_gc_next_run) {
kdebug("DEFERRED");
key_gc_next_run = gc_at;
@@ -77,7 +77,7 @@ void key_schedule_gc(time_t gc_at)
void key_schedule_gc_links(void)
{
set_bit(KEY_GC_KEY_EXPIRED, &key_gc_flags);
- queue_work(system_nrt_wq, &key_gc_work);
+ schedule_work(&key_gc_work);
}
/*
@@ -120,7 +120,7 @@ void key_gc_keytype(struct key_type *ktype)
set_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags);
kdebug("schedule");
- queue_work(system_nrt_wq, &key_gc_work);
+ schedule_work(&key_gc_work);
kdebug("sleep");
wait_on_bit(&key_gc_flags, KEY_GC_REAPING_KEYTYPE, key_gc_wait_bit,
@@ -369,7 +369,7 @@ maybe_resched:
}
if (gc_state & KEY_GC_REAP_AGAIN)
- queue_work(system_nrt_wq, &key_gc_work);
+ schedule_work(&key_gc_work);
kleave(" [end %x]", gc_state);
return;
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 22ff05269e3..8bbefc3b55d 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -52,8 +52,7 @@ struct key_user {
atomic_t usage; /* for accessing qnkeys & qnbytes */
atomic_t nkeys; /* number of keys */
atomic_t nikeys; /* number of instantiated keys */
- uid_t uid;
- struct user_namespace *user_ns;
+ kuid_t uid;
int qnkeys; /* number of keys allocated to this user */
int qnbytes; /* number of bytes allocated to this user */
};
@@ -62,8 +61,7 @@ extern struct rb_root key_user_tree;
extern spinlock_t key_user_lock;
extern struct key_user root_key_user;
-extern struct key_user *key_user_lookup(uid_t uid,
- struct user_namespace *user_ns);
+extern struct key_user *key_user_lookup(kuid_t uid);
extern void key_user_put(struct key_user *user);
/*
diff --git a/security/keys/key.c b/security/keys/key.c
index 50d96d4e06f..a30e9273490 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -18,7 +18,6 @@
#include <linux/workqueue.h>
#include <linux/random.h>
#include <linux/err.h>
-#include <linux/user_namespace.h>
#include "internal.h"
struct kmem_cache *key_jar;
@@ -52,7 +51,7 @@ void __key_check(const struct key *key)
* Get the key quota record for a user, allocating a new record if one doesn't
* already exist.
*/
-struct key_user *key_user_lookup(uid_t uid, struct user_namespace *user_ns)
+struct key_user *key_user_lookup(kuid_t uid)
{
struct key_user *candidate = NULL, *user;
struct rb_node *parent = NULL;
@@ -67,13 +66,9 @@ try_again:
parent = *p;
user = rb_entry(parent, struct key_user, node);
- if (uid < user->uid)
+ if (uid_lt(uid, user->uid))
p = &(*p)->rb_left;
- else if (uid > user->uid)
- p = &(*p)->rb_right;
- else if (user_ns < user->user_ns)
- p = &(*p)->rb_left;
- else if (user_ns > user->user_ns)
+ else if (uid_gt(uid, user->uid))
p = &(*p)->rb_right;
else
goto found;
@@ -102,7 +97,6 @@ try_again:
atomic_set(&candidate->nkeys, 0);
atomic_set(&candidate->nikeys, 0);
candidate->uid = uid;
- candidate->user_ns = get_user_ns(user_ns);
candidate->qnkeys = 0;
candidate->qnbytes = 0;
spin_lock_init(&candidate->lock);
@@ -131,7 +125,6 @@ void key_user_put(struct key_user *user)
if (atomic_dec_and_lock(&user->usage, &key_user_lock)) {
rb_erase(&user->node, &key_user_tree);
spin_unlock(&key_user_lock);
- put_user_ns(user->user_ns);
kfree(user);
}
@@ -229,7 +222,7 @@ serial_exists:
* key_alloc() calls don't race with module unloading.
*/
struct key *key_alloc(struct key_type *type, const char *desc,
- uid_t uid, gid_t gid, const struct cred *cred,
+ kuid_t uid, kgid_t gid, const struct cred *cred,
key_perm_t perm, unsigned long flags)
{
struct key_user *user = NULL;
@@ -253,16 +246,16 @@ struct key *key_alloc(struct key_type *type, const char *desc,
quotalen = desclen + type->def_datalen;
/* get hold of the key tracking for this user */
- user = key_user_lookup(uid, cred->user_ns);
+ user = key_user_lookup(uid);
if (!user)
goto no_memory_1;
/* check that the user's quota permits allocation of another key and
* its description */
if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
- unsigned maxkeys = (uid == 0) ?
+ unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxkeys : key_quota_maxkeys;
- unsigned maxbytes = (uid == 0) ?
+ unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxbytes : key_quota_maxbytes;
spin_lock(&user->lock);
@@ -380,7 +373,7 @@ int key_payload_reserve(struct key *key, size_t datalen)
/* contemplate the quota adjustment */
if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
- unsigned maxbytes = (key->user->uid == 0) ?
+ unsigned maxbytes = uid_eq(key->user->uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxbytes : key_quota_maxbytes;
spin_lock(&key->user->lock);
@@ -598,7 +591,7 @@ void key_put(struct key *key)
key_check(key);
if (atomic_dec_and_test(&key->usage))
- queue_work(system_nrt_wq, &key_gc_work);
+ schedule_work(&key_gc_work);
}
}
EXPORT_SYMBOL(key_put);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 3364fbf4680..305ecb76519 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -569,8 +569,8 @@ okay:
ret = snprintf(tmpbuf, PAGE_SIZE - 1,
"%s;%d;%d;%08x;%s",
key->type->name,
- key->uid,
- key->gid,
+ from_kuid_munged(current_user_ns(), key->uid),
+ from_kgid_munged(current_user_ns(), key->gid),
key->perm,
key->description ?: "");
@@ -766,15 +766,25 @@ error:
*
* If successful, 0 will be returned.
*/
-long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
+long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
{
struct key_user *newowner, *zapowner = NULL;
struct key *key;
key_ref_t key_ref;
long ret;
+ kuid_t uid;
+ kgid_t gid;
+
+ uid = make_kuid(current_user_ns(), user);
+ gid = make_kgid(current_user_ns(), group);
+ ret = -EINVAL;
+ if ((user != (uid_t) -1) && !uid_valid(uid))
+ goto error;
+ if ((group != (gid_t) -1) && !gid_valid(gid))
+ goto error;
ret = 0;
- if (uid == (uid_t) -1 && gid == (gid_t) -1)
+ if (user == (uid_t) -1 && group == (gid_t) -1)
goto error;
key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
@@ -792,27 +802,27 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
if (!capable(CAP_SYS_ADMIN)) {
/* only the sysadmin can chown a key to some other UID */
- if (uid != (uid_t) -1 && key->uid != uid)
+ if (user != (uid_t) -1 && !uid_eq(key->uid, uid))
goto error_put;
/* only the sysadmin can set the key's GID to a group other
* than one of those that the current process subscribes to */
- if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
+ if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid))
goto error_put;
}
/* change the UID */
- if (uid != (uid_t) -1 && uid != key->uid) {
+ if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) {
ret = -ENOMEM;
- newowner = key_user_lookup(uid, current_user_ns());
+ newowner = key_user_lookup(uid);
if (!newowner)
goto error_put;
/* transfer the quota burden to the new user */
if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
- unsigned maxkeys = (uid == 0) ?
+ unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxkeys : key_quota_maxkeys;
- unsigned maxbytes = (uid == 0) ?
+ unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxbytes : key_quota_maxbytes;
spin_lock(&newowner->lock);
@@ -846,7 +856,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
}
/* change the GID */
- if (gid != (gid_t) -1)
+ if (group != (gid_t) -1)
key->gid = gid;
ret = 0;
@@ -897,7 +907,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
down_write(&key->sem);
/* if we're not the sysadmin, we can only change a key that we own */
- if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) {
+ if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) {
key->perm = perm;
ret = 0;
}
@@ -1486,7 +1496,6 @@ long keyctl_session_to_parent(void)
oldwork = NULL;
parent = me->real_parent;
- task_lock(parent);
/* the parent mustn't be init and mustn't be a kernel thread */
if (parent->pid <= 1 || !parent->mm)
goto unlock;
@@ -1507,18 +1516,18 @@ long keyctl_session_to_parent(void)
/* the parent must have the same effective ownership and mustn't be
* SUID/SGID */
- if (pcred->uid != mycred->euid ||
- pcred->euid != mycred->euid ||
- pcred->suid != mycred->euid ||
- pcred->gid != mycred->egid ||
- pcred->egid != mycred->egid ||
- pcred->sgid != mycred->egid)
+ if (!uid_eq(pcred->uid, mycred->euid) ||
+ !uid_eq(pcred->euid, mycred->euid) ||
+ !uid_eq(pcred->suid, mycred->euid) ||
+ !gid_eq(pcred->gid, mycred->egid) ||
+ !gid_eq(pcred->egid, mycred->egid) ||
+ !gid_eq(pcred->sgid, mycred->egid))
goto unlock;
/* the keyrings must have the same UID */
if ((pcred->tgcred->session_keyring &&
- pcred->tgcred->session_keyring->uid != mycred->euid) ||
- mycred->tgcred->session_keyring->uid != mycred->euid)
+ !uid_eq(pcred->tgcred->session_keyring->uid, mycred->euid)) ||
+ !uid_eq(mycred->tgcred->session_keyring->uid, mycred->euid))
goto unlock;
/* cancel an already pending keyring replacement */
@@ -1530,7 +1539,6 @@ long keyctl_session_to_parent(void)
if (!ret)
newwork = NULL;
unlock:
- task_unlock(parent);
write_unlock_irq(&tasklist_lock);
rcu_read_unlock();
if (oldwork)
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 81e7852d281..a5f5c4b6edc 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -256,7 +256,7 @@ error:
/*
* Allocate a keyring and link into the destination keyring.
*/
-struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
+struct key *keyring_alloc(const char *description, kuid_t uid, kgid_t gid,
const struct cred *cred, unsigned long flags,
struct key *dest)
{
@@ -612,7 +612,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
&keyring_name_hash[bucket],
type_data.link
) {
- if (keyring->user->user_ns != current_user_ns())
+ if (!kuid_has_mapping(current_user_ns(), keyring->user->uid))
continue;
if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 0b4d019e027..efcc0c855a0 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -36,33 +36,27 @@ int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
key = key_ref_to_ptr(key_ref);
- if (key->user->user_ns != cred->user_ns)
- goto use_other_perms;
-
/* use the second 8-bits of permissions for keys the caller owns */
- if (key->uid == cred->fsuid) {
+ if (uid_eq(key->uid, cred->fsuid)) {
kperm = key->perm >> 16;
goto use_these_perms;
}
/* use the third 8-bits of permissions for keys the caller has a group
* membership in common with */
- if (key->gid != -1 && key->perm & KEY_GRP_ALL) {
- if (key->gid == cred->fsgid) {
+ if (gid_valid(key->gid) && key->perm & KEY_GRP_ALL) {
+ if (gid_eq(key->gid, cred->fsgid)) {
kperm = key->perm >> 8;
goto use_these_perms;
}
- ret = groups_search(cred->group_info,
- make_kgid(current_user_ns(), key->gid));
+ ret = groups_search(cred->group_info, key->gid);
if (ret) {
kperm = key->perm >> 8;
goto use_these_perms;
}
}
-use_other_perms:
-
/* otherwise use the least-significant 8-bits */
kperm = key->perm;
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 30d1ddfd9ce..217b6855e81 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -88,14 +88,14 @@ __initcall(key_proc_init);
*/
#ifdef CONFIG_KEYS_DEBUG_PROC_KEYS
-static struct rb_node *key_serial_next(struct rb_node *n)
+static struct rb_node *key_serial_next(struct seq_file *p, struct rb_node *n)
{
- struct user_namespace *user_ns = current_user_ns();
+ struct user_namespace *user_ns = seq_user_ns(p);
n = rb_next(n);
while (n) {
struct key *key = rb_entry(n, struct key, serial_node);
- if (key->user->user_ns == user_ns)
+ if (kuid_has_mapping(user_ns, key->user->uid))
break;
n = rb_next(n);
}
@@ -107,9 +107,9 @@ static int proc_keys_open(struct inode *inode, struct file *file)
return seq_open(file, &proc_keys_ops);
}
-static struct key *find_ge_key(key_serial_t id)
+static struct key *find_ge_key(struct seq_file *p, key_serial_t id)
{
- struct user_namespace *user_ns = current_user_ns();
+ struct user_namespace *user_ns = seq_user_ns(p);
struct rb_node *n = key_serial_tree.rb_node;
struct key *minkey = NULL;
@@ -132,7 +132,7 @@ static struct key *find_ge_key(key_serial_t id)
return NULL;
for (;;) {
- if (minkey->user->user_ns == user_ns)
+ if (kuid_has_mapping(user_ns, minkey->user->uid))
return minkey;
n = rb_next(&minkey->serial_node);
if (!n)
@@ -151,7 +151,7 @@ static void *proc_keys_start(struct seq_file *p, loff_t *_pos)
if (*_pos > INT_MAX)
return NULL;
- key = find_ge_key(pos);
+ key = find_ge_key(p, pos);
if (!key)
return NULL;
*_pos = key->serial;
@@ -168,7 +168,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos)
{
struct rb_node *n;
- n = key_serial_next(v);
+ n = key_serial_next(p, v);
if (n)
*_pos = key_node_serial(n);
return n;
@@ -254,8 +254,8 @@ static int proc_keys_show(struct seq_file *m, void *v)
atomic_read(&key->usage),
xbuf,
key->perm,
- key->uid,
- key->gid,
+ from_kuid_munged(seq_user_ns(m), key->uid),
+ from_kgid_munged(seq_user_ns(m), key->gid),
key->type->name);
#undef showflag
@@ -270,26 +270,26 @@ static int proc_keys_show(struct seq_file *m, void *v)
#endif /* CONFIG_KEYS_DEBUG_PROC_KEYS */
-static struct rb_node *__key_user_next(struct rb_node *n)
+static struct rb_node *__key_user_next(struct user_namespace *user_ns, struct rb_node *n)
{
while (n) {
struct key_user *user = rb_entry(n, struct key_user, node);
- if (user->user_ns == current_user_ns())
+ if (kuid_has_mapping(user_ns, user->uid))
break;
n = rb_next(n);
}
return n;
}
-static struct rb_node *key_user_next(struct rb_node *n)
+static struct rb_node *key_user_next(struct user_namespace *user_ns, struct rb_node *n)
{
- return __key_user_next(rb_next(n));
+ return __key_user_next(user_ns, rb_next(n));
}
-static struct rb_node *key_user_first(struct rb_root *r)
+static struct rb_node *key_user_first(struct user_namespace *user_ns, struct rb_root *r)
{
struct rb_node *n = rb_first(r);
- return __key_user_next(n);
+ return __key_user_next(user_ns, n);
}
/*
@@ -309,10 +309,10 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
spin_lock(&key_user_lock);
- _p = key_user_first(&key_user_tree);
+ _p = key_user_first(seq_user_ns(p), &key_user_tree);
while (pos > 0 && _p) {
pos--;
- _p = key_user_next(_p);
+ _p = key_user_next(seq_user_ns(p), _p);
}
return _p;
@@ -321,7 +321,7 @@ static void *proc_key_users_start(struct seq_file *p, loff_t *_pos)
static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos)
{
(*_pos)++;
- return key_user_next((struct rb_node *)v);
+ return key_user_next(seq_user_ns(p), (struct rb_node *)v);
}
static void proc_key_users_stop(struct seq_file *p, void *v)
@@ -334,13 +334,13 @@ static int proc_key_users_show(struct seq_file *m, void *v)
{
struct rb_node *_p = v;
struct key_user *user = rb_entry(_p, struct key_user, node);
- unsigned maxkeys = (user->uid == 0) ?
+ unsigned maxkeys = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxkeys : key_quota_maxkeys;
- unsigned maxbytes = (user->uid == 0) ?
+ unsigned maxbytes = uid_eq(user->uid, GLOBAL_ROOT_UID) ?
key_quota_root_maxbytes : key_quota_maxbytes;
seq_printf(m, "%5u: %5d %d/%d %d/%d %d/%d\n",
- user->uid,
+ from_kuid_munged(seq_user_ns(m), user->uid),
atomic_read(&user->usage),
atomic_read(&user->nkeys),
atomic_read(&user->nikeys),
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 54339cfd673..a58f712605d 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -34,8 +34,7 @@ struct key_user root_key_user = {
.lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock),
.nkeys = ATOMIC_INIT(2),
.nikeys = ATOMIC_INIT(2),
- .uid = 0,
- .user_ns = &init_user_ns,
+ .uid = GLOBAL_ROOT_UID,
};
/*
@@ -48,11 +47,13 @@ int install_user_keyrings(void)
struct key *uid_keyring, *session_keyring;
char buf[20];
int ret;
+ uid_t uid;
cred = current_cred();
user = cred->user;
+ uid = from_kuid(cred->user_ns, user->uid);
- kenter("%p{%u}", user, user->uid);
+ kenter("%p{%u}", user, uid);
if (user->uid_keyring) {
kleave(" = 0 [exist]");
@@ -67,11 +68,11 @@ int install_user_keyrings(void)
* - there may be one in existence already as it may have been
* pinned by a session, but the user_struct pointing to it
* may have been destroyed by setuid */
- sprintf(buf, "_uid.%u", user->uid);
+ sprintf(buf, "_uid.%u", uid);
uid_keyring = find_keyring_by_name(buf, true);
if (IS_ERR(uid_keyring)) {
- uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
+ uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID,
cred, KEY_ALLOC_IN_QUOTA,
NULL);
if (IS_ERR(uid_keyring)) {
@@ -82,12 +83,12 @@ int install_user_keyrings(void)
/* get a default session keyring (which might also exist
* already) */
- sprintf(buf, "_uid_ses.%u", user->uid);
+ sprintf(buf, "_uid_ses.%u", uid);
session_keyring = find_keyring_by_name(buf, true);
if (IS_ERR(session_keyring)) {
session_keyring =
- keyring_alloc(buf, user->uid, (gid_t) -1,
+ keyring_alloc(buf, user->uid, INVALID_GID,
cred, KEY_ALLOC_IN_QUOTA, NULL);
if (IS_ERR(session_keyring)) {
ret = PTR_ERR(session_keyring);
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 000e7501752..66e21184b55 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -139,8 +139,8 @@ static int call_sbin_request_key(struct key_construction *cons,
goto error_link;
/* record the UID and GID */
- sprintf(uid_str, "%d", cred->fsuid);
- sprintf(gid_str, "%d", cred->fsgid);
+ sprintf(uid_str, "%d", from_kuid(&init_user_ns, cred->fsuid));
+ sprintf(gid_str, "%d", from_kgid(&init_user_ns, cred->fsgid));
/* we say which key is under construction */
sprintf(key_str, "%d", key->serial);
@@ -442,7 +442,7 @@ static struct key *construct_key_and_link(struct key_type *type,
kenter("");
- user = key_user_lookup(current_fsuid(), current_user_ns());
+ user = key_user_lookup(current_fsuid());
if (!user)
return ERR_PTR(-ENOMEM);
diff --git a/security/security.c b/security/security.c
index 860aeb349cb..f9a2f2ef245 100644
--- a/security/security.c
+++ b/security/security.c
@@ -434,7 +434,7 @@ int security_path_chmod(struct path *path, umode_t mode)
return security_ops->path_chmod(path, mode);
}
-int security_path_chown(struct path *path, uid_t uid, gid_t gid)
+int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(path->dentry->d_inode)))
return 0;
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c
index 8a77725423e..14d810ead42 100644
--- a/security/selinux/netlink.c
+++ b/security/selinux/netlink.c
@@ -113,13 +113,12 @@ static int __init selnl_init(void)
{
struct netlink_kernel_cfg cfg = {
.groups = SELNLGRP_MAX,
+ .flags = NL_CFG_F_NONROOT_RECV,
};
- selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX,
- THIS_MODULE, &cfg);
+ selnl = netlink_kernel_create(&init_net, NETLINK_SELINUX, &cfg);
if (selnl == NULL)
panic("SELinux: Cannot create netlink socket.");
- netlink_set_nonroot(NETLINK_SELINUX, NL_NONROOT_RECV);
return 0;
}
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 298e695d682..55af8c5b57e 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -174,7 +174,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
"enforcing=%d old_enforcing=%d auid=%u ses=%u",
new_value, selinux_enforcing,
- audit_get_loginuid(current),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
selinux_enforcing = new_value;
if (selinux_enforcing)
@@ -305,7 +305,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf,
goto out;
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS,
"selinux=0 auid=%u ses=%u",
- audit_get_loginuid(current),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
}
@@ -551,7 +551,7 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
out1:
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
"policy loaded auid=%u ses=%u",
- audit_get_loginuid(current),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
out:
mutex_unlock(&sel_mutex);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 4321b8fc886..b4feecc3fe0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2440,7 +2440,7 @@ int security_set_bools(int len, int *values)
sym_name(&policydb, SYM_BOOLS, i),
!!values[i],
policydb.bool_val_to_struct[i]->state,
- audit_get_loginuid(current),
+ from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
}
if (values[i])
diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c
index 7ef9fa3e37e..c1b00375c9a 100644
--- a/security/tomoyo/audit.c
+++ b/security/tomoyo/audit.c
@@ -168,9 +168,14 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile,
tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid,
tomoyo_sys_getpid(), tomoyo_sys_getppid(),
- current_uid(), current_gid(), current_euid(),
- current_egid(), current_suid(), current_sgid(),
- current_fsuid(), current_fsgid());
+ from_kuid(&init_user_ns, current_uid()),
+ from_kgid(&init_user_ns, current_gid()),
+ from_kuid(&init_user_ns, current_euid()),
+ from_kgid(&init_user_ns, current_egid()),
+ from_kuid(&init_user_ns, current_suid()),
+ from_kgid(&init_user_ns, current_sgid()),
+ from_kuid(&init_user_ns, current_fsuid()),
+ from_kgid(&init_user_ns, current_fsgid()));
if (!obj)
goto no_obj_info;
if (!obj->validate_done) {
@@ -191,15 +196,19 @@ static char *tomoyo_print_header(struct tomoyo_request_info *r)
tomoyo_buffer_len - 1 - pos,
" path%u.parent={ uid=%u gid=%u "
"ino=%lu perm=0%o }", (i >> 1) + 1,
- stat->uid, stat->gid, (unsigned long)
- stat->ino, stat->mode & S_IALLUGO);
+ from_kuid(&init_user_ns, stat->uid),
+ from_kgid(&init_user_ns, stat->gid),
+ (unsigned long)stat->ino,
+ stat->mode & S_IALLUGO);
continue;
}
pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
" path%u={ uid=%u gid=%u ino=%lu major=%u"
" minor=%u perm=0%o type=%s", (i >> 1) + 1,
- stat->uid, stat->gid, (unsigned long)
- stat->ino, MAJOR(dev), MINOR(dev),
+ from_kuid(&init_user_ns, stat->uid),
+ from_kgid(&init_user_ns, stat->gid),
+ (unsigned long)stat->ino,
+ MAJOR(dev), MINOR(dev),
mode & S_IALLUGO, tomoyo_filetype(mode));
if (S_ISCHR(mode) || S_ISBLK(mode)) {
dev = stat->rdev;
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 2e0f12c6293..f89a0333b81 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -925,7 +925,9 @@ static bool tomoyo_manager(void)
if (!tomoyo_policy_loaded)
return true;
- if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
+ if (!tomoyo_manage_by_non_root &&
+ (!uid_eq(task->cred->uid, GLOBAL_ROOT_UID) ||
+ !uid_eq(task->cred->euid, GLOBAL_ROOT_UID)))
return false;
exe = tomoyo_get_exe();
if (!exe)
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 75e4dc1c02a..af010b62d54 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -561,8 +561,8 @@ struct tomoyo_address_group {
/* Subset of "struct stat". Used by conditional ACL and audit logs. */
struct tomoyo_mini_stat {
- uid_t uid;
- gid_t gid;
+ kuid_t uid;
+ kgid_t gid;
ino_t ino;
umode_t mode;
dev_t dev;
diff --git a/security/tomoyo/condition.c b/security/tomoyo/condition.c
index 986330b8c73..63681e8be62 100644
--- a/security/tomoyo/condition.c
+++ b/security/tomoyo/condition.c
@@ -813,28 +813,28 @@ bool tomoyo_condition(struct tomoyo_request_info *r,
unsigned long value = 0;
switch (index) {
case TOMOYO_TASK_UID:
- value = current_uid();
+ value = from_kuid(&init_user_ns, current_uid());
break;
case TOMOYO_TASK_EUID:
- value = current_euid();
+ value = from_kuid(&init_user_ns, current_euid());
break;
case TOMOYO_TASK_SUID:
- value = current_suid();
+ value = from_kuid(&init_user_ns, current_suid());
break;
case TOMOYO_TASK_FSUID:
- value = current_fsuid();
+ value = from_kuid(&init_user_ns, current_fsuid());
break;
case TOMOYO_TASK_GID:
- value = current_gid();
+ value = from_kgid(&init_user_ns, current_gid());
break;
case TOMOYO_TASK_EGID:
- value = current_egid();
+ value = from_kgid(&init_user_ns, current_egid());
break;
case TOMOYO_TASK_SGID:
- value = current_sgid();
+ value = from_kgid(&init_user_ns, current_sgid());
break;
case TOMOYO_TASK_FSGID:
- value = current_fsgid();
+ value = from_kgid(&init_user_ns, current_fsgid());
break;
case TOMOYO_TASK_PID:
value = tomoyo_sys_getpid();
@@ -970,13 +970,13 @@ bool tomoyo_condition(struct tomoyo_request_info *r,
case TOMOYO_PATH2_UID:
case TOMOYO_PATH1_PARENT_UID:
case TOMOYO_PATH2_PARENT_UID:
- value = stat->uid;
+ value = from_kuid(&init_user_ns, stat->uid);
break;
case TOMOYO_PATH1_GID:
case TOMOYO_PATH2_GID:
case TOMOYO_PATH1_PARENT_GID:
case TOMOYO_PATH2_PARENT_GID:
- value = stat->gid;
+ value = from_kgid(&init_user_ns, stat->gid);
break;
case TOMOYO_PATH1_INO:
case TOMOYO_PATH2_INO:
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index c2d04a50f76..d88eb3a046e 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -373,13 +373,15 @@ static int tomoyo_path_chmod(struct path *path, umode_t mode)
*
* Returns 0 on success, negative value otherwise.
*/
-static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
+static int tomoyo_path_chown(struct path *path, kuid_t uid, kgid_t gid)
{
int error = 0;
- if (uid != (uid_t) -1)
- error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid);
- if (!error && gid != (gid_t) -1)
- error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid);
+ if (uid_valid(uid))
+ error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path,
+ from_kuid(&init_user_ns, uid));
+ if (!error && gid_valid(gid))
+ error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path,
+ from_kgid(&init_user_ns, gid));
return error;
}