summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/Kconfig2
-rw-r--r--security/integrity/digsig_asymmetric.c16
-rw-r--r--security/integrity/iint.c4
-rw-r--r--security/integrity/ima/ima.h49
-rw-r--r--security/integrity/ima/ima_api.c25
-rw-r--r--security/integrity/ima/ima_appraise.c69
-rw-r--r--security/integrity/ima/ima_crypto.c120
-rw-r--r--security/integrity/ima/ima_fs.c53
-rw-r--r--security/integrity/ima/ima_init.c2
-rw-r--r--security/integrity/ima/ima_main.c92
-rw-r--r--security/integrity/ima/ima_policy.c115
-rw-r--r--security/integrity/ima/ima_template.c2
-rw-r--r--security/integrity/ima/ima_template_lib.c1
-rw-r--r--security/integrity/integrity.h17
-rw-r--r--security/keys/big_key.c15
-rw-r--r--security/keys/encrypted-keys/encrypted.c82
-rw-r--r--security/keys/key.c2
-rw-r--r--security/keys/trusted.c11
-rw-r--r--security/security.c34
-rw-r--r--security/selinux/Makefile2
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--security/smack/smack_lsm.c46
22 files changed, 501 insertions, 260 deletions
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 21d756832b75..979be65d22c4 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
+ select CRYPTO_RSA
select X509_CERTIFICATE_PARSER
help
This option enables digital signature verification using
@@ -45,7 +46,6 @@ config INTEGRITY_TRUSTED_KEYRING
bool "Require all keys on the integrity keyrings be signed"
depends on SYSTEM_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
- select KEYS_DEBUG_PROC_KEYS
default y
help
This option requires that all keys added to the .ima and
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index 5ade2a7517a6..80052ed8d467 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -16,6 +16,7 @@
#include <linux/ratelimit.h>
#include <linux/key-type.h>
#include <crypto/public_key.h>
+#include <crypto/hash_info.h>
#include <keys/asymmetric-type.h>
#include <keys/system_keyring.h>
@@ -94,7 +95,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
if (siglen != __be16_to_cpu(hdr->sig_size))
return -EBADMSG;
- if (hdr->hash_algo >= PKEY_HASH__LAST)
+ if (hdr->hash_algo >= HASH_ALGO__LAST)
return -ENOPKG;
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
@@ -103,16 +104,13 @@ int asymmetric_verify(struct key *keyring, const char *sig,
memset(&pks, 0, sizeof(pks));
- pks.pkey_hash_algo = hdr->hash_algo;
+ pks.pkey_algo = "rsa";
+ pks.hash_algo = hash_algo_name[hdr->hash_algo];
pks.digest = (u8 *)data;
pks.digest_size = datalen;
- pks.nr_mpi = 1;
- pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
-
- if (pks.rsa.s)
- ret = verify_signature(key, &pks);
-
- mpi_free(pks.rsa.s);
+ pks.s = hdr->sig;
+ pks.s_size = siglen;
+ ret = verify_signature(key, &pks);
key_put(key);
pr_debug("%s() = %d\n", __func__, ret);
return ret;
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 8f1ab37f2897..345b75997e4c 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -77,7 +77,7 @@ static void iint_free(struct integrity_iint_cache *iint)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
- iint->ima_module_status = INTEGRITY_UNKNOWN;
+ iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
kmem_cache_free(iint_cache, iint);
}
@@ -157,7 +157,7 @@ static void init_once(void *foo)
iint->ima_file_status = INTEGRITY_UNKNOWN;
iint->ima_mmap_status = INTEGRITY_UNKNOWN;
iint->ima_bprm_status = INTEGRITY_UNKNOWN;
- iint->ima_module_status = INTEGRITY_UNKNOWN;
+ iint->ima_read_status = INTEGRITY_UNKNOWN;
iint->evm_status = INTEGRITY_UNKNOWN;
}
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 585af61ed399..5d0f61163d98 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -19,10 +19,12 @@
#include <linux/types.h>
#include <linux/crypto.h>
+#include <linux/fs.h>
#include <linux/security.h>
#include <linux/hash.h>
#include <linux/tpm.h>
#include <linux/audit.h>
+#include <crypto/hash_info.h>
#include "../integrity.h"
@@ -106,6 +108,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
const char *op, struct inode *inode,
const unsigned char *filename);
int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+ struct ima_digest_data *hash);
int ima_calc_field_array_hash(struct ima_field_data *field_data,
struct ima_template_desc *desc, int num_fields,
struct ima_digest_data *hash);
@@ -136,13 +140,25 @@ static inline unsigned long ima_hash_key(u8 *digest)
return hash_long(*digest, IMA_HASH_BITS);
}
+enum ima_hooks {
+ FILE_CHECK = 1,
+ MMAP_CHECK,
+ BPRM_CHECK,
+ POST_SETATTR,
+ MODULE_CHECK,
+ FIRMWARE_CHECK,
+ KEXEC_KERNEL_CHECK,
+ KEXEC_INITRAMFS_CHECK,
+ POLICY_CHECK,
+ MAX_CHECK
+};
+
/* LIM API function definitions */
-int ima_get_action(struct inode *inode, int mask, int function);
-int ima_must_measure(struct inode *inode, int mask, int function);
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func);
+int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
int ima_collect_measurement(struct integrity_iint_cache *iint,
- struct file *file,
- struct evm_ima_xattr_data **xattr_value,
- int *xattr_len);
+ struct file *file, void *buf, loff_t size,
+ enum hash_algo algo);
void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
@@ -157,8 +173,6 @@ void ima_free_template_entry(struct ima_template_entry *entry);
const char *ima_d_path(struct path *path, char **pathbuf);
/* IMA policy related functions */
-enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR };
-
int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
int flags);
void ima_init_policy(void);
@@ -178,23 +192,25 @@ int ima_policy_show(struct seq_file *m, void *v);
#define IMA_APPRAISE_LOG 0x04
#define IMA_APPRAISE_MODULES 0x08
#define IMA_APPRAISE_FIRMWARE 0x10
+#define IMA_APPRAISE_POLICY 0x20
#ifdef CONFIG_IMA_APPRAISE
-int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
+int ima_appraise_measurement(enum ima_hooks func,
+ struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len, int opened);
int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
- int func);
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
- struct ima_digest_data *hash);
+ enum ima_hooks func);
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+ int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value);
#else
-static inline int ima_appraise_measurement(int func,
+static inline int ima_appraise_measurement(enum ima_hooks func,
struct integrity_iint_cache *iint,
struct file *file,
const unsigned char *filename,
@@ -216,15 +232,16 @@ static inline void ima_update_xattr(struct integrity_iint_cache *iint,
}
static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache
- *iint, int func)
+ *iint,
+ enum ima_hooks func)
{
return INTEGRITY_UNKNOWN;
}
-static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
- int xattr_len,
- struct ima_digest_data *hash)
+static inline enum hash_algo
+ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
{
+ return ima_hash_algo;
}
static inline int ima_read_xattr(struct dentry *dentry,
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1d950fbb2aec..370e42dfc5c5 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -18,7 +18,7 @@
#include <linux/fs.h>
#include <linux/xattr.h>
#include <linux/evm.h>
-#include <crypto/hash_info.h>
+
#include "ima.h"
/*
@@ -156,7 +156,7 @@ err_out:
* ima_get_action - appraise & measure decision based on policy.
* @inode: pointer to inode to measure
* @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE)
- * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK)
+ * @func: caller identifier
*
* The policy is defined in terms of keypairs:
* subj=, obj=, type=, func=, mask=, fsmagic=
@@ -168,13 +168,13 @@ err_out:
* Returns IMA_MEASURE, IMA_APPRAISE mask.
*
*/
-int ima_get_action(struct inode *inode, int mask, int function)
+int ima_get_action(struct inode *inode, int mask, enum ima_hooks func)
{
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
flags &= ima_policy_flag;
- return ima_match_policy(inode, function, mask, flags);
+ return ima_match_policy(inode, func, mask, flags);
}
/*
@@ -188,9 +188,8 @@ int ima_get_action(struct inode *inode, int mask, int function)
* Return 0 on success, error code otherwise
*/
int ima_collect_measurement(struct integrity_iint_cache *iint,
- struct file *file,
- struct evm_ima_xattr_data **xattr_value,
- int *xattr_len)
+ struct file *file, void *buf, loff_t size,
+ enum hash_algo algo)
{
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
@@ -201,9 +200,6 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
char digest[IMA_MAX_DIGEST_SIZE];
} hash;
- if (xattr_value)
- *xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value);
-
if (!(iint->flags & IMA_COLLECTED)) {
u64 i_version = file_inode(file)->i_version;
@@ -213,13 +209,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
goto out;
}
- /* use default hash algorithm */
- hash.hdr.algo = ima_hash_algo;
-
- if (xattr_value)
- ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
+ hash.hdr.algo = algo;
- result = ima_calc_file_hash(file, &hash.hdr);
+ result = (!buf) ? ima_calc_file_hash(file, &hash.hdr) :
+ ima_calc_buffer_hash(buf, size, &hash.hdr);
if (!result) {
int length = sizeof(hash.hdr) + hash.hdr.length;
void *tmpbuf = krealloc(iint->ima_hash, length,
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 1873b5536f80..6b4694aedae8 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -15,7 +15,6 @@
#include <linux/magic.h>
#include <linux/ima.h>
#include <linux/evm.h>
-#include <crypto/hash_info.h>
#include "ima.h"
@@ -68,25 +67,25 @@ static int ima_fix_xattr(struct dentry *dentry,
/* Return specific func appraised cached result */
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
- int func)
+ enum ima_hooks func)
{
switch (func) {
case MMAP_CHECK:
return iint->ima_mmap_status;
case BPRM_CHECK:
return iint->ima_bprm_status;
- case MODULE_CHECK:
- return iint->ima_module_status;
- case FIRMWARE_CHECK:
- return iint->ima_firmware_status;
case FILE_CHECK:
- default:
+ case POST_SETATTR:
return iint->ima_file_status;
+ case MODULE_CHECK ... MAX_CHECK - 1:
+ default:
+ return iint->ima_read_status;
}
}
static void ima_set_cache_status(struct integrity_iint_cache *iint,
- int func, enum integrity_status status)
+ enum ima_hooks func,
+ enum integrity_status status)
{
switch (func) {
case MMAP_CHECK:
@@ -95,20 +94,19 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
case BPRM_CHECK:
iint->ima_bprm_status = status;
break;
- case MODULE_CHECK:
- iint->ima_module_status = status;
- break;
- case FIRMWARE_CHECK:
- iint->ima_firmware_status = status;
- break;
case FILE_CHECK:
- default:
+ case POST_SETATTR:
iint->ima_file_status = status;
break;
+ case MODULE_CHECK ... MAX_CHECK - 1:
+ default:
+ iint->ima_read_status = status;
+ break;
}
}
-static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
+static void ima_cache_flags(struct integrity_iint_cache *iint,
+ enum ima_hooks func)
{
switch (func) {
case MMAP_CHECK:
@@ -117,49 +115,51 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
case BPRM_CHECK:
iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED);
break;
- case MODULE_CHECK:
- iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED);
- break;
- case FIRMWARE_CHECK:
- iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED);
- break;
case FILE_CHECK:
- default:
+ case POST_SETATTR:
iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED);
break;
+ case MODULE_CHECK ... MAX_CHECK - 1:
+ default:
+ iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED);
+ break;
}
}
-void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
- struct ima_digest_data *hash)
+enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+ int xattr_len)
{
struct signature_v2_hdr *sig;
if (!xattr_value || xattr_len < 2)
- return;
+ /* return default hash algo */
+ return ima_hash_algo;
switch (xattr_value->type) {
case EVM_IMA_XATTR_DIGSIG:
sig = (typeof(sig))xattr_value;
if (sig->version != 2 || xattr_len <= sizeof(*sig))
- return;
- hash->algo = sig->hash_algo;
+ return ima_hash_algo;
+ return sig->hash_algo;
break;
case IMA_XATTR_DIGEST_NG:
- hash->algo = xattr_value->digest[0];
+ return xattr_value->digest[0];
break;
case IMA_XATTR_DIGEST:
/* this is for backward compatibility */
if (xattr_len == 21) {
unsigned int zero = 0;
if (!memcmp(&xattr_value->digest[16], &zero, 4))
- hash->algo = HASH_ALGO_MD5;
+ return HASH_ALGO_MD5;
else
- hash->algo = HASH_ALGO_SHA1;
+ return HASH_ALGO_SHA1;
} else if (xattr_len == 17)
- hash->algo = HASH_ALGO_MD5;
+ return HASH_ALGO_MD5;
break;
}
+
+ /* return default hash algo */
+ return ima_hash_algo;
}
int ima_read_xattr(struct dentry *dentry,
@@ -182,7 +182,8 @@ int ima_read_xattr(struct dentry *dentry,
*
* Return 0 on success, error code otherwise
*/
-int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
+int ima_appraise_measurement(enum ima_hooks func,
+ struct integrity_iint_cache *iint,
struct file *file, const unsigned char *filename,
struct evm_ima_xattr_data *xattr_value,
int xattr_len, int opened)
@@ -296,7 +297,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
if (iint->flags & IMA_DIGSIG)
return;
- rc = ima_collect_measurement(iint, file, NULL, NULL);
+ rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo);
if (rc < 0)
return;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 6eb62936c672..38f2ed830dd6 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -24,7 +24,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <crypto/hash.h>
-#include <crypto/hash_info.h>
+
#include "ima.h"
struct ahash_completion {
@@ -519,6 +519,124 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
return rc;
}
+static int calc_buffer_ahash_atfm(const void *buf, loff_t len,
+ struct ima_digest_data *hash,
+ struct crypto_ahash *tfm)
+{
+ struct ahash_request *req;
+ struct scatterlist sg;
+ struct ahash_completion res;
+ int rc, ahash_rc = 0;
+
+ hash->length = crypto_ahash_digestsize(tfm);
+
+ req = ahash_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ init_completion(&res.completion);
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP,
+ ahash_complete, &res);
+
+ rc = ahash_wait(crypto_ahash_init(req), &res);
+ if (rc)
+ goto out;
+
+ sg_init_one(&sg, buf, len);
+ ahash_request_set_crypt(req, &sg, NULL, len);
+
+ ahash_rc = crypto_ahash_update(req);
+
+ /* wait for the update request to complete */
+ rc = ahash_wait(ahash_rc, &res);
+ if (!rc) {
+ ahash_request_set_crypt(req, NULL, hash->digest, 0);
+ rc = ahash_wait(crypto_ahash_final(req), &res);
+ }
+out:
+ ahash_request_free(req);
+ return rc;
+}
+
+static int calc_buffer_ahash(const void *buf, loff_t len,
+ struct ima_digest_data *hash)
+{
+ struct crypto_ahash *tfm;
+ int rc;
+
+ tfm = ima_alloc_atfm(hash->algo);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ rc = calc_buffer_ahash_atfm(buf, len, hash, tfm);
+
+ ima_free_atfm(tfm);
+
+ return rc;
+}
+
+static int calc_buffer_shash_tfm(const void *buf, loff_t size,
+ struct ima_digest_data *hash,
+ struct crypto_shash *tfm)
+{
+ SHASH_DESC_ON_STACK(shash, tfm);
+ unsigned int len;
+ int rc;
+
+ shash->tfm = tfm;
+ shash->flags = 0;
+
+ hash->length = crypto_shash_digestsize(tfm);
+
+ rc = crypto_shash_init(shash);
+ if (rc != 0)
+ return rc;
+
+ while (size) {
+ len = size < PAGE_SIZE ? size : PAGE_SIZE;
+ rc = crypto_shash_update(shash, buf, len);
+ if (rc)
+ break;
+ buf += len;
+ size -= len;
+ }
+
+ if (!rc)
+ rc = crypto_shash_final(shash, hash->digest);
+ return rc;
+}
+
+static int calc_buffer_shash(const void *buf, loff_t len,
+ struct ima_digest_data *hash)
+{
+ struct crypto_shash *tfm;
+ int rc;
+
+ tfm = ima_alloc_tfm(hash->algo);
+ if (IS_ERR(tfm))
+ return PTR_ERR(tfm);
+
+ rc = calc_buffer_shash_tfm(buf, len, hash, tfm);
+
+ ima_free_tfm(tfm);
+ return rc;
+}
+
+int ima_calc_buffer_hash(const void *buf, loff_t len,
+ struct ima_digest_data *hash)
+{
+ int rc;
+
+ if (ima_ahash_minsize && len >= ima_ahash_minsize) {
+ rc = calc_buffer_ahash(buf, len, hash);
+ if (!rc)
+ return 0;
+ }
+
+ return calc_buffer_shash(buf, len, hash);
+}
+
static void __init ima_pcrread(int idx, u8 *pcr)
{
if (!ima_used_chip)
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index f355231997b4..60d011aaec38 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -22,6 +22,7 @@
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/parser.h>
+#include <linux/vmalloc.h>
#include "ima.h"
@@ -258,6 +259,43 @@ static const struct file_operations ima_ascii_measurements_ops = {
.release = seq_release,
};
+static ssize_t ima_read_policy(char *path)
+{
+ void *data;
+ char *datap;
+ loff_t size;
+ int rc, pathlen = strlen(path);
+
+ char *p;
+
+ /* remove \n */
+ datap = path;
+ strsep(&datap, "\n");
+
+ rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY);
+ if (rc < 0) {
+ pr_err("Unable to open file: %s (%d)", path, rc);
+ return rc;
+ }
+
+ datap = data;
+ while (size > 0 && (p = strsep(&datap, "\n"))) {
+ pr_debug("rule: %s\n", p);
+ rc = ima_parse_add_rule(p);
+ if (rc < 0)
+ break;
+ size -= rc;
+ }
+
+ vfree(data);
+ if (rc < 0)
+ return rc;
+ else if (size)
+ return -EINVAL;
+ else
+ return pathlen;
+}
+
static ssize_t ima_write_policy(struct file *file, const char __user *buf,
size_t datalen, loff_t *ppos)
{
@@ -286,9 +324,20 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
result = mutex_lock_interruptible(&ima_write_mutex);
if (result < 0)
goto out_free;
- result = ima_parse_add_rule(data);
- mutex_unlock(&ima_write_mutex);
+ if (data[0] == '/') {
+ result = ima_read_policy(data);
+ } else if (ima_appraise & IMA_APPRAISE_POLICY) {
+ pr_err("IMA: signed policy file (specified as an absolute pathname) required\n");
+ integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
+ "policy_update", "signed policy required",
+ 1, 0);
+ if (ima_appraise & IMA_APPRAISE_ENFORCE)
+ result = -EACCES;
+ } else {
+ result = ima_parse_add_rule(data);
+ }
+ mutex_unlock(&ima_write_mutex);
out_free:
kfree(data);
out:
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index bd79f254d204..5d679a685616 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -21,7 +21,7 @@
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/err.h>
-#include <crypto/hash_info.h>
+
#include "ima.h"
/* name for boot aggregate entry */
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 9d96551d0196..391f41751021 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -24,7 +24,6 @@
#include <linux/slab.h>
#include <linux/xattr.h>
#include <linux/ima.h>
-#include <crypto/hash_info.h>
#include "ima.h"
@@ -154,8 +153,8 @@ void ima_file_free(struct file *file)
ima_check_last_writer(iint, inode, file);
}
-static int process_measurement(struct file *file, int mask, int function,
- int opened)
+static int process_measurement(struct file *file, char *buf, loff_t size,
+ int mask, enum ima_hooks func, int opened)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint = NULL;
@@ -163,9 +162,10 @@ static int process_measurement(struct file *file, int mask, int function,
char *pathbuf = NULL;
const char *pathname = NULL;
int rc = -ENOMEM, action, must_appraise;
- struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
+ struct evm_ima_xattr_data *xattr_value = NULL;
int xattr_len = 0;
bool violation_check;
+ enum hash_algo hash_algo;
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
return 0;
@@ -174,8 +174,8 @@ static int process_measurement(struct file *file, int mask, int function,
* bitmask based on the appraise/audit/measurement policy.
* Included is the appraise submask.
*/
- action = ima_get_action(inode, mask, function);
- violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) &&
+ action = ima_get_action(inode, mask, func);
+ violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE));
if (!action && !violation_check)
return 0;
@@ -184,7 +184,7 @@ static int process_measurement(struct file *file, int mask, int function,
/* Is the appraise rule hook specific? */
if (action & IMA_FILE_APPRAISE)
- function = FILE_CHECK;
+ func = FILE_CHECK;
inode_lock(inode);
@@ -214,16 +214,19 @@ static int process_measurement(struct file *file, int mask, int function,
/* Nothing to do, just return existing appraised status */
if (!action) {
if (must_appraise)
- rc = ima_get_cache_status(iint, function);
+ rc = ima_get_cache_status(iint, func);
goto out_digsig;
}
template_desc = ima_template_desc_current();
if ((action & IMA_APPRAISE_SUBMASK) ||
strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
- xattr_ptr = &xattr_value;
+ /* read 'security.ima' */
+ xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
- rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
+ hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
+
+ rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
if (rc != 0) {
if (file->f_flags & O_DIRECT)
rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
@@ -237,7 +240,7 @@ static int process_measurement(struct file *file, int mask, int function,
ima_store_measurement(iint, file, pathname,
xattr_value, xattr_len);
if (action & IMA_APPRAISE_SUBMASK)
- rc = ima_appraise_measurement(function, iint, file, pathname,
+ rc = ima_appraise_measurement(func, iint, file, pathname,
xattr_value, xattr_len, opened);
if (action & IMA_AUDIT)
ima_audit_measurement(iint, pathname);
@@ -270,7 +273,8 @@ out:
int ima_file_mmap(struct file *file, unsigned long prot)
{
if (file && (prot & PROT_EXEC))
- return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0);
+ return process_measurement(file, NULL, 0, MAY_EXEC,
+ MMAP_CHECK, 0);
return 0;
}
@@ -289,7 +293,8 @@ int ima_file_mmap(struct file *file, unsigned long prot)
*/
int ima_bprm_check(struct linux_binprm *bprm)
{
- return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0);
+ return process_measurement(bprm->file, NULL, 0, MAY_EXEC,
+ BPRM_CHECK, 0);
}
/**
@@ -304,24 +309,26 @@ int ima_bprm_check(struct linux_binprm *bprm)
*/
int ima_file_check(struct file *file, int mask, int opened)
{
- return process_measurement(file,
+ return process_measurement(file, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
FILE_CHECK, opened);
}
EXPORT_SYMBOL_GPL(ima_file_check);
/**
- * ima_module_check - based on policy, collect/store/appraise measurement.
- * @file: pointer to the file to be measured/appraised
+ * ima_read_file - pre-measure/appraise hook decision based on policy
+ * @file: pointer to the file to be measured/appraised/audit
+ * @read_id: caller identifier
*
- * Measure/appraise kernel modules based on policy.
+ * Permit reading a file based on policy. The policy rules are written
+ * in terms of the policy identifier. Appraising the integrity of
+ * a file requires a file descriptor.
*
- * On success return 0. On integrity appraisal error, assuming the file
- * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
+ * For permission return 0, otherwise return -EACCES.
*/
-int ima_module_check(struct file *file)
+int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
{
- if (!file) {
+ if (!file && read_id == READING_MODULE) {
#ifndef CONFIG_MODULE_SIG_FORCE
if ((ima_appraise & IMA_APPRAISE_MODULES) &&
(ima_appraise & IMA_APPRAISE_ENFORCE))
@@ -329,18 +336,53 @@ int ima_module_check(struct file *file)
#endif
return 0; /* We rely on module signature checking */
}
- return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0);
+ return 0;
}
-int ima_fw_from_file(struct file *file, char *buf, size_t size)
+static int read_idmap[READING_MAX_ID] = {
+ [READING_FIRMWARE] = FIRMWARE_CHECK,
+ [READING_MODULE] = MODULE_CHECK,
+ [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
+ [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
+ [READING_POLICY] = POLICY_CHECK
+};
+
+/**
+ * ima_post_read_file - in memory collect/appraise/audit measurement
+ * @file: pointer to the file to be measured/appraised/audit
+ * @buf: pointer to in memory file contents
+ * @size: size of in memory file contents
+ * @read_id: caller identifier
+ *
+ * Measure/appraise/audit in memory file based on policy. Policy rules
+ * are written in terms of a policy identifier.
+ *
+ * On success return 0. On integrity appraisal error, assuming the file
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
+ */
+int ima_post_read_file(struct file *file, void *buf, loff_t size,
+ enum kernel_read_file_id read_id)
{
- if (!file) {
+ enum ima_hooks func;
+
+ if (!file && read_id == READING_FIRMWARE) {
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
(ima_appraise & IMA_APPRAISE_ENFORCE))
return -EACCES; /* INTEGRITY_UNKNOWN */
return 0;
}
- return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0);
+
+ if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
+ return 0;
+
+ if (!file || !buf || size == 0) { /* should never happen */
+ if (ima_appraise & IMA_APPRAISE_ENFORCE)
+ return -EACCES;
+ return 0;
+ }
+
+ func = read_idmap[read_id] ?: FILE_CHECK;
+ return process_measurement(file, buf, size, MAY_READ, func, 0);
}
static int __init init_ima(void)
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 0a3b781f18e5..be09e2cacf82 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -12,6 +12,7 @@
*/
#include <linux/module.h>
#include <linux/list.h>
+#include <linux/fs.h>
#include <linux/security.h>
#include <linux/magic.h>
#include <linux/parser.h>
@@ -113,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = {
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID},
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
+ {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
};
static struct ima_rule_entry default_appraise_rules[] = {
@@ -127,6 +129,10 @@ static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+#ifdef CONFIG_IMA_WRITE_POLICY
+ {.action = APPRAISE, .func = POLICY_CHECK,
+ .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
+#endif
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
#else
@@ -207,8 +213,8 @@ static void ima_lsm_update_rules(void)
*
* Returns true on rule match, false on failure.
*/
-static bool ima_match_rules(struct ima_rule_entry *rule,
- struct inode *inode, enum ima_hooks func, int mask)
+static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
+ enum ima_hooks func, int mask)
{
struct task_struct *tsk = current;
const struct cred *cred = current_cred();
@@ -289,7 +295,7 @@ retry:
* In addition to knowing that we need to appraise the file in general,
* we need to differentiate between calling hooks, for hook specific rules.
*/
-static int get_subaction(struct ima_rule_entry *rule, int func)
+static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
{
if (!(rule->flags & IMA_FUNC))
return IMA_FILE_APPRAISE;
@@ -299,13 +305,12 @@ static int get_subaction(struct ima_rule_entry *rule, int func)
return IMA_MMAP_APPRAISE;
case BPRM_CHECK:
return IMA_BPRM_APPRAISE;
- case MODULE_CHECK:
- return IMA_MODULE_APPRAISE;
- case FIRMWARE_CHECK:
- return IMA_FIRMWARE_APPRAISE;
case FILE_CHECK:
- default:
+ case POST_SETATTR:
return IMA_FILE_APPRAISE;
+ case MODULE_CHECK ... MAX_CHECK - 1:
+ default:
+ return IMA_READ_APPRAISE;
}
}
@@ -411,13 +416,16 @@ void __init ima_init_policy(void)
for (i = 0; i < appraise_entries; i++) {
list_add_tail(&default_appraise_rules[i].list,
&ima_default_rules);
+ if (default_appraise_rules[i].func == POLICY_CHECK)
+ temp_ima_appraise |= IMA_APPRAISE_POLICY;
}
ima_rules = &ima_default_rules;
+ ima_update_policy_flag();
}
/* Make sure we have a valid policy, at least containing some rules. */
-int ima_check_policy()
+int ima_check_policy(void)
{
if (list_empty(&ima_temp_rules))
return -EINVAL;
@@ -612,6 +620,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
entry->func = MMAP_CHECK;
else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
entry->func = BPRM_CHECK;
+ else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") ==
+ 0)
+ entry->func = KEXEC_KERNEL_CHECK;
+ else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK")
+ == 0)
+ entry->func = KEXEC_INITRAMFS_CHECK;
+ else if (strcmp(args[0].from, "POLICY_CHECK") == 0)
+ entry->func = POLICY_CHECK;
else
result = -EINVAL;
if (!result)
@@ -770,6 +786,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
temp_ima_appraise |= IMA_APPRAISE_MODULES;
else if (entry->func == FIRMWARE_CHECK)
temp_ima_appraise |= IMA_APPRAISE_FIRMWARE;
+ else if (entry->func == POLICY_CHECK)
+ temp_ima_appraise |= IMA_APPRAISE_POLICY;
audit_log_format(ab, "res=%d", !result);
audit_log_end(ab);
return result;
@@ -855,7 +873,9 @@ static char *mask_tokens[] = {
enum {
func_file = 0, func_mmap, func_bprm,
- func_module, func_firmware, func_post
+ func_module, func_firmware, func_post,
+ func_kexec_kernel, func_kexec_initramfs,
+ func_policy
};
static char *func_tokens[] = {
@@ -864,6 +884,9 @@ static char *func_tokens[] = {
"BPRM_CHECK",
"MODULE_CHECK",
"FIRMWARE_CHECK",
+ "KEXEC_KERNEL_CHECK",
+ "KEXEC_INITRAMFS_CHECK",
+ "POLICY_CHECK",
"POST_SETATTR"
};
@@ -903,6 +926,49 @@ void ima_policy_stop(struct seq_file *m, void *v)
#define mt(token) mask_tokens[token]
#define ft(token) func_tokens[token]
+/*
+ * policy_func_show - display the ima_hooks policy rule
+ */
+static void policy_func_show(struct seq_file *m, enum ima_hooks func)
+{
+ char tbuf[64] = {0,};
+
+ switch (func) {
+ case FILE_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_file));
+ break;
+ case MMAP_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_mmap));
+ break;
+ case BPRM_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_bprm));
+ break;
+ case MODULE_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_module));
+ break;
+ case FIRMWARE_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_firmware));
+ break;
+ case POST_SETATTR:
+ seq_printf(m, pt(Opt_func), ft(func_post));
+ break;
+ case KEXEC_KERNEL_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
+ break;
+ case KEXEC_INITRAMFS_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
+ break;
+ case POLICY_CHECK:
+ seq_printf(m, pt(Opt_func), ft(func_policy));
+ break;
+ default:
+ snprintf(tbuf, sizeof(tbuf), "%d", func);
+ seq_printf(m, pt(Opt_func), tbuf);
+ break;
+ }
+ seq_puts(m, " ");
+}
+
int ima_policy_show(struct seq_file *m, void *v)
{
struct ima_rule_entry *entry = v;
@@ -924,33 +990,8 @@ int ima_policy_show(struct seq_file *m, void *v)
seq_puts(m, " ");
- if (entry->flags & IMA_FUNC) {
- switch (entry->func) {
- case FILE_CHECK:
- seq_printf(m, pt(Opt_func), ft(func_file));
- break;
- case MMAP_CHECK:
- seq_printf(m, pt(Opt_func), ft(func_mmap));
- break;
- case BPRM_CHECK:
- seq_printf(m, pt(Opt_func), ft(func_bprm));
- break;
- case MODULE_CHECK:
- seq_printf(m, pt(Opt_func), ft(func_module));
- break;
- case FIRMWARE_CHECK:
- seq_printf(m, pt(Opt_func), ft(func_firmware));
- break;
- case POST_SETATTR:
- seq_printf(m, pt(Opt_func), ft(func_post));
- break;
- default:
- snprintf(tbuf, sizeof(tbuf), "%d", entry->func);
- seq_printf(m, pt(Opt_func), tbuf);
- break;
- }
- seq_puts(m, " ");
- }
+ if (entry->flags & IMA_FUNC)
+ policy_func_show(m, entry->func);
if (entry->flags & IMA_MASK) {
if (entry->mask & MAY_EXEC)
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 0b7404ebfa80..febd12ed9b55 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -15,8 +15,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <crypto/hash_info.h>
-
#include "ima.h"
#include "ima_template_lib.h"
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 2934e3d377f1..f9bae04ba176 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -12,7 +12,6 @@
* File: ima_template_lib.c
* Library of supported template fields.
*/
-#include <crypto/hash_info.h>
#include "ima_template_lib.h"
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 5efe2ecc538d..e08935cf343f 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -45,16 +45,12 @@
#define IMA_MMAP_APPRAISED 0x00000800
#define IMA_BPRM_APPRAISE 0x00001000
#define IMA_BPRM_APPRAISED 0x00002000
-#define IMA_MODULE_APPRAISE 0x00004000
-#define IMA_MODULE_APPRAISED 0x00008000
-#define IMA_FIRMWARE_APPRAISE 0x00010000
-#define IMA_FIRMWARE_APPRAISED 0x00020000
+#define IMA_READ_APPRAISE 0x00004000
+#define IMA_READ_APPRAISED 0x00008000
#define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \
- IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \
- IMA_FIRMWARE_APPRAISE)
+ IMA_BPRM_APPRAISE | IMA_READ_APPRAISE)
#define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \
- IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \
- IMA_FIRMWARE_APPRAISED)
+ IMA_BPRM_APPRAISED | IMA_READ_APPRAISED)
enum evm_ima_xattr_type {
IMA_XATTR_DIGEST = 0x01,
@@ -94,7 +90,7 @@ struct ima_digest_data {
struct signature_v2_hdr {
uint8_t type; /* xattr type */
uint8_t version; /* signature format version */
- uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
+ uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific */
uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */
@@ -109,8 +105,7 @@ struct integrity_iint_cache {
enum integrity_status ima_file_status:4;
enum integrity_status ima_mmap_status:4;
enum integrity_status ima_bprm_status:4;
- enum integrity_status ima_module_status:4;
- enum integrity_status ima_firmware_status:4;
+ enum integrity_status ima_read_status:4;
enum integrity_status evm_status:4;
struct ima_digest_data *ima_hash;
};
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index 907c1522ee46..c721e398893a 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -9,7 +9,6 @@
* 2 of the Licence, or (at your option) any later version.
*/
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/file.h>
@@ -18,8 +17,6 @@
#include <keys/user-type.h>
#include <keys/big_key-type.h>
-MODULE_LICENSE("GPL");
-
/*
* Layout of key payload words.
*/
@@ -212,18 +209,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
return ret;
}
-/*
- * Module stuff
- */
static int __init big_key_init(void)
{
return register_key_type(&key_type_big_key);
}
-
-static void __exit big_key_cleanup(void)
-{
- unregister_key_type(&key_type_big_key);
-}
-
-module_init(big_key_init);
-module_exit(big_key_cleanup);
+device_initcall(big_key_init);
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c
index 696ccfa08d10..5adbfc32242f 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -28,11 +28,10 @@
#include <linux/random.h>
#include <linux/rcupdate.h>
#include <linux/scatterlist.h>
-#include <linux/crypto.h>
#include <linux/ctype.h>
#include <crypto/hash.h>
#include <crypto/sha.h>
-#include <crypto/aes.h>
+#include <crypto/skcipher.h>
#include "encrypted.h"
#include "ecryptfs_format.h"
@@ -85,17 +84,17 @@ static const match_table_t key_tokens = {
static int aes_get_sizes(void)
{
- struct crypto_blkcipher *tfm;
+ struct crypto_skcipher *tfm;
- tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
+ tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm)) {
pr_err("encrypted_key: failed to alloc_cipher (%ld)\n",
PTR_ERR(tfm));
return PTR_ERR(tfm);
}
- ivsize = crypto_blkcipher_ivsize(tfm);
- blksize = crypto_blkcipher_blocksize(tfm);
- crypto_free_blkcipher(tfm);
+ ivsize = crypto_skcipher_ivsize(tfm);
+ blksize = crypto_skcipher_blocksize(tfm);
+ crypto_free_skcipher(tfm);
return 0;
}
@@ -401,28 +400,37 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,
return ret;
}
-static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key,
- unsigned int key_len, const u8 *iv,
- unsigned int ivsize)
+static struct skcipher_request *init_skcipher_req(const u8 *key,
+ unsigned int key_len)
{
+ struct skcipher_request *req;
+ struct crypto_skcipher *tfm;
int ret;
- desc->tfm = crypto_alloc_blkcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(desc->tfm)) {
+ tfm = crypto_alloc_skcipher(blkcipher_alg, 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(tfm)) {
pr_err("encrypted_key: failed to load %s transform (%ld)\n",
- blkcipher_alg, PTR_ERR(desc->tfm));
- return PTR_ERR(desc->tfm);
+ blkcipher_alg, PTR_ERR(tfm));
+ return ERR_CAST(tfm);
}
- desc->flags = 0;
- ret = crypto_blkcipher_setkey(desc->tfm, key, key_len);
+ ret = crypto_skcipher_setkey(tfm, key, key_len);
if (ret < 0) {
pr_err("encrypted_key: failed to setkey (%d)\n", ret);
- crypto_free_blkcipher(desc->tfm);
- return ret;
+ crypto_free_skcipher(tfm);
+ return ERR_PTR(ret);
}
- crypto_blkcipher_set_iv(desc->tfm, iv, ivsize);
- return 0;
+
+ req = skcipher_request_alloc(tfm, GFP_KERNEL);
+ if (!req) {
+ pr_err("encrypted_key: failed to allocate request for %s\n",
+ blkcipher_alg);
+ crypto_free_skcipher(tfm);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ skcipher_request_set_callback(req, 0, NULL, NULL);
+ return req;
}
static struct key *request_master_key(struct encrypted_key_payload *epayload,
@@ -467,7 +475,8 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
{
struct scatterlist sg_in[2];
struct scatterlist sg_out[1];
- struct blkcipher_desc desc;
+ struct crypto_skcipher *tfm;
+ struct skcipher_request *req;
unsigned int encrypted_datalen;
unsigned int padlen;
char pad[16];
@@ -476,9 +485,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
padlen = encrypted_datalen - epayload->decrypted_datalen;
- ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
- epayload->iv, ivsize);
- if (ret < 0)
+ req = init_skcipher_req(derived_key, derived_keylen);
+ ret = PTR_ERR(req);
+ if (IS_ERR(req))
goto out;
dump_decrypted_data(epayload);
@@ -491,8 +500,12 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,
sg_init_table(sg_out, 1);
sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
- ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in, encrypted_datalen);
- crypto_free_blkcipher(desc.tfm);
+ skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
+ epayload->iv);
+ ret = crypto_skcipher_encrypt(req);
+ tfm = crypto_skcipher_reqtfm(req);
+ skcipher_request_free(req);
+ crypto_free_skcipher(tfm);
if (ret < 0)
pr_err("encrypted_key: failed to encrypt (%d)\n", ret);
else
@@ -565,15 +578,16 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
{
struct scatterlist sg_in[1];
struct scatterlist sg_out[2];
- struct blkcipher_desc desc;
+ struct crypto_skcipher *tfm;
+ struct skcipher_request *req;
unsigned int encrypted_datalen;
char pad[16];
int ret;
encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
- ret = init_blkcipher_desc(&desc, derived_key, derived_keylen,
- epayload->iv, ivsize);
- if (ret < 0)
+ req = init_skcipher_req(derived_key, derived_keylen);
+ ret = PTR_ERR(req);
+ if (IS_ERR(req))
goto out;
dump_encrypted_data(epayload, encrypted_datalen);
@@ -585,8 +599,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,
epayload->decrypted_datalen);
sg_set_buf(&sg_out[1], pad, sizeof pad);
- ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, encrypted_datalen);
- crypto_free_blkcipher(desc.tfm);
+ skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
+ epayload->iv);
+ ret = crypto_skcipher_decrypt(req);
+ tfm = crypto_skcipher_reqtfm(req);
+ skcipher_request_free(req);
+ crypto_free_skcipher(tfm);
if (ret < 0)
goto out;
dump_decrypted_data(epayload);
diff --git a/security/keys/key.c b/security/keys/key.c
index 09ef276c4bdc..b28755131687 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_TRUSTED)
key->flags |= 1 << KEY_FLAG_TRUSTED;
+ if (flags & KEY_ALLOC_BUILT_IN)
+ key->flags |= 1 << KEY_FLAG_BUILTIN;
#ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC;
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 0dcab20cdacd..90d61751ff12 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -744,6 +744,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
unsigned long handle;
unsigned long lock;
unsigned long token_mask = 0;
+ unsigned int digest_len;
int i;
int tpm2;
@@ -752,7 +753,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
return tpm2;
opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
- opt->digest_len = hash_digest_size[opt->hash];
while ((p = strsep(&c, " \t"))) {
if (*p == '\0' || *p == ' ' || *p == '\t')
@@ -812,8 +812,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
for (i = 0; i < HASH_ALGO__LAST; i++) {
if (!strcmp(args[0].from, hash_algo_name[i])) {
opt->hash = i;
- opt->digest_len =
- hash_digest_size[opt->hash];
break;
}
}
@@ -825,13 +823,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
}
break;
case Opt_policydigest:
- if (!tpm2 ||
- strlen(args[0].from) != (2 * opt->digest_len))
+ digest_len = hash_digest_size[opt->hash];
+ if (!tpm2 || strlen(args[0].from) != (2 * digest_len))
return -EINVAL;
res = hex2bin(opt->policydigest, args[0].from,
- opt->digest_len);
+ digest_len);
if (res < 0)
return -EINVAL;
+ opt->policydigest_len = digest_len;
break;
case Opt_policyhandle:
if (!tpm2)
diff --git a/security/security.c b/security/security.c
index e8ffd92ae2eb..3644b0344d29 100644
--- a/security/security.c
+++ b/security/security.c
@@ -884,31 +884,33 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)
return call_int_hook(kernel_create_files_as, 0, new, inode);
}
-int security_kernel_fw_from_file(struct file *file, char *buf, size_t size)
+int security_kernel_module_request(char *kmod_name)
+{
+ return call_int_hook(kernel_module_request, 0, kmod_name);
+}
+
+int security_kernel_read_file(struct file *file, enum kernel_read_file_id id)
{
int ret;
- ret = call_int_hook(kernel_fw_from_file, 0, file, buf, size);
+ ret = call_int_hook(kernel_read_file, 0, file, id);
if (ret)
return ret;
- return ima_fw_from_file(file, buf, size);
-}
-EXPORT_SYMBOL_GPL(security_kernel_fw_from_file);
-
-int security_kernel_module_request(char *kmod_name)
-{
- return call_int_hook(kernel_module_request, 0, kmod_name);
+ return ima_read_file(file, id);
}
+EXPORT_SYMBOL_GPL(security_kernel_read_file);
-int security_kernel_module_from_file(struct file *file)
+int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
+ enum kernel_read_file_id id)
{
int ret;
- ret = call_int_hook(kernel_module_from_file, 0, file);
+ ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id);
if (ret)
return ret;
- return ima_module_check(file);
+ return ima_post_read_file(file, buf, size, id);
}
+EXPORT_SYMBOL_GPL(security_kernel_post_read_file);
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
@@ -1691,12 +1693,12 @@ struct security_hook_heads security_hook_heads = {
LIST_HEAD_INIT(security_hook_heads.kernel_act_as),
.kernel_create_files_as =
LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as),
- .kernel_fw_from_file =
- LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file),
.kernel_module_request =
LIST_HEAD_INIT(security_hook_heads.kernel_module_request),
- .kernel_module_from_file =
- LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file),
+ .kernel_read_file =
+ LIST_HEAD_INIT(security_hook_heads.kernel_read_file),
+ .kernel_post_read_file =
+ LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file),
.task_fix_setuid =
LIST_HEAD_INIT(security_hook_heads.task_fix_setuid),
.task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid),
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index ad5cd76ec231..3411c33e2a44 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -13,7 +13,7 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
selinux-$(CONFIG_NETLABEL) += netlabel.o
-ccflags-y := -Isecurity/selinux -Isecurity/selinux/include
+ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include
$(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8010bc5391c3..912deee3f01e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3249,7 +3249,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
static void selinux_inode_getsecid(struct inode *inode, u32 *secid)
{
- struct inode_security_struct *isec = inode_security(inode);
+ struct inode_security_struct *isec = inode_security_novalidate(inode);
*secid = isec->sid;
}
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 2d6e9bdea398..11f79013ae1f 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1442,9 +1442,13 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
* Don't do anything special for these.
* XATTR_NAME_SMACKIPIN
* XATTR_NAME_SMACKIPOUT
- * XATTR_NAME_SMACKEXEC
*/
- if (strcmp(name, XATTR_NAME_SMACK) == 0)
+ if (strcmp(name, XATTR_NAME_SMACK) == 0) {
+ struct super_block *sbp = d_backing_inode(dentry)->i_sb;
+ struct superblock_smack *sbsp = sbp->s_security;
+
+ isp->smk_inode = sbsp->smk_default;
+ } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0)
isp->smk_task = NULL;
else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0)
isp->smk_mmap = NULL;
@@ -1545,12 +1549,8 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid)
* File Hooks
*/
-/**
- * smack_file_permission - Smack check on file operations
- * @file: unused
- * @mask: unused
- *
- * Returns 0
+/*
+ * There is no smack_file_permission hook
*
* Should access checks be done on each read or write?
* UNICOS and SELinux say yes.
@@ -1559,10 +1559,6 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid)
* I'll say no for now. Smack does not do the frequent
* label changing that SELinux does.
*/
-static int smack_file_permission(struct file *file, int mask)
-{
- return 0;
-}
/**
* smack_file_alloc_security - assign a file security blob
@@ -4503,16 +4499,10 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule,
return 0;
}
-/**
- * smack_audit_rule_free - free smack rule representation
- * @vrule: rule to be freed.
- *
+/*
+ * There is no need for a smack_audit_rule_free hook.
* No memory was allocated.
*/
-static void smack_audit_rule_free(void *vrule)
-{
- /* No-op */
-}
#endif /* CONFIG_AUDIT */
@@ -4563,16 +4553,11 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
return 0;
}
-/**
- * smack_release_secctx - don't do anything.
- * @secdata: unused
- * @seclen: unused
- *
- * Exists to make sure nothing gets done, and properly
+/*
+ * There used to be a smack_release_secctx hook
+ * that did nothing back when hooks were in a vector.
+ * Now that there's a list such a hook adds cost.
*/
-static void smack_release_secctx(char *secdata, u32 seclen)
-{
-}
static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
@@ -4631,7 +4616,6 @@ static struct security_hook_list smack_hooks[] = {
LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity),
LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid),
- LSM_HOOK_INIT(file_permission, smack_file_permission),
LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security),
LSM_HOOK_INIT(file_free_security, smack_file_free_security),
LSM_HOOK_INIT(file_ioctl, smack_file_ioctl),
@@ -4726,13 +4710,11 @@ static struct security_hook_list smack_hooks[] = {
LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init),
LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known),
LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match),
- LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free),
#endif /* CONFIG_AUDIT */
LSM_HOOK_INIT(ismaclabel, smack_ismaclabel),
LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx),
LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid),
- LSM_HOOK_INIT(release_secctx, smack_release_secctx),
LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx),
LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx),
LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx),