aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/lsm.c13
-rw-r--r--security/commoncap.c15
-rw-r--r--security/device_cgroup.c1
-rw-r--r--security/integrity/ima/ima_appraise.c2
-rw-r--r--security/integrity/ima/ima_kexec.c6
-rw-r--r--security/integrity/ima/ima_main.c14
-rw-r--r--security/integrity/platform_certs/load_uefi.c5
-rw-r--r--security/keys/Kconfig2
-rw-r--r--security/keys/dh.c130
-rw-r--r--security/security.c14
-rw-r--r--security/selinux/hooks.c119
-rw-r--r--security/selinux/ss/hashtab.c17
-rw-r--r--security/selinux/ss/sidtab.c2
-rw-r--r--security/selinux/xfrm.c4
-rw-r--r--security/smack/smack.h16
-rw-r--r--security/smack/smack_lsm.c9
-rw-r--r--security/tomoyo/util.c31
17 files changed, 134 insertions, 266 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 0d6585056f3d..4f0eecb67dde 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -728,7 +728,14 @@ static void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
return;
}
-static void apparmor_task_getsecid(struct task_struct *p, u32 *secid)
+static void apparmor_current_getsecid_subj(u32 *secid)
+{
+ struct aa_label *label = aa_get_current_label();
+ *secid = label->secid;
+ aa_put_label(label);
+}
+
+static void apparmor_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
struct aa_label *label = aa_get_task_label(p);
*secid = label->secid;
@@ -1252,8 +1259,8 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_free, apparmor_task_free),
LSM_HOOK_INIT(task_alloc, apparmor_task_alloc),
- LSM_HOOK_INIT(task_getsecid_subj, apparmor_task_getsecid),
- LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid),
+ LSM_HOOK_INIT(current_getsecid_subj, apparmor_current_getsecid_subj),
+ LSM_HOOK_INIT(task_getsecid_obj, apparmor_task_getsecid_obj),
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
LSM_HOOK_INIT(task_kill, apparmor_task_kill),
diff --git a/security/commoncap.c b/security/commoncap.c
index 3f810d37b71b..5fc8986c3c77 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -24,6 +24,7 @@
#include <linux/user_namespace.h>
#include <linux/binfmts.h>
#include <linux/personality.h>
+#include <linux/mnt_idmapping.h>
/*
* If a non-root user executes a setuid-root binary in
@@ -418,7 +419,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
kroot = make_kuid(fs_ns, root);
/* If this is an idmapped mount shift the kuid. */
- kroot = kuid_into_mnt(mnt_userns, kroot);
+ kroot = mapped_kuid_fs(mnt_userns, fs_ns, kroot);
/* If the root kuid maps to a valid uid in current ns, then return
* this as a nscap. */
@@ -488,6 +489,7 @@ out_free:
* @size: size of @ivalue
* @task_ns: user namespace of the caller
* @mnt_userns: user namespace of the mount the inode was found from
+ * @fs_userns: user namespace of the filesystem
*
* If the inode has been found through an idmapped mount the user namespace of
* the vfsmount must be passed through @mnt_userns. This function will then
@@ -497,7 +499,8 @@ out_free:
*/
static kuid_t rootid_from_xattr(const void *value, size_t size,
struct user_namespace *task_ns,
- struct user_namespace *mnt_userns)
+ struct user_namespace *mnt_userns,
+ struct user_namespace *fs_userns)
{
const struct vfs_ns_cap_data *nscap = value;
kuid_t rootkid;
@@ -507,7 +510,7 @@ static kuid_t rootid_from_xattr(const void *value, size_t size,
rootid = le32_to_cpu(nscap->rootid);
rootkid = make_kuid(task_ns, rootid);
- return kuid_from_mnt(mnt_userns, rootkid);
+ return mapped_kuid_user(mnt_userns, fs_userns, rootkid);
}
static bool validheader(size_t size, const struct vfs_cap_data *cap)
@@ -553,12 +556,12 @@ int cap_convert_nscap(struct user_namespace *mnt_userns, struct dentry *dentry,
return -EINVAL;
if (!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_SETFCAP))
return -EPERM;
- if (size == XATTR_CAPS_SZ_2 && (mnt_userns == &init_user_ns))
+ if (size == XATTR_CAPS_SZ_2 && (mnt_userns == fs_ns))
if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP))
/* user is privileged, just write the v2 */
return size;
- rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns);
+ rootid = rootid_from_xattr(*ivalue, size, task_ns, mnt_userns, fs_ns);
if (!uid_valid(rootid))
return -EINVAL;
@@ -699,7 +702,7 @@ int get_vfs_caps_from_disk(struct user_namespace *mnt_userns,
/* Limit the caps to the mounter of the filesystem
* or the more limited uid specified in the xattr.
*/
- rootkuid = kuid_into_mnt(mnt_userns, rootkuid);
+ rootkuid = mapped_kuid_fs(mnt_userns, fs_ns, rootkuid);
if (!rootid_owns_currentns(rootkuid))
return -ENODATA;
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 04375df52fc9..842889f3dcb7 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -5,6 +5,7 @@
* Copyright 2007 IBM Corp
*/
+#include <linux/bpf-cgroup.h>
#include <linux/device_cgroup.h>
#include <linux/cgroup.h>
#include <linux/ctype.h>
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index dbba51583e7c..17232bbfb9f9 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -76,7 +76,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
if (!ima_appraise)
return 0;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
return ima_match_policy(mnt_userns, inode, current_cred(), secid,
func, mask, IMA_APPRAISE | IMA_HASH, NULL,
NULL, NULL, NULL);
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index f799cc278a9a..13753136f03f 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -61,9 +61,9 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
}
memcpy(file.buf, &khdr, sizeof(khdr));
- print_hex_dump(KERN_DEBUG, "ima dump: ", DUMP_PREFIX_NONE,
- 16, 1, file.buf,
- file.count < 100 ? file.count : 100, true);
+ print_hex_dump_debug("ima dump: ", DUMP_PREFIX_NONE, 16, 1,
+ file.buf, file.count < 100 ? file.count : 100,
+ true);
*buffer_size = file.count;
*buffer = file.buf;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 465865412100..8c6e4514d494 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -408,7 +408,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
u32 secid;
if (file && (prot & PROT_EXEC)) {
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_EXEC, MMAP_CHECK);
}
@@ -446,7 +446,7 @@ int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
!(prot & PROT_EXEC) || (vma->vm_flags & VM_EXEC))
return 0;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
inode = file_inode(vma->vm_file);
action = ima_get_action(file_mnt_user_ns(vma->vm_file), inode,
current_cred(), secid, MAY_EXEC, MMAP_CHECK,
@@ -487,7 +487,7 @@ int ima_bprm_check(struct linux_binprm *bprm)
int ret;
u32 secid;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
ret = process_measurement(bprm->file, current_cred(), secid, NULL, 0,
MAY_EXEC, BPRM_CHECK);
if (ret)
@@ -512,7 +512,7 @@ int ima_file_check(struct file *file, int mask)
{
u32 secid;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
return process_measurement(file, current_cred(), secid, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK);
@@ -709,7 +709,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
/* Read entire file for all partial reads. */
func = read_idmap[read_id] ?: FILE_CHECK;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
return process_measurement(file, current_cred(), secid, NULL,
0, MAY_READ, func);
}
@@ -752,7 +752,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
}
func = read_idmap[read_id] ?: FILE_CHECK;
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
return process_measurement(file, current_cred(), secid, buf, size,
MAY_READ, func);
}
@@ -905,7 +905,7 @@ int process_buffer_measurement(struct user_namespace *mnt_userns,
* buffer measurements.
*/
if (func) {
- security_task_getsecid_subj(current, &secid);
+ security_current_getsecid_subj(&secid);
action = ima_get_action(mnt_userns, inode, current_cred(),
secid, 0, func, &pcr, &template,
func_data, NULL);
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index f290f78c3f30..08b6d12f99b4 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -6,6 +6,7 @@
#include <linux/err.h>
#include <linux/efi.h>
#include <linux/slab.h>
+#include <linux/ima.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
#include "../integrity.h"
@@ -176,6 +177,10 @@ static int __init load_uefi_certs(void)
kfree(dbx);
}
+ /* the MOK/MOKx can not be trusted when secure boot is disabled */
+ if (!arch_ima_get_secureboot())
+ return 0;
+
mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status);
if (!mokx) {
if (status == EFI_NOT_FOUND)
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index 64b81abd087e..969122c7b92f 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -109,7 +109,7 @@ config KEY_DH_OPERATIONS
bool "Diffie-Hellman operations on retained keys"
depends on KEYS
select CRYPTO
- select CRYPTO_HASH
+ select CRYPTO_KDF800108_CTR
select CRYPTO_DH
help
This option provides support for calculating Diffie-Hellman
diff --git a/security/keys/dh.c b/security/keys/dh.c
index 1abfa70ed6e1..4573fc15617d 100644
--- a/security/keys/dh.c
+++ b/security/keys/dh.c
@@ -11,6 +11,7 @@
#include <crypto/hash.h>
#include <crypto/kpp.h>
#include <crypto/dh.h>
+#include <crypto/kdf_sp800108.h>
#include <keys/user-type.h>
#include "internal.h"
@@ -79,17 +80,9 @@ static void dh_crypto_done(struct crypto_async_request *req, int err)
complete(&compl->completion);
}
-struct kdf_sdesc {
- struct shash_desc shash;
- char ctx[];
-};
-
-static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname)
+static int kdf_alloc(struct crypto_shash **hash, char *hashname)
{
struct crypto_shash *tfm;
- struct kdf_sdesc *sdesc;
- int size;
- int err;
/* allocate synchronous hash */
tfm = crypto_alloc_shash(hashname, 0, 0);
@@ -98,112 +91,30 @@ static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname)
return PTR_ERR(tfm);
}
- err = -EINVAL;
- if (crypto_shash_digestsize(tfm) == 0)
- goto out_free_tfm;
-
- err = -ENOMEM;
- size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm);
- sdesc = kmalloc(size, GFP_KERNEL);
- if (!sdesc)
- goto out_free_tfm;
- sdesc->shash.tfm = tfm;
+ if (crypto_shash_digestsize(tfm) == 0) {
+ crypto_free_shash(tfm);
+ return -EINVAL;
+ }
- *sdesc_ret = sdesc;
+ *hash = tfm;
return 0;
-
-out_free_tfm:
- crypto_free_shash(tfm);
- return err;
}
-static void kdf_dealloc(struct kdf_sdesc *sdesc)
+static void kdf_dealloc(struct crypto_shash *hash)
{
- if (!sdesc)
- return;
-
- if (sdesc->shash.tfm)
- crypto_free_shash(sdesc->shash.tfm);
-
- kfree_sensitive(sdesc);
-}
-
-/*
- * Implementation of the KDF in counter mode according to SP800-108 section 5.1
- * as well as SP800-56A section 5.8.1 (Single-step KDF).
- *
- * SP800-56A:
- * The src pointer is defined as Z || other info where Z is the shared secret
- * from DH and other info is an arbitrary string (see SP800-56A section
- * 5.8.1.2).
- *
- * 'dlen' must be a multiple of the digest size.
- */
-static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,
- u8 *dst, unsigned int dlen, unsigned int zlen)
-{
- struct shash_desc *desc = &sdesc->shash;
- unsigned int h = crypto_shash_digestsize(desc->tfm);
- int err = 0;
- u8 *dst_orig = dst;
- __be32 counter = cpu_to_be32(1);
-
- while (dlen) {
- err = crypto_shash_init(desc);
- if (err)
- goto err;
-
- err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32));
- if (err)
- goto err;
-
- if (zlen && h) {
- u8 tmpbuffer[32];
- size_t chunk = min_t(size_t, zlen, sizeof(tmpbuffer));
- memset(tmpbuffer, 0, chunk);
-
- do {
- err = crypto_shash_update(desc, tmpbuffer,
- chunk);
- if (err)
- goto err;
-
- zlen -= chunk;
- chunk = min_t(size_t, zlen, sizeof(tmpbuffer));
- } while (zlen);
- }
-
- if (src && slen) {
- err = crypto_shash_update(desc, src, slen);
- if (err)
- goto err;
- }
-
- err = crypto_shash_final(desc, dst);
- if (err)
- goto err;
-
- dlen -= h;
- dst += h;
- counter = cpu_to_be32(be32_to_cpu(counter) + 1);
- }
-
- return 0;
-
-err:
- memzero_explicit(dst_orig, dlen);
- return err;
+ if (hash)
+ crypto_free_shash(hash);
}
-static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
+static int keyctl_dh_compute_kdf(struct crypto_shash *hash,
char __user *buffer, size_t buflen,
- uint8_t *kbuf, size_t kbuflen, size_t lzero)
+ uint8_t *kbuf, size_t kbuflen)
{
+ struct kvec kbuf_iov = { .iov_base = kbuf, .iov_len = kbuflen };
uint8_t *outbuf = NULL;
int ret;
- size_t outbuf_len = roundup(buflen,
- crypto_shash_digestsize(sdesc->shash.tfm));
+ size_t outbuf_len = roundup(buflen, crypto_shash_digestsize(hash));
outbuf = kmalloc(outbuf_len, GFP_KERNEL);
if (!outbuf) {
@@ -211,7 +122,7 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,
goto err;
}
- ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, outbuf_len, lzero);
+ ret = crypto_kdf108_ctr_generate(hash, &kbuf_iov, 1, outbuf, outbuf_len);
if (ret)
goto err;
@@ -240,7 +151,7 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
struct kpp_request *req;
uint8_t *secret;
uint8_t *outbuf;
- struct kdf_sdesc *sdesc = NULL;
+ struct crypto_shash *hash = NULL;
if (!params || (!buffer && buflen)) {
ret = -EINVAL;
@@ -273,7 +184,7 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
}
/* allocate KDF from the kernel crypto API */
- ret = kdf_alloc(&sdesc, hashname);
+ ret = kdf_alloc(&hash, hashname);
kfree(hashname);
if (ret)
goto out1;
@@ -383,9 +294,8 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,
goto out6;
}
- ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf,
- req->dst_len + kdfcopy->otherinfolen,
- outlen - req->dst_len);
+ ret = keyctl_dh_compute_kdf(hash, buffer, buflen, outbuf,
+ req->dst_len + kdfcopy->otherinfolen);
} else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) {
ret = req->dst_len;
} else {
@@ -403,7 +313,7 @@ out3:
out2:
dh_free_data(&dh_inputs);
out1:
- kdf_dealloc(sdesc);
+ kdf_dealloc(hash);
return ret;
}
diff --git a/security/security.c b/security/security.c
index c88167a414b4..3d4eb474f35b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -994,14 +994,6 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb,
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);
-int security_add_mnt_opt(const char *option, const char *val, int len,
- void **mnt_opts)
-{
- return call_int_hook(sb_add_mnt_opt, -EINVAL,
- option, val, len, mnt_opts);
-}
-EXPORT_SYMBOL(security_add_mnt_opt);
-
int security_move_mount(const struct path *from_path, const struct path *to_path)
{
return call_int_hook(move_mount, 0, from_path, to_path);
@@ -1808,12 +1800,12 @@ int security_task_getsid(struct task_struct *p)
return call_int_hook(task_getsid, 0, p);
}
-void security_task_getsecid_subj(struct task_struct *p, u32 *secid)
+void security_current_getsecid_subj(u32 *secid)
{
*secid = 0;
- call_void_hook(task_getsecid_subj, p, secid);
+ call_void_hook(current_getsecid_subj, secid);
}
-EXPORT_SYMBOL(security_task_getsecid_subj);
+EXPORT_SYMBOL(security_current_getsecid_subj);
void security_task_getsecid_obj(struct task_struct *p, u32 *secid)
{
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 62d30c0a30c2..5b6895e4fc29 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -230,19 +230,6 @@ static inline u32 cred_sid(const struct cred *cred)
}
/*
- * get the subjective security ID of a task
- */
-static inline u32 task_sid_subj(const struct task_struct *task)
-{
- u32 sid;
-
- rcu_read_lock();
- sid = cred_sid(rcu_dereference(task->cred));
- rcu_read_unlock();
- return sid;
-}
-
-/*
* get the objective security ID of a task
*/
static inline u32 task_sid_obj(const struct task_struct *task)
@@ -611,10 +598,11 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
return 0;
}
-static int parse_sid(struct super_block *sb, const char *s, u32 *sid)
+static int parse_sid(struct super_block *sb, const char *s, u32 *sid,
+ gfp_t gfp)
{
int rc = security_context_str_to_sid(&selinux_state, s,
- sid, GFP_KERNEL);
+ sid, gfp);
if (rc)
pr_warn("SELinux: security_context_str_to_sid"
"(%s) failed for (dev %s, type %s) errno=%d\n",
@@ -685,7 +673,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
*/
if (opts) {
if (opts->fscontext) {
- rc = parse_sid(sb, opts->fscontext, &fscontext_sid);
+ rc = parse_sid(sb, opts->fscontext, &fscontext_sid,
+ GFP_KERNEL);
if (rc)
goto out;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid,
@@ -694,7 +683,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
sbsec->flags |= FSCONTEXT_MNT;
}
if (opts->context) {
- rc = parse_sid(sb, opts->context, &context_sid);
+ rc = parse_sid(sb, opts->context, &context_sid,
+ GFP_KERNEL);
if (rc)
goto out;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
@@ -703,7 +693,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
sbsec->flags |= CONTEXT_MNT;
}
if (opts->rootcontext) {
- rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid);
+ rc = parse_sid(sb, opts->rootcontext, &rootcontext_sid,
+ GFP_KERNEL);
if (rc)
goto out;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid,
@@ -712,7 +703,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
sbsec->flags |= ROOTCONTEXT_MNT;
}
if (opts->defcontext) {
- rc = parse_sid(sb, opts->defcontext, &defcontext_sid);
+ rc = parse_sid(sb, opts->defcontext, &defcontext_sid,
+ GFP_KERNEL);
if (rc)
goto out;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid,
@@ -983,82 +975,54 @@ out:
static int selinux_add_opt(int token, const char *s, void **mnt_opts)
{
struct selinux_mnt_opts *opts = *mnt_opts;
+ bool is_alloc_opts = false;
- if (token == Opt_seclabel) /* eaten and completely ignored */
+ if (token == Opt_seclabel)
+ /* eaten and completely ignored */
return 0;
+ if (!s)
+ return -ENOMEM;
if (!opts) {
- opts = kzalloc(sizeof(struct selinux_mnt_opts), GFP_KERNEL);
+ opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return -ENOMEM;
*mnt_opts = opts;
+ is_alloc_opts = true;
}
- if (!s)
- return -ENOMEM;
+
switch (token) {
case Opt_context:
if (opts->context || opts->defcontext)
- goto Einval;
+ goto err;
opts->context = s;
break;
case Opt_fscontext:
if (opts->fscontext)
- goto Einval;
+ goto err;
opts->fscontext = s;
break;
case Opt_rootcontext:
if (opts->rootcontext)
- goto Einval;
+ goto err;
opts->rootcontext = s;
break;
case Opt_defcontext:
if (opts->context || opts->defcontext)
- goto Einval;
+ goto err;
opts->defcontext = s;
break;
}
- return 0;
-Einval:
- pr_warn(SEL_MOUNT_FAIL_MSG);
- return -EINVAL;
-}
-
-static int selinux_add_mnt_opt(const char *option, const char *val, int len,
- void **mnt_opts)
-{
- int token = Opt_error;
- int rc, i;
-
- for (i = 0; i < ARRAY_SIZE(tokens); i++) {
- if (strcmp(option, tokens[i].name) == 0) {
- token = tokens[i].opt;
- break;
- }
- }
- if (token == Opt_error)
- return -EINVAL;
-
- if (token != Opt_seclabel) {
- val = kmemdup_nul(val, len, GFP_KERNEL);
- if (!val) {
- rc = -ENOMEM;
- goto free_opt;
- }
- }
- rc = selinux_add_opt(token, val, mnt_opts);
- if (unlikely(rc)) {
- kfree(val);
- goto free_opt;
- }
- return rc;
+ return 0;
-free_opt:
- if (*mnt_opts) {
- selinux_free_mnt_opts(*mnt_opts);
+err:
+ if (is_alloc_opts) {
+ kfree(opts);
*mnt_opts = NULL;
}
- return rc;
+ pr_warn(SEL_MOUNT_FAIL_MSG);
+ return -EINVAL;
}
static int show_sid(struct seq_file *m, u32 sid)
@@ -2702,14 +2666,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
return (sbsec->flags & SE_MNTMASK) ? 1 : 0;
if (opts->fscontext) {
- rc = parse_sid(sb, opts->fscontext, &sid);
+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
return 1;
}
if (opts->context) {
- rc = parse_sid(sb, opts->context, &sid);
+ rc = parse_sid(sb, opts->context, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
@@ -2719,14 +2683,14 @@ static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts)
struct inode_security_struct *root_isec;
root_isec = backing_inode_security(sb->s_root);
- rc = parse_sid(sb, opts->rootcontext, &sid);
+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
return 1;
}
if (opts->defcontext) {
- rc = parse_sid(sb, opts->defcontext, &sid);
+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_NOWAIT);
if (rc)
return 1;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
@@ -2749,14 +2713,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
return 0;
if (opts->fscontext) {
- rc = parse_sid(sb, opts->fscontext, &sid);
+ rc = parse_sid(sb, opts->fscontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
goto out_bad_option;
}
if (opts->context) {
- rc = parse_sid(sb, opts->context, &sid);
+ rc = parse_sid(sb, opts->context, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
@@ -2765,14 +2729,14 @@ static int selinux_sb_remount(struct super_block *sb, void *mnt_opts)
if (opts->rootcontext) {
struct inode_security_struct *root_isec;
root_isec = backing_inode_security(sb->s_root);
- rc = parse_sid(sb, opts->rootcontext, &sid);
+ rc = parse_sid(sb, opts->rootcontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
goto out_bad_option;
}
if (opts->defcontext) {
- rc = parse_sid(sb, opts->defcontext, &sid);
+ rc = parse_sid(sb, opts->defcontext, &sid, GFP_KERNEL);
if (rc)
return rc;
if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
@@ -4205,9 +4169,9 @@ static int selinux_task_getsid(struct task_struct *p)
PROCESS__GETSESSION, NULL);
}
-static void selinux_task_getsecid_subj(struct task_struct *p, u32 *secid)
+static void selinux_current_getsecid_subj(u32 *secid)
{
- *secid = task_sid_subj(p);
+ *secid = current_sid();
}
static void selinux_task_getsecid_obj(struct task_struct *p, u32 *secid)
@@ -5780,7 +5744,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct sk_security_struct *sksec;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
- u8 proto;
+ u8 proto = 0;
sk = skb_to_full_sk(skb);
if (sk == NULL)
@@ -7159,7 +7123,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
- LSM_HOOK_INIT(task_getsecid_subj, selinux_task_getsecid_subj),
+ LSM_HOOK_INIT(current_getsecid_subj, selinux_current_getsecid_subj),
LSM_HOOK_INIT(task_getsecid_obj, selinux_task_getsecid_obj),
LSM_HOOK_INIT(task_setnice, selinux_task_setnice),
LSM_HOOK_INIT(task_setioprio, selinux_task_setioprio),
@@ -7298,7 +7262,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(fs_context_dup, selinux_fs_context_dup),
LSM_HOOK_INIT(fs_context_parse_param, selinux_fs_context_parse_param),
LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts),
- LSM_HOOK_INIT(sb_add_mnt_opt, selinux_add_mnt_opt),
#ifdef CONFIG_SECURITY_NETWORK_XFRM
LSM_HOOK_INIT(xfrm_policy_clone_security, selinux_xfrm_policy_clone),
#endif
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 727c3b484bd3..0ae4e4e57a40 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -31,13 +31,20 @@ static u32 hashtab_compute_size(u32 nel)
int hashtab_init(struct hashtab *h, u32 nel_hint)
{
- h->size = hashtab_compute_size(nel_hint);
+ u32 size = hashtab_compute_size(nel_hint);
+
+ /* should already be zeroed, but better be safe */
h->nel = 0;
- if (!h->size)
- return 0;
+ h->size = 0;
+ h->htable = NULL;
- h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL);
- return h->htable ? 0 : -ENOMEM;
+ if (size) {
+ h->htable = kcalloc(size, sizeof(*h->htable), GFP_KERNEL);
+ if (!h->htable)
+ return -ENOMEM;
+ h->size = size;
+ }
+ return 0;
}
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index 656d50b09f76..293ec048af08 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -570,7 +570,7 @@ void sidtab_sid2str_put(struct sidtab *s, struct sidtab_entry *entry,
goto out_unlock;
}
- cache = kmalloc(sizeof(struct sidtab_str_cache) + str_len, GFP_ATOMIC);
+ cache = kmalloc(struct_size(cache, str, str_len), GFP_ATOMIC);
if (!cache)
goto out_unlock;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index be83e5ce4469..90697317895f 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -89,7 +89,7 @@ static int selinux_xfrm_alloc_user(struct xfrm_sec_ctx **ctxp,
if (str_len >= PAGE_SIZE)
return -ENOMEM;
- ctx = kmalloc(sizeof(*ctx) + str_len + 1, gfp);
+ ctx = kmalloc(struct_size(ctx, ctx_str, str_len + 1), gfp);
if (!ctx)
return -ENOMEM;
@@ -360,7 +360,7 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x,
if (rc)
return rc;
- ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC);
+ ctx = kmalloc(struct_size(ctx, ctx_str, str_len), GFP_ATOMIC);
if (!ctx) {
rc = -ENOMEM;
goto out;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 99c3422596ab..fc837dcebf96 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -389,22 +389,6 @@ static inline struct smack_known *smk_of_task(const struct task_smack *tsp)
return tsp->smk_task;
}
-static inline struct smack_known *smk_of_task_struct_subj(
- const struct task_struct *t)
-{
- struct smack_known *skp;
- const struct cred *cred;
-
- rcu_read_lock();
-
- cred = rcu_dereference(t->cred);
- skp = smk_of_task(smack_cred(cred));
-
- rcu_read_unlock();
-
- return skp;
-}
-
static inline struct smack_known *smk_of_task_struct_obj(
const struct task_struct *t)
{
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index efd35b07c7f8..14b279cc75c9 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -2067,15 +2067,14 @@ static int smack_task_getsid(struct task_struct *p)
}
/**
- * smack_task_getsecid_subj - get the subjective secid of the task
- * @p: the task
+ * smack_current_getsecid_subj - get the subjective secid of the current task
* @secid: where to put the result
*
* Sets the secid to contain a u32 version of the task's subjective smack label.
*/
-static void smack_task_getsecid_subj(struct task_struct *p, u32 *secid)
+static void smack_current_getsecid_subj(u32 *secid)
{
- struct smack_known *skp = smk_of_task_struct_subj(p);
+ struct smack_known *skp = smk_of_current();
*secid = skp->smk_secid;
}
@@ -4807,7 +4806,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_setpgid, smack_task_setpgid),
LSM_HOOK_INIT(task_getpgid, smack_task_getpgid),
LSM_HOOK_INIT(task_getsid, smack_task_getsid),
- LSM_HOOK_INIT(task_getsecid_subj, smack_task_getsecid_subj),
+ LSM_HOOK_INIT(current_getsecid_subj, smack_current_getsecid_subj),
LSM_HOOK_INIT(task_getsecid_obj, smack_task_getsecid_obj),
LSM_HOOK_INIT(task_setnice, smack_task_setnice),
LSM_HOOK_INIT(task_setioprio, smack_task_setioprio),
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 1da2e3722b12..6799b1122c9d 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -1051,10 +1051,11 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
return false;
if (!domain)
return true;
+ if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED]))
+ return false;
list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
srcu_read_lock_held(&tomoyo_ss)) {
u16 perm;
- u8 i;
if (ptr->is_deleted)
continue;
@@ -1065,23 +1066,23 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
*/
switch (ptr->type) {
case TOMOYO_TYPE_PATH_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_path_acl, head)->perm);
+ perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm);
break;
case TOMOYO_TYPE_PATH2_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_path2_acl, head)->perm);
+ perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm);
break;
case TOMOYO_TYPE_PATH_NUMBER_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_path_number_acl, head)
+ perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head)
->perm);
break;
case TOMOYO_TYPE_MKDEV_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
+ perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
break;
case TOMOYO_TYPE_INET_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_inet_acl, head)->perm);
+ perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm);
break;
case TOMOYO_TYPE_UNIX_ACL:
- data_race(perm = container_of(ptr, struct tomoyo_unix_acl, head)->perm);
+ perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm);
break;
case TOMOYO_TYPE_MANUAL_TASK_ACL:
perm = 0;
@@ -1089,21 +1090,17 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
default:
perm = 1;
}
- for (i = 0; i < 16; i++)
- if (perm & (1 << i))
- count++;
+ count += hweight16(perm);
}
if (count < tomoyo_profile(domain->ns, domain->profile)->
pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
return true;
- if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) {
- domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true;
- /* r->granted = false; */
- tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
+ WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true);
+ /* r->granted = false; */
+ tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
#ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
- pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
- domain->domainname->name);
+ pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
+ domain->domainname->name);
#endif
- }
return false;
}