summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/commoncap.c67
-rw-r--r--security/integrity/evm/evm_crypto.c7
-rw-r--r--security/integrity/iint.c8
-rw-r--r--security/integrity/ima/ima_kexec.c3
-rw-r--r--security/integrity/ima/ima_mok.c5
-rw-r--r--security/keys/key.c2
-rw-r--r--security/keys/trusted.c2
-rw-r--r--security/smack/smackfs.c21
8 files changed, 83 insertions, 32 deletions
diff --git a/security/commoncap.c b/security/commoncap.c
index 0ca31c8bc0b1..28a6939bcc4e 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -371,10 +371,11 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
{
int size, ret;
kuid_t kroot;
+ u32 nsmagic, magic;
uid_t root, mappedroot;
char *tmpbuf = NULL;
struct vfs_cap_data *cap;
- struct vfs_ns_cap_data *nscap;
+ struct vfs_ns_cap_data *nscap = NULL;
struct dentry *dentry;
struct user_namespace *fs_ns;
@@ -396,46 +397,61 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
fs_ns = inode->i_sb->s_user_ns;
cap = (struct vfs_cap_data *) tmpbuf;
if (is_v2header((size_t) ret, cap)) {
- /* If this is sizeof(vfs_cap_data) then we're ok with the
- * on-disk value, so return that. */
- if (alloc)
- *buffer = tmpbuf;
- else
- kfree(tmpbuf);
- return ret;
- } else if (!is_v3header((size_t) ret, cap)) {
- kfree(tmpbuf);
- return -EINVAL;
+ root = 0;
+ } else if (is_v3header((size_t) ret, cap)) {
+ nscap = (struct vfs_ns_cap_data *) tmpbuf;
+ root = le32_to_cpu(nscap->rootid);
+ } else {
+ size = -EINVAL;
+ goto out_free;
}
- nscap = (struct vfs_ns_cap_data *) tmpbuf;
- root = le32_to_cpu(nscap->rootid);
kroot = make_kuid(fs_ns, root);
/* If the root kuid maps to a valid uid in current ns, then return
* this as a nscap. */
mappedroot = from_kuid(current_user_ns(), kroot);
if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) {
+ size = sizeof(struct vfs_ns_cap_data);
if (alloc) {
- *buffer = tmpbuf;
+ if (!nscap) {
+ /* v2 -> v3 conversion */
+ nscap = kzalloc(size, GFP_ATOMIC);
+ if (!nscap) {
+ size = -ENOMEM;
+ goto out_free;
+ }
+ nsmagic = VFS_CAP_REVISION_3;
+ magic = le32_to_cpu(cap->magic_etc);
+ if (magic & VFS_CAP_FLAGS_EFFECTIVE)
+ nsmagic |= VFS_CAP_FLAGS_EFFECTIVE;
+ memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
+ nscap->magic_etc = cpu_to_le32(nsmagic);
+ } else {
+ /* use allocated v3 buffer */
+ tmpbuf = NULL;
+ }
nscap->rootid = cpu_to_le32(mappedroot);
- } else
- kfree(tmpbuf);
- return size;
+ *buffer = nscap;
+ }
+ goto out_free;
}
if (!rootid_owns_currentns(kroot)) {
- kfree(tmpbuf);
- return -EOPNOTSUPP;
+ size = -EOVERFLOW;
+ goto out_free;
}
/* This comes from a parent namespace. Return as a v2 capability */
size = sizeof(struct vfs_cap_data);
if (alloc) {
- *buffer = kmalloc(size, GFP_ATOMIC);
- if (*buffer) {
- struct vfs_cap_data *cap = *buffer;
- __le32 nsmagic, magic;
+ if (nscap) {
+ /* v3 -> v2 conversion */
+ cap = kzalloc(size, GFP_ATOMIC);
+ if (!cap) {
+ size = -ENOMEM;
+ goto out_free;
+ }
magic = VFS_CAP_REVISION_2;
nsmagic = le32_to_cpu(nscap->magic_etc);
if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE)
@@ -443,9 +459,12 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
cap->magic_etc = cpu_to_le32(magic);
} else {
- size = -ENOMEM;
+ /* use unconverted v2 */
+ tmpbuf = NULL;
}
+ *buffer = cap;
}
+out_free:
kfree(tmpbuf);
return size;
}
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index ee6bd945f3d6..25dac691491b 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -75,7 +75,7 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo)
{
long rc;
const char *algo;
- struct crypto_shash **tfm, *tmp_tfm;
+ struct crypto_shash **tfm, *tmp_tfm = NULL;
struct shash_desc *desc;
if (type == EVM_XATTR_HMAC) {
@@ -120,13 +120,16 @@ unlock:
alloc:
desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm),
GFP_KERNEL);
- if (!desc)
+ if (!desc) {
+ crypto_free_shash(tmp_tfm);
return ERR_PTR(-ENOMEM);
+ }
desc->tfm = *tfm;
rc = crypto_shash_init(desc);
if (rc) {
+ crypto_free_shash(tmp_tfm);
kfree(desc);
return ERR_PTR(rc);
}
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index e12c4900510f..0b9cb639a0ed 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -98,6 +98,14 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
struct rb_node *node, *parent = NULL;
struct integrity_iint_cache *iint, *test_iint;
+ /*
+ * The integrity's "iint_cache" is initialized at security_init(),
+ * unless it is not included in the ordered list of LSMs enabled
+ * on the boot command line.
+ */
+ if (!iint_cache)
+ panic("%s: lsm=integrity required.\n", __func__);
+
iint = integrity_iint_find(inode);
if (iint)
return iint;
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 9e94eca48b89..955e4b4d09e2 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -120,6 +120,7 @@ void ima_add_kexec_buffer(struct kimage *image)
ret = kexec_add_buffer(&kbuf);
if (ret) {
pr_err("Error passing over kexec measurement buffer.\n");
+ vfree(kexec_buffer);
return;
}
@@ -129,6 +130,8 @@ void ima_add_kexec_buffer(struct kimage *image)
return;
}
+ image->ima_buffer = kexec_buffer;
+
pr_debug("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
kbuf.mem);
}
diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c
index 36cadadbfba4..1e5c01916173 100644
--- a/security/integrity/ima/ima_mok.c
+++ b/security/integrity/ima/ima_mok.c
@@ -38,13 +38,12 @@ __init int ima_mok_init(void)
(KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ |
KEY_USR_WRITE | KEY_USR_SEARCH,
- KEY_ALLOC_NOT_IN_QUOTA,
+ KEY_ALLOC_NOT_IN_QUOTA |
+ KEY_ALLOC_SET_KEEP,
restriction, NULL);
if (IS_ERR(ima_blacklist_keyring))
panic("Can't allocate IMA blacklist keyring.");
-
- set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags);
return 0;
}
device_initcall(ima_mok_init);
diff --git a/security/keys/key.c b/security/keys/key.c
index e9845d0d8d34..623fcb4094dd 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -302,6 +302,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_BUILTIN;
if (flags & KEY_ALLOC_UID_KEYRING)
key->flags |= 1 << KEY_FLAG_UID_KEYRING;
+ if (flags & KEY_ALLOC_SET_KEEP)
+ key->flags |= 1 << KEY_FLAG_KEEP;
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 36afc29aecc3..92a14ab82f72 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -805,7 +805,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
case Opt_migratable:
if (*args[0].from == '0')
pay->migratable = 0;
- else
+ else if (*args[0].from != '1')
return -EINVAL;
break;
case Opt_pcrlock:
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 9c4308077574..5e75ff2e1b14 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -1163,7 +1163,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf,
return -EPERM;
if (*ppos != 0)
return -EINVAL;
- if (count < SMK_NETLBLADDRMIN)
+ if (count < SMK_NETLBLADDRMIN || count > PAGE_SIZE - 1)
return -EINVAL;
data = memdup_user_nul(buf, count);
@@ -1423,7 +1423,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf,
return -EPERM;
if (*ppos != 0)
return -EINVAL;
- if (count < SMK_NETLBLADDRMIN)
+ if (count < SMK_NETLBLADDRMIN || count > PAGE_SIZE - 1)
return -EINVAL;
data = memdup_user_nul(buf, count);
@@ -1830,6 +1830,10 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
+ /* Enough data must be present */
+ if (count == 0 || count > PAGE_SIZE)
+ return -EINVAL;
+
data = memdup_user_nul(buf, count);
if (IS_ERR(data))
return PTR_ERR(data);
@@ -2001,6 +2005,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
+ if (count > PAGE_SIZE)
+ return -EINVAL;
+
data = memdup_user_nul(buf, count);
if (IS_ERR(data))
return PTR_ERR(data);
@@ -2088,6 +2095,9 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
+ if (count > PAGE_SIZE)
+ return -EINVAL;
+
data = memdup_user_nul(buf, count);
if (IS_ERR(data))
return PTR_ERR(data);
@@ -2643,6 +2653,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
if (!smack_privileged(CAP_MAC_ADMIN))
return -EPERM;
+ /* Enough data must be present */
+ if (count == 0 || count > PAGE_SIZE)
+ return -EINVAL;
+
data = memdup_user_nul(buf, count);
if (IS_ERR(data))
return PTR_ERR(data);
@@ -2735,10 +2749,13 @@ static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf,
return -EPERM;
/*
+ * No partial write.
* Enough data must be present.
*/
if (*ppos != 0)
return -EINVAL;
+ if (count == 0 || count > PAGE_SIZE)
+ return -EINVAL;
data = memdup_user_nul(buf, count);
if (IS_ERR(data))