summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/apparmorfs.c8
-rw-r--r--security/keys/big_key.c2
-rw-r--r--security/keys/encrypted-keys/ecryptfs_format.c3
-rw-r--r--security/keys/encrypted-keys/encrypted.c4
-rw-r--r--security/keys/process_keys.c2
-rw-r--r--security/keys/trusted-keys/trusted_core.c4
-rw-r--r--security/keys/trusted-keys/trusted_tpm2.c29
-rw-r--r--security/keys/user_defined.c2
-rw-r--r--security/landlock/fs.c9
-rw-r--r--security/selinux/hooks.c251
-rw-r--r--security/selinux/include/objsec.h22
-rw-r--r--security/selinux/selinuxfs.c15
12 files changed, 181 insertions, 170 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index ee04c1ac9d6e..e4114aa1e04f 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -355,17 +355,17 @@ static void aafs_remove(struct dentry *dentry)
if (!dentry || IS_ERR(dentry))
return;
+ /* ->d_parent is stable as rename is not supported */
dir = d_inode(dentry->d_parent);
- inode_lock(dir);
- if (simple_positive(dentry)) {
+ dentry = start_removing_dentry(dentry->d_parent, dentry);
+ if (!IS_ERR(dentry) && simple_positive(dentry)) {
if (d_is_dir(dentry))
simple_rmdir(dir, dentry);
else
simple_unlink(dir, dentry);
d_delete(dentry);
- dput(dentry);
}
- inode_unlock(dir);
+ end_removing(dentry);
simple_release_fs(&aafs_mnt, &aafs_count);
}
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index c3367622c683..d46862ab90d6 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -66,7 +66,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
BUILD_BUG_ON(sizeof(*payload) != sizeof(prep->payload.data));
- if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
+ if (datalen == 0 || datalen > 1024 * 1024 || !prep->data)
return -EINVAL;
/* Set an arbitrary quota */
diff --git a/security/keys/encrypted-keys/ecryptfs_format.c b/security/keys/encrypted-keys/ecryptfs_format.c
index 8fdd76105ce3..2fc6f3a66135 100644
--- a/security/keys/encrypted-keys/ecryptfs_format.c
+++ b/security/keys/encrypted-keys/ecryptfs_format.c
@@ -54,8 +54,7 @@ int ecryptfs_fill_auth_tok(struct ecryptfs_auth_tok *auth_tok,
auth_tok->version = (((uint16_t)(major << 8) & 0xFF00)
| ((uint16_t)minor & 0x00FF));
auth_tok->token_type = ECRYPTFS_PASSWORD;
- strncpy((char *)auth_tok->token.password.signature, key_desc,
- ECRYPTFS_PASSWORD_SIG_SIZE);
+ strscpy_pad(auth_tok->token.password.signature, key_desc);
auth_tok->token.password.session_key_encryption_key_bytes =
ECRYPTFS_MAX_KEY_BYTES;
/*
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 513c09e2b01c..596e7a30bd3c 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -795,7 +795,7 @@ static int encrypted_instantiate(struct key *key,
size_t datalen = prep->datalen;
int ret;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
+ if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
datablob = kmalloc(datalen + 1, GFP_KERNEL);
@@ -856,7 +856,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
if (key_is_negative(key))
return -ENOKEY;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
+ if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
buf = kmalloc(datalen + 1, GFP_KERNEL);
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index b5d5333ab330..a63c46bb2d14 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -51,7 +51,7 @@ static struct key *get_user_register(struct user_namespace *user_ns)
if (!reg_keyring) {
reg_keyring = keyring_alloc(".user_reg",
user_ns->owner, INVALID_GID,
- &init_cred,
+ kernel_cred(),
KEY_POS_WRITE | KEY_POS_SEARCH |
KEY_USR_VIEW | KEY_USR_READ,
0,
diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c
index e2d9644efde1..b1680ee53f86 100644
--- a/security/keys/trusted-keys/trusted_core.c
+++ b/security/keys/trusted-keys/trusted_core.c
@@ -157,7 +157,7 @@ static int trusted_instantiate(struct key *key,
int key_cmd;
size_t key_len;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
+ if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);
@@ -240,7 +240,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
p = key->payload.data[0];
if (!p->migratable)
return -EPERM;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
+ if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
orig_datablob = datablob = kmalloc(datalen + 1, GFP_KERNEL);
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 024be262702f..91656e44b326 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -18,14 +18,6 @@
#include "tpm2key.asn1.h"
-static struct tpm2_hash tpm2_hash_map[] = {
- {HASH_ALGO_SHA1, TPM_ALG_SHA1},
- {HASH_ALGO_SHA256, TPM_ALG_SHA256},
- {HASH_ALGO_SHA384, TPM_ALG_SHA384},
- {HASH_ALGO_SHA512, TPM_ALG_SHA512},
- {HASH_ALGO_SM3_256, TPM_ALG_SM3_256},
-};
-
static u32 tpm2key_oid[] = { 2, 23, 133, 10, 1, 5 };
static int tpm2_key_encode(struct trusted_key_payload *payload,
@@ -244,20 +236,13 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
off_t offset = TPM_HEADER_SIZE;
struct tpm_buf buf, sized;
int blob_len = 0;
- u32 hash;
+ int hash;
u32 flags;
- int i;
int rc;
- for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
- if (options->hash == tpm2_hash_map[i].crypto_id) {
- hash = tpm2_hash_map[i].tpm_id;
- break;
- }
- }
-
- if (i == ARRAY_SIZE(tpm2_hash_map))
- return -EINVAL;
+ hash = tpm2_find_hash_alg(options->hash);
+ if (hash < 0)
+ return hash;
if (!options->keyhandle)
return -EINVAL;
@@ -387,6 +372,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
struct trusted_key_options *options,
u32 *blob_handle)
{
+ u8 *blob_ref __free(kfree) = NULL;
struct tpm_buf buf;
unsigned int private_len;
unsigned int public_len;
@@ -400,6 +386,9 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
/* old form */
blob = payload->blob;
payload->old_format = 1;
+ } else {
+ /* Bind for cleanup: */
+ blob_ref = blob;
}
/* new format carries keyhandle but old format doesn't */
@@ -464,8 +453,6 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
(__be32 *) &buf.data[TPM_HEADER_SIZE]);
out:
- if (blob != payload->blob)
- kfree(blob);
tpm_buf_destroy(&buf);
if (rc > 0)
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 749e2a4dcb13..686d56e4cc85 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -61,7 +61,7 @@ int user_preparse(struct key_preparsed_payload *prep)
struct user_key_payload *upayload;
size_t datalen = prep->datalen;
- if (datalen <= 0 || datalen > 32767 || !prep->data)
+ if (datalen == 0 || datalen > 32767 || !prep->data)
return -EINVAL;
upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 0bade2c5aa1d..cee2b6f22c83 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1296,7 +1296,7 @@ static void hook_sb_delete(struct super_block *const sb)
* second call to iput() for the same Landlock object. Also
* checks I_NEW because such inode cannot be tied to an object.
*/
- if (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) {
+ if (inode_state_read(inode) & (I_FREEING | I_WILL_FREE | I_NEW)) {
spin_unlock(&inode->i_lock);
continue;
}
@@ -1335,11 +1335,10 @@ static void hook_sb_delete(struct super_block *const sb)
* At this point, we own the ihold() reference that was
* originally set up by get_inode_object() and the
* __iget() reference that we just set in this loop
- * walk. Therefore the following call to iput() will
- * not sleep nor drop the inode because there is now at
- * least two references to it.
+ * walk. Therefore there are at least two references
+ * on the inode.
*/
- iput(inode);
+ iput_not_last(inode);
} else {
spin_unlock(&object->lock);
rcu_read_unlock();
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index cd5f6974f9e6..139df920f582 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -211,12 +211,12 @@ static int selinux_lsm_notifier_avc_callback(u32 event)
*/
static void cred_init_security(void)
{
- struct task_security_struct *tsec;
+ struct cred_security_struct *crsec;
/* NOTE: the lsm framework zeros out the buffer on allocation */
- tsec = selinux_cred(unrcu_pointer(current->real_cred));
- tsec->osid = tsec->sid = tsec->avdcache.sid = SECINITSID_KERNEL;
+ crsec = selinux_cred(unrcu_pointer(current->real_cred));
+ crsec->osid = crsec->sid = SECINITSID_KERNEL;
}
/*
@@ -224,10 +224,10 @@ static void cred_init_security(void)
*/
static inline u32 cred_sid(const struct cred *cred)
{
- const struct task_security_struct *tsec;
+ const struct cred_security_struct *crsec;
- tsec = selinux_cred(cred);
- return tsec->sid;
+ crsec = selinux_cred(cred);
+ return crsec->sid;
}
static void __ad_net_init(struct common_audit_data *ad,
@@ -438,15 +438,15 @@ static int may_context_mount_sb_relabel(u32 sid,
struct superblock_security_struct *sbsec,
const struct cred *cred)
{
- const struct task_security_struct *tsec = selinux_cred(cred);
+ const struct cred_security_struct *crsec = selinux_cred(cred);
int rc;
- rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(crsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
return rc;
- rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(crsec->sid, sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELTO, NULL);
return rc;
}
@@ -455,9 +455,9 @@ static int may_context_mount_inode_relabel(u32 sid,
struct superblock_security_struct *sbsec,
const struct cred *cred)
{
- const struct task_security_struct *tsec = selinux_cred(cred);
+ const struct cred_security_struct *crsec = selinux_cred(cred);
int rc;
- rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ rc = avc_has_perm(crsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
FILESYSTEM__RELABELFROM, NULL);
if (rc)
return rc;
@@ -1789,7 +1789,7 @@ out:
* Determine the label for an inode that might be unioned.
*/
static int
-selinux_determine_inode_label(const struct task_security_struct *tsec,
+selinux_determine_inode_label(const struct cred_security_struct *crsec,
struct inode *dir,
const struct qstr *name, u16 tclass,
u32 *_new_isid)
@@ -1801,11 +1801,11 @@ selinux_determine_inode_label(const struct task_security_struct *tsec,
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
*_new_isid = sbsec->mntpoint_sid;
} else if ((sbsec->flags & SBLABEL_MNT) &&
- tsec->create_sid) {
- *_new_isid = tsec->create_sid;
+ crsec->create_sid) {
+ *_new_isid = crsec->create_sid;
} else {
const struct inode_security_struct *dsec = inode_security(dir);
- return security_transition_sid(tsec->sid,
+ return security_transition_sid(crsec->sid,
dsec->sid, tclass,
name, _new_isid);
}
@@ -1818,7 +1818,7 @@ static int may_create(struct inode *dir,
struct dentry *dentry,
u16 tclass)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
struct inode_security_struct *dsec;
struct superblock_security_struct *sbsec;
u32 sid, newsid;
@@ -1828,7 +1828,7 @@ static int may_create(struct inode *dir,
dsec = inode_security(dir);
sbsec = selinux_superblock(dir->i_sb);
- sid = tsec->sid;
+ sid = crsec->sid;
ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry;
@@ -1839,7 +1839,7 @@ static int may_create(struct inode *dir,
if (rc)
return rc;
- rc = selinux_determine_inode_label(tsec, dir, &dentry->d_name, tclass,
+ rc = selinux_determine_inode_label(crsec, dir, &dentry->d_name, tclass,
&newsid);
if (rc)
return rc;
@@ -2252,8 +2252,8 @@ static u32 ptrace_parent_sid(void)
}
static int check_nnp_nosuid(const struct linux_binprm *bprm,
- const struct task_security_struct *old_tsec,
- const struct task_security_struct *new_tsec)
+ const struct cred_security_struct *old_crsec,
+ const struct cred_security_struct *new_crsec)
{
int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
@@ -2263,7 +2263,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
if (!nnp && !nosuid)
return 0; /* neither NNP nor nosuid */
- if (new_tsec->sid == old_tsec->sid)
+ if (new_crsec->sid == old_crsec->sid)
return 0; /* No change in credentials */
/*
@@ -2278,7 +2278,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
av |= PROCESS2__NNP_TRANSITION;
if (nosuid)
av |= PROCESS2__NOSUID_TRANSITION;
- rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ rc = avc_has_perm(old_crsec->sid, new_crsec->sid,
SECCLASS_PROCESS2, av, NULL);
if (!rc)
return 0;
@@ -2289,8 +2289,8 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
* i.e. SIDs that are guaranteed to only be allowed a subset
* of the permissions of the current SID.
*/
- rc = security_bounded_transition(old_tsec->sid,
- new_tsec->sid);
+ rc = security_bounded_transition(old_crsec->sid,
+ new_crsec->sid);
if (!rc)
return 0;
@@ -2306,8 +2306,8 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
{
- const struct task_security_struct *old_tsec;
- struct task_security_struct *new_tsec;
+ const struct cred_security_struct *old_crsec;
+ struct cred_security_struct *new_crsec;
struct inode_security_struct *isec;
struct common_audit_data ad;
struct inode *inode = file_inode(bprm->file);
@@ -2316,18 +2316,18 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
/* SELinux context only depends on initial program or script and not
* the script interpreter */
- old_tsec = selinux_cred(current_cred());
- new_tsec = selinux_cred(bprm->cred);
+ old_crsec = selinux_cred(current_cred());
+ new_crsec = selinux_cred(bprm->cred);
isec = inode_security(inode);
/* Default to the current task SID. */
- new_tsec->sid = old_tsec->sid;
- new_tsec->osid = old_tsec->sid;
+ new_crsec->sid = old_crsec->sid;
+ new_crsec->osid = old_crsec->sid;
/* Reset fs, key, and sock SIDs on execve. */
- new_tsec->create_sid = 0;
- new_tsec->keycreate_sid = 0;
- new_tsec->sockcreate_sid = 0;
+ new_crsec->create_sid = 0;
+ new_crsec->keycreate_sid = 0;
+ new_crsec->sockcreate_sid = 0;
/*
* Before policy is loaded, label any task outside kernel space
@@ -2336,26 +2336,26 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
* (if the policy chooses to set SECINITSID_INIT != SECINITSID_KERNEL).
*/
if (!selinux_initialized()) {
- new_tsec->sid = SECINITSID_INIT;
+ new_crsec->sid = SECINITSID_INIT;
/* also clear the exec_sid just in case */
- new_tsec->exec_sid = 0;
+ new_crsec->exec_sid = 0;
return 0;
}
- if (old_tsec->exec_sid) {
- new_tsec->sid = old_tsec->exec_sid;
+ if (old_crsec->exec_sid) {
+ new_crsec->sid = old_crsec->exec_sid;
/* Reset exec SID on execve. */
- new_tsec->exec_sid = 0;
+ new_crsec->exec_sid = 0;
/* Fail on NNP or nosuid if not an allowed transition. */
- rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
+ rc = check_nnp_nosuid(bprm, old_crsec, new_crsec);
if (rc)
return rc;
} else {
/* Check for a default transition on this program. */
- rc = security_transition_sid(old_tsec->sid,
+ rc = security_transition_sid(old_crsec->sid,
isec->sid, SECCLASS_PROCESS, NULL,
- &new_tsec->sid);
+ &new_crsec->sid);
if (rc)
return rc;
@@ -2363,34 +2363,34 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
* Fallback to old SID on NNP or nosuid if not an allowed
* transition.
*/
- rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
+ rc = check_nnp_nosuid(bprm, old_crsec, new_crsec);
if (rc)
- new_tsec->sid = old_tsec->sid;
+ new_crsec->sid = old_crsec->sid;
}
ad.type = LSM_AUDIT_DATA_FILE;
ad.u.file = bprm->file;
- if (new_tsec->sid == old_tsec->sid) {
- rc = avc_has_perm(old_tsec->sid, isec->sid,
+ if (new_crsec->sid == old_crsec->sid) {
+ rc = avc_has_perm(old_crsec->sid, isec->sid,
SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
if (rc)
return rc;
} else {
/* Check permissions for the transition. */
- rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ rc = avc_has_perm(old_crsec->sid, new_crsec->sid,
SECCLASS_PROCESS, PROCESS__TRANSITION, &ad);
if (rc)
return rc;
- rc = avc_has_perm(new_tsec->sid, isec->sid,
+ rc = avc_has_perm(new_crsec->sid, isec->sid,
SECCLASS_FILE, FILE__ENTRYPOINT, &ad);
if (rc)
return rc;
/* Check for shared state */
if (bprm->unsafe & LSM_UNSAFE_SHARE) {
- rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ rc = avc_has_perm(old_crsec->sid, new_crsec->sid,
SECCLASS_PROCESS, PROCESS__SHARE,
NULL);
if (rc)
@@ -2402,7 +2402,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
if (bprm->unsafe & LSM_UNSAFE_PTRACE) {
u32 ptsid = ptrace_parent_sid();
if (ptsid != 0) {
- rc = avc_has_perm(ptsid, new_tsec->sid,
+ rc = avc_has_perm(ptsid, new_crsec->sid,
SECCLASS_PROCESS,
PROCESS__PTRACE, NULL);
if (rc)
@@ -2416,7 +2416,7 @@ static int selinux_bprm_creds_for_exec(struct linux_binprm *bprm)
/* Enable secure mode for SIDs transitions unless
the noatsecure permission is granted between
the two SIDs, i.e. ahp returns 0. */
- rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ rc = avc_has_perm(old_crsec->sid, new_crsec->sid,
SECCLASS_PROCESS, PROCESS__NOATSECURE,
NULL);
bprm->secureexec |= !!rc;
@@ -2484,12 +2484,12 @@ static inline void flush_unauthorized_files(const struct cred *cred,
*/
static void selinux_bprm_committing_creds(const struct linux_binprm *bprm)
{
- struct task_security_struct *new_tsec;
+ struct cred_security_struct *new_crsec;
struct rlimit *rlim, *initrlim;
int rc, i;
- new_tsec = selinux_cred(bprm->cred);
- if (new_tsec->sid == new_tsec->osid)
+ new_crsec = selinux_cred(bprm->cred);
+ if (new_crsec->sid == new_crsec->osid)
return;
/* Close files for which the new task SID is not authorized. */
@@ -2508,7 +2508,7 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm)
* higher than the default soft limit for cases where the default is
* lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.
*/
- rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS,
+ rc = avc_has_perm(new_crsec->osid, new_crsec->sid, SECCLASS_PROCESS,
PROCESS__RLIMITINH, NULL);
if (rc) {
/* protect against do_prlimit() */
@@ -2530,12 +2530,12 @@ static void selinux_bprm_committing_creds(const struct linux_binprm *bprm)
*/
static void selinux_bprm_committed_creds(const struct linux_binprm *bprm)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
u32 osid, sid;
int rc;
- osid = tsec->osid;
- sid = tsec->sid;
+ osid = crsec->osid;
+ sid = crsec->sid;
if (sid == osid)
return;
@@ -2912,7 +2912,7 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
{
u32 newsid;
int rc;
- struct task_security_struct *tsec;
+ struct cred_security_struct *crsec;
rc = selinux_determine_inode_label(selinux_cred(old),
d_inode(dentry->d_parent), name,
@@ -2921,8 +2921,8 @@ static int selinux_dentry_create_files_as(struct dentry *dentry, int mode,
if (rc)
return rc;
- tsec = selinux_cred(new);
- tsec->create_sid = newsid;
+ crsec = selinux_cred(new);
+ crsec->create_sid = newsid;
return 0;
}
@@ -2930,7 +2930,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
struct xattr *xattrs, int *xattr_count)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
struct superblock_security_struct *sbsec;
struct xattr *xattr = lsm_get_xattr_slot(xattrs, xattr_count);
u32 newsid, clen;
@@ -2940,9 +2940,9 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
sbsec = selinux_superblock(dir->i_sb);
- newsid = tsec->create_sid;
+ newsid = crsec->create_sid;
newsclass = inode_mode_to_security_class(inode->i_mode);
- rc = selinux_determine_inode_label(tsec, dir, qstr, newsclass, &newsid);
+ rc = selinux_determine_inode_label(crsec, dir, qstr, newsclass, &newsid);
if (rc)
return rc;
@@ -3114,7 +3114,7 @@ static noinline int audit_inode_permission(struct inode *inode,
static inline void task_avdcache_reset(struct task_security_struct *tsec)
{
memset(&tsec->avdcache.dir, 0, sizeof(tsec->avdcache.dir));
- tsec->avdcache.sid = tsec->sid;
+ tsec->avdcache.sid = current_sid();
tsec->avdcache.seqno = avc_policy_seqno();
tsec->avdcache.dir_spot = TSEC_AVDC_DIR_SIZE - 1;
}
@@ -3138,7 +3138,7 @@ static inline int task_avdcache_search(struct task_security_struct *tsec,
if (isec->sclass != SECCLASS_DIR)
return -ENOENT;
- if (unlikely(tsec->sid != tsec->avdcache.sid ||
+ if (unlikely(current_sid() != tsec->avdcache.sid ||
tsec->avdcache.seqno != avc_policy_seqno())) {
task_avdcache_reset(tsec);
return -ENOENT;
@@ -3202,6 +3202,7 @@ static int selinux_inode_permission(struct inode *inode, int requested)
{
int mask;
u32 perms;
+ u32 sid = current_sid();
struct task_security_struct *tsec;
struct inode_security_struct *isec;
struct avdc_entry *avdc;
@@ -3214,8 +3215,8 @@ static int selinux_inode_permission(struct inode *inode, int requested)
if (!mask)
return 0;
- tsec = selinux_cred(current_cred());
- if (task_avdcache_permnoaudit(tsec))
+ tsec = selinux_task(current);
+ if (task_avdcache_permnoaudit(tsec, sid))
return 0;
isec = inode_security_rcu(inode, requested & MAY_NOT_BLOCK);
@@ -3235,7 +3236,7 @@ static int selinux_inode_permission(struct inode *inode, int requested)
struct av_decision avd;
/* Cache miss. */
- rc = avc_has_perm_noaudit(tsec->sid, isec->sid, isec->sclass,
+ rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass,
perms, 0, &avd);
audited = avc_audit_required(perms, &avd, rc,
(requested & MAY_ACCESS) ? FILE__AUDIT_ACCESS : 0,
@@ -3286,9 +3287,9 @@ static int selinux_inode_getattr(const struct path *path)
{
struct task_security_struct *tsec;
- tsec = selinux_cred(current_cred());
+ tsec = selinux_task(current);
- if (task_avdcache_permnoaudit(tsec))
+ if (task_avdcache_permnoaudit(tsec, current_sid()))
return 0;
return path_has_perm(current_cred(), path, FILE__GETATTR);
@@ -3660,7 +3661,7 @@ static void selinux_inode_getlsmprop(struct inode *inode, struct lsm_prop *prop)
static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
{
struct lsm_prop prop;
- struct task_security_struct *tsec;
+ struct cred_security_struct *crsec;
struct cred *new_creds = *new;
if (new_creds == NULL) {
@@ -3669,10 +3670,10 @@ static int selinux_inode_copy_up(struct dentry *src, struct cred **new)
return -ENOMEM;
}
- tsec = selinux_cred(new_creds);
+ crsec = selinux_cred(new_creds);
/* Get label from overlay inode and set it in create_sid */
selinux_inode_getlsmprop(d_inode(src), &prop);
- tsec->create_sid = prop.selinux.secid;
+ crsec->create_sid = prop.selinux.secid;
*new = new_creds;
return 0;
}
@@ -3698,7 +3699,7 @@ static int selinux_inode_copy_up_xattr(struct dentry *dentry, const char *name)
static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
struct kernfs_node *kn)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
u32 parent_sid, newsid, clen;
int rc;
char *context;
@@ -3726,8 +3727,8 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
if (rc)
return rc;
- if (tsec->create_sid) {
- newsid = tsec->create_sid;
+ if (crsec->create_sid) {
+ newsid = crsec->create_sid;
} else {
u16 secclass = inode_mode_to_security_class(kn->mode);
const char *kn_name;
@@ -3738,7 +3739,7 @@ static int selinux_kernfs_init_security(struct kernfs_node *kn_dir,
q.name = kn_name;
q.hash_len = hashlen_string(kn_dir, kn_name);
- rc = security_transition_sid(tsec->sid,
+ rc = security_transition_sid(crsec->sid,
parent_sid, secclass, &q,
&newsid);
if (rc)
@@ -4152,7 +4153,10 @@ static int selinux_task_alloc(struct task_struct *task,
u64 clone_flags)
{
u32 sid = current_sid();
+ struct task_security_struct *old_tsec = selinux_task(current);
+ struct task_security_struct *new_tsec = selinux_task(task);
+ *new_tsec = *old_tsec;
return avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__FORK, NULL);
}
@@ -4162,10 +4166,10 @@ static int selinux_task_alloc(struct task_struct *task,
static int selinux_cred_prepare(struct cred *new, const struct cred *old,
gfp_t gfp)
{
- const struct task_security_struct *old_tsec = selinux_cred(old);
- struct task_security_struct *tsec = selinux_cred(new);
+ const struct cred_security_struct *old_crsec = selinux_cred(old);
+ struct cred_security_struct *crsec = selinux_cred(new);
- *tsec = *old_tsec;
+ *crsec = *old_crsec;
return 0;
}
@@ -4174,10 +4178,10 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old,
*/
static void selinux_cred_transfer(struct cred *new, const struct cred *old)
{
- const struct task_security_struct *old_tsec = selinux_cred(old);
- struct task_security_struct *tsec = selinux_cred(new);
+ const struct cred_security_struct *old_crsec = selinux_cred(old);
+ struct cred_security_struct *crsec = selinux_cred(new);
- *tsec = *old_tsec;
+ *crsec = *old_crsec;
}
static void selinux_cred_getsecid(const struct cred *c, u32 *secid)
@@ -4196,7 +4200,7 @@ static void selinux_cred_getlsmprop(const struct cred *c, struct lsm_prop *prop)
*/
static int selinux_kernel_act_as(struct cred *new, u32 secid)
{
- struct task_security_struct *tsec = selinux_cred(new);
+ struct cred_security_struct *crsec = selinux_cred(new);
u32 sid = current_sid();
int ret;
@@ -4205,10 +4209,10 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
KERNEL_SERVICE__USE_AS_OVERRIDE,
NULL);
if (ret == 0) {
- tsec->sid = secid;
- tsec->create_sid = 0;
- tsec->keycreate_sid = 0;
- tsec->sockcreate_sid = 0;
+ crsec->sid = secid;
+ crsec->create_sid = 0;
+ crsec->keycreate_sid = 0;
+ crsec->sockcreate_sid = 0;
}
return ret;
}
@@ -4220,7 +4224,7 @@ static int selinux_kernel_act_as(struct cred *new, u32 secid)
static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
{
struct inode_security_struct *isec = inode_security(inode);
- struct task_security_struct *tsec = selinux_cred(new);
+ struct cred_security_struct *crsec = selinux_cred(new);
u32 sid = current_sid();
int ret;
@@ -4230,7 +4234,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
NULL);
if (ret == 0)
- tsec->create_sid = isec->sid;
+ crsec->create_sid = isec->sid;
return ret;
}
@@ -4745,15 +4749,15 @@ static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid)
/* socket security operations */
-static int socket_sockcreate_sid(const struct task_security_struct *tsec,
+static int socket_sockcreate_sid(const struct cred_security_struct *crsec,
u16 secclass, u32 *socksid)
{
- if (tsec->sockcreate_sid > SECSID_NULL) {
- *socksid = tsec->sockcreate_sid;
+ if (crsec->sockcreate_sid > SECSID_NULL) {
+ *socksid = crsec->sockcreate_sid;
return 0;
}
- return security_transition_sid(tsec->sid, tsec->sid,
+ return security_transition_sid(crsec->sid, crsec->sid,
secclass, NULL, socksid);
}
@@ -4798,7 +4802,7 @@ static int sock_has_perm(struct sock *sk, u32 perms)
static int selinux_socket_create(int family, int type,
int protocol, int kern)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
u32 newsid;
u16 secclass;
int rc;
@@ -4807,17 +4811,17 @@ static int selinux_socket_create(int family, int type,
return 0;
secclass = socket_type_to_security_class(family, type, protocol);
- rc = socket_sockcreate_sid(tsec, secclass, &newsid);
+ rc = socket_sockcreate_sid(crsec, secclass, &newsid);
if (rc)
return rc;
- return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
+ return avc_has_perm(crsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
}
static int selinux_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
struct inode_security_struct *isec = inode_security_novalidate(SOCK_INODE(sock));
struct sk_security_struct *sksec;
u16 sclass = socket_type_to_security_class(family, type, protocol);
@@ -4825,7 +4829,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
int err = 0;
if (!kern) {
- err = socket_sockcreate_sid(tsec, sclass, &sid);
+ err = socket_sockcreate_sid(crsec, sclass, &sid);
if (err)
return err;
}
@@ -6527,37 +6531,37 @@ static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
static int selinux_lsm_getattr(unsigned int attr, struct task_struct *p,
char **value)
{
- const struct task_security_struct *tsec;
+ const struct cred_security_struct *crsec;
int error;
u32 sid;
u32 len;
rcu_read_lock();
- tsec = selinux_cred(__task_cred(p));
+ crsec = selinux_cred(__task_cred(p));
if (p != current) {
- error = avc_has_perm(current_sid(), tsec->sid,
+ error = avc_has_perm(current_sid(), crsec->sid,
SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
if (error)
goto err_unlock;
}
switch (attr) {
case LSM_ATTR_CURRENT:
- sid = tsec->sid;
+ sid = crsec->sid;
break;
case LSM_ATTR_PREV:
- sid = tsec->osid;
+ sid = crsec->osid;
break;
case LSM_ATTR_EXEC:
- sid = tsec->exec_sid;
+ sid = crsec->exec_sid;
break;
case LSM_ATTR_FSCREATE:
- sid = tsec->create_sid;
+ sid = crsec->create_sid;
break;
case LSM_ATTR_KEYCREATE:
- sid = tsec->keycreate_sid;
+ sid = crsec->keycreate_sid;
break;
case LSM_ATTR_SOCKCREATE:
- sid = tsec->sockcreate_sid;
+ sid = crsec->sockcreate_sid;
break;
default:
error = -EOPNOTSUPP;
@@ -6582,7 +6586,7 @@ err_unlock:
static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
{
- struct task_security_struct *tsec;
+ struct cred_security_struct *crsec;
struct cred *new;
u32 mysid = current_sid(), sid = 0, ptsid;
int error;
@@ -6668,11 +6672,11 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
operation. See selinux_bprm_creds_for_exec for the execve
checks and may_create for the file creation checks. The
operation will then fail if the context is not permitted. */
- tsec = selinux_cred(new);
+ crsec = selinux_cred(new);
if (attr == LSM_ATTR_EXEC) {
- tsec->exec_sid = sid;
+ crsec->exec_sid = sid;
} else if (attr == LSM_ATTR_FSCREATE) {
- tsec->create_sid = sid;
+ crsec->create_sid = sid;
} else if (attr == LSM_ATTR_KEYCREATE) {
if (sid) {
error = avc_has_perm(mysid, sid,
@@ -6680,22 +6684,22 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
if (error)
goto abort_change;
}
- tsec->keycreate_sid = sid;
+ crsec->keycreate_sid = sid;
} else if (attr == LSM_ATTR_SOCKCREATE) {
- tsec->sockcreate_sid = sid;
+ crsec->sockcreate_sid = sid;
} else if (attr == LSM_ATTR_CURRENT) {
error = -EINVAL;
if (sid == 0)
goto abort_change;
if (!current_is_single_threaded()) {
- error = security_bounded_transition(tsec->sid, sid);
+ error = security_bounded_transition(crsec->sid, sid);
if (error)
goto abort_change;
}
/* Check permissions for the transition. */
- error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
+ error = avc_has_perm(crsec->sid, sid, SECCLASS_PROCESS,
PROCESS__DYNTRANSITION, NULL);
if (error)
goto abort_change;
@@ -6710,7 +6714,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
goto abort_change;
}
- tsec->sid = sid;
+ crsec->sid = sid;
} else {
error = -EINVAL;
goto abort_change;
@@ -6877,14 +6881,14 @@ static int selinux_inode_getsecctx(struct inode *inode, struct lsm_context *cp)
static int selinux_key_alloc(struct key *k, const struct cred *cred,
unsigned long flags)
{
- const struct task_security_struct *tsec;
+ const struct cred_security_struct *crsec;
struct key_security_struct *ksec = selinux_key(k);
- tsec = selinux_cred(cred);
- if (tsec->keycreate_sid)
- ksec->sid = tsec->keycreate_sid;
+ crsec = selinux_cred(cred);
+ if (crsec->keycreate_sid)
+ ksec->sid = crsec->keycreate_sid;
else
- ksec->sid = tsec->sid;
+ ksec->sid = crsec->sid;
return 0;
}
@@ -7138,7 +7142,8 @@ static int selinux_bpf_token_create(struct bpf_token *token, union bpf_attr *att
#endif
struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
- .lbs_cred = sizeof(struct task_security_struct),
+ .lbs_cred = sizeof(struct cred_security_struct),
+ .lbs_task = sizeof(struct task_security_struct),
.lbs_file = sizeof(struct file_security_struct),
.lbs_inode = sizeof(struct inode_security_struct),
.lbs_ipc = sizeof(struct ipc_security_struct),
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 2d5139c6d45b..8fc3de5234ac 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -37,13 +37,16 @@ struct avdc_entry {
bool permissive; /* AVC permissive flag */
};
-struct task_security_struct {
+struct cred_security_struct {
u32 osid; /* SID prior to last execve */
u32 sid; /* current SID */
u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */
u32 keycreate_sid; /* keycreate SID */
u32 sockcreate_sid; /* fscreate SID */
+} __randomize_layout;
+
+struct task_security_struct {
#define TSEC_AVDC_DIR_SIZE (1 << 2)
struct {
u32 sid; /* current SID for cached entries */
@@ -54,10 +57,11 @@ struct task_security_struct {
} avdcache;
} __randomize_layout;
-static inline bool task_avdcache_permnoaudit(struct task_security_struct *tsec)
+static inline bool task_avdcache_permnoaudit(struct task_security_struct *tsec,
+ u32 sid)
{
return (tsec->avdcache.permissive_neveraudit &&
- tsec->sid == tsec->avdcache.sid &&
+ sid == tsec->avdcache.sid &&
tsec->avdcache.seqno == avc_policy_seqno());
}
@@ -172,11 +176,17 @@ struct perf_event_security_struct {
};
extern struct lsm_blob_sizes selinux_blob_sizes;
-static inline struct task_security_struct *selinux_cred(const struct cred *cred)
+static inline struct cred_security_struct *selinux_cred(const struct cred *cred)
{
return cred->security + selinux_blob_sizes.lbs_cred;
}
+static inline struct task_security_struct *
+selinux_task(const struct task_struct *task)
+{
+ return task->security + selinux_blob_sizes.lbs_task;
+}
+
static inline struct file_security_struct *selinux_file(const struct file *file)
{
return file->f_security + selinux_blob_sizes.lbs_file;
@@ -207,9 +217,9 @@ selinux_ipc(const struct kern_ipc_perm *ipc)
*/
static inline u32 current_sid(void)
{
- const struct task_security_struct *tsec = selinux_cred(current_cred());
+ const struct cred_security_struct *crsec = selinux_cred(current_cred());
- return tsec->sid;
+ return crsec->sid;
}
static inline struct superblock_security_struct *
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 93ea27acbfef..d98fbc4d068f 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -507,6 +507,7 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
{
int ret = 0;
struct dentry *tmp_parent, *tmp_bool_dir, *tmp_class_dir;
+ struct renamedata rd = {};
unsigned int bool_num = 0;
char **bool_names = NULL;
int *bool_values = NULL;
@@ -540,9 +541,14 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
if (ret)
goto out;
- lock_rename(tmp_parent, fsi->sb->s_root);
+ rd.old_parent = tmp_parent;
+ rd.new_parent = fsi->sb->s_root;
/* booleans */
+ ret = start_renaming_two_dentries(&rd, tmp_bool_dir, fsi->bool_dir);
+ if (ret)
+ goto out;
+
d_exchange(tmp_bool_dir, fsi->bool_dir);
swap(fsi->bool_num, bool_num);
@@ -550,12 +556,17 @@ static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
swap(fsi->bool_pending_values, bool_values);
fsi->bool_dir = tmp_bool_dir;
+ end_renaming(&rd);
/* classes */
+ ret = start_renaming_two_dentries(&rd, tmp_class_dir, fsi->class_dir);
+ if (ret)
+ goto out;
+
d_exchange(tmp_class_dir, fsi->class_dir);
fsi->class_dir = tmp_class_dir;
- unlock_rename(tmp_parent, fsi->sb->s_root);
+ end_renaming(&rd);
out:
sel_remove_old_bool_data(bool_num, bool_names, bool_values);