Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
This commit is contained in:
commit
a6aacbde40
|
@ -1330,6 +1330,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||||
Formats: { "ima" | "ima-ng" }
|
Formats: { "ima" | "ima-ng" }
|
||||||
Default: "ima-ng"
|
Default: "ima-ng"
|
||||||
|
|
||||||
|
ima_template_fmt=
|
||||||
|
[IMA] Define a custom template format.
|
||||||
|
Format: { "field1|...|fieldN" }
|
||||||
|
|
||||||
ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
|
ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
|
||||||
Format: <min_file_size>
|
Format: <min_file_size>
|
||||||
Set the minimal file size for using asynchronous hash.
|
Set the minimal file size for using asynchronous hash.
|
||||||
|
|
|
@ -27,25 +27,22 @@ Managing templates with these structures is very simple. To support
|
||||||
a new data type, developers define the field identifier and implement
|
a new data type, developers define the field identifier and implement
|
||||||
two functions, init() and show(), respectively to generate and display
|
two functions, init() and show(), respectively to generate and display
|
||||||
measurement entries. Defining a new template descriptor requires
|
measurement entries. Defining a new template descriptor requires
|
||||||
specifying the template format, a string of field identifiers separated
|
specifying the template format (a string of field identifiers separated
|
||||||
by the '|' character. While in the current implementation it is possible
|
by the '|' character) through the 'ima_template_fmt' kernel command line
|
||||||
to define new template descriptors only by adding their definition in the
|
parameter. At boot time, IMA initializes the chosen template descriptor
|
||||||
template specific code (ima_template.c), in a future version it will be
|
by translating the format into an array of template fields structures taken
|
||||||
possible to register a new template on a running kernel by supplying to IMA
|
from the set of the supported ones.
|
||||||
the desired format string. In this version, IMA initializes at boot time
|
|
||||||
all defined template descriptors by translating the format into an array
|
|
||||||
of template fields structures taken from the set of the supported ones.
|
|
||||||
|
|
||||||
After the initialization step, IMA will call ima_alloc_init_template()
|
After the initialization step, IMA will call ima_alloc_init_template()
|
||||||
(new function defined within the patches for the new template management
|
(new function defined within the patches for the new template management
|
||||||
mechanism) to generate a new measurement entry by using the template
|
mechanism) to generate a new measurement entry by using the template
|
||||||
descriptor chosen through the kernel configuration or through the newly
|
descriptor chosen through the kernel configuration or through the newly
|
||||||
introduced 'ima_template=' kernel command line parameter. It is during this
|
introduced 'ima_template' and 'ima_template_fmt' kernel command line parameters.
|
||||||
phase that the advantages of the new architecture are clearly shown:
|
It is during this phase that the advantages of the new architecture are
|
||||||
the latter function will not contain specific code to handle a given template
|
clearly shown: the latter function will not contain specific code to handle
|
||||||
but, instead, it simply calls the init() method of the template fields
|
a given template but, instead, it simply calls the init() method of the template
|
||||||
associated to the chosen template descriptor and store the result (pointer
|
fields associated to the chosen template descriptor and store the result
|
||||||
to allocated data and data length) in the measurement entry structure.
|
(pointer to allocated data and data length) in the measurement entry structure.
|
||||||
|
|
||||||
The same mechanism is employed to display measurements entries.
|
The same mechanism is employed to display measurements entries.
|
||||||
The functions ima[_ascii]_measurements_show() retrieve, for each entry,
|
The functions ima[_ascii]_measurements_show() retrieve, for each entry,
|
||||||
|
@ -86,4 +83,6 @@ currently the following methods are supported:
|
||||||
- select a template descriptor among those supported in the kernel
|
- select a template descriptor among those supported in the kernel
|
||||||
configuration ('ima-ng' is the default choice);
|
configuration ('ima-ng' is the default choice);
|
||||||
- specify a template descriptor name from the kernel command line through
|
- specify a template descriptor name from the kernel command line through
|
||||||
the 'ima_template=' parameter.
|
the 'ima_template=' parameter;
|
||||||
|
- register a new template descriptor with custom format through the kernel
|
||||||
|
command line parameter 'ima_template_fmt='.
|
||||||
|
|
|
@ -412,6 +412,23 @@ ssize_t new_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *p
|
||||||
|
|
||||||
EXPORT_SYMBOL(new_sync_read);
|
EXPORT_SYMBOL(new_sync_read);
|
||||||
|
|
||||||
|
ssize_t __vfs_read(struct file *file, char __user *buf, size_t count,
|
||||||
|
loff_t *pos)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
if (file->f_op->read)
|
||||||
|
ret = file->f_op->read(file, buf, count, pos);
|
||||||
|
else if (file->f_op->aio_read)
|
||||||
|
ret = do_sync_read(file, buf, count, pos);
|
||||||
|
else if (file->f_op->read_iter)
|
||||||
|
ret = new_sync_read(file, buf, count, pos);
|
||||||
|
else
|
||||||
|
ret = -EINVAL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
|
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
@ -426,12 +443,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
|
||||||
ret = rw_verify_area(READ, file, pos, count);
|
ret = rw_verify_area(READ, file, pos, count);
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
count = ret;
|
count = ret;
|
||||||
if (file->f_op->read)
|
ret = __vfs_read(file, buf, count, pos);
|
||||||
ret = file->f_op->read(file, buf, count, pos);
|
|
||||||
else if (file->f_op->aio_read)
|
|
||||||
ret = do_sync_read(file, buf, count, pos);
|
|
||||||
else
|
|
||||||
ret = new_sync_read(file, buf, count, pos);
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
fsnotify_access(file);
|
fsnotify_access(file);
|
||||||
add_rchar(current, ret);
|
add_rchar(current, ret);
|
||||||
|
|
|
@ -1553,6 +1553,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
|
||||||
struct iovec *fast_pointer,
|
struct iovec *fast_pointer,
|
||||||
struct iovec **ret_pointer);
|
struct iovec **ret_pointer);
|
||||||
|
|
||||||
|
extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
|
||||||
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
|
extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
|
||||||
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
|
extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
|
||||||
extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
|
extern ssize_t vfs_readv(struct file *, const struct iovec __user *,
|
||||||
|
|
|
@ -24,6 +24,7 @@ enum integrity_status {
|
||||||
#ifdef CONFIG_INTEGRITY
|
#ifdef CONFIG_INTEGRITY
|
||||||
extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode);
|
extern struct integrity_iint_cache *integrity_inode_get(struct inode *inode);
|
||||||
extern void integrity_inode_free(struct inode *inode);
|
extern void integrity_inode_free(struct inode *inode);
|
||||||
|
extern void __init integrity_load_keys(void);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline struct integrity_iint_cache *
|
static inline struct integrity_iint_cache *
|
||||||
|
@ -36,5 +37,10 @@ static inline void integrity_inode_free(struct inode *inode)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void integrity_load_keys(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_INTEGRITY */
|
#endif /* CONFIG_INTEGRITY */
|
||||||
|
|
||||||
#endif /* _LINUX_INTEGRITY_H */
|
#endif /* _LINUX_INTEGRITY_H */
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
#include <linux/context_tracking.h>
|
#include <linux/context_tracking.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/integrity.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/bugs.h>
|
#include <asm/bugs.h>
|
||||||
|
@ -1027,8 +1028,11 @@ static noinline void __init kernel_init_freeable(void)
|
||||||
* Ok, we have completed the initial bootup, and
|
* Ok, we have completed the initial bootup, and
|
||||||
* we're essentially up and running. Get rid of the
|
* we're essentially up and running. Get rid of the
|
||||||
* initmem segments and start the user-mode stuff..
|
* initmem segments and start the user-mode stuff..
|
||||||
|
*
|
||||||
|
* rootfs is available now, try loading the public keys
|
||||||
|
* and default modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* rootfs is available now, try loading default modules */
|
integrity_load_keys();
|
||||||
load_default_modules();
|
load_default_modules();
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/rbtree.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/cred.h>
|
#include <linux/cred.h>
|
||||||
#include <linux/key-type.h>
|
#include <linux/key-type.h>
|
||||||
#include <linux/digsig.h>
|
#include <linux/digsig.h>
|
||||||
|
@ -63,7 +63,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int integrity_init_keyring(const unsigned int id)
|
int __init integrity_init_keyring(const unsigned int id)
|
||||||
{
|
{
|
||||||
const struct cred *cred = current_cred();
|
const struct cred *cred = current_cred();
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -84,3 +84,37 @@ int integrity_init_keyring(const unsigned int id)
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __init integrity_load_x509(const unsigned int id, char *path)
|
||||||
|
{
|
||||||
|
key_ref_t key;
|
||||||
|
char *data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (!keyring[id])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
rc = integrity_read_file(path, &data);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
key = key_create_or_update(make_key_ref(keyring[id], 1),
|
||||||
|
"asymmetric",
|
||||||
|
NULL,
|
||||||
|
data,
|
||||||
|
rc,
|
||||||
|
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||||
|
KEY_USR_VIEW | KEY_USR_READ),
|
||||||
|
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_TRUSTED);
|
||||||
|
if (IS_ERR(key)) {
|
||||||
|
rc = PTR_ERR(key);
|
||||||
|
pr_err("Problem loading X.509 certificate (%d): %s\n",
|
||||||
|
rc, path);
|
||||||
|
} else {
|
||||||
|
pr_notice("Loaded X.509 cert '%s': %s\n",
|
||||||
|
key_ref_to_ptr(key)->description, path);
|
||||||
|
key_ref_put(key);
|
||||||
|
}
|
||||||
|
kfree(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -162,9 +162,14 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
|
||||||
(const char *)xattr_data, xattr_len,
|
(const char *)xattr_data, xattr_len,
|
||||||
calc.digest, sizeof(calc.digest));
|
calc.digest, sizeof(calc.digest));
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
/* we probably want to replace rsa with hmac here */
|
/* Replace RSA with HMAC if not mounted readonly and
|
||||||
evm_update_evmxattr(dentry, xattr_name, xattr_value,
|
* not immutable
|
||||||
xattr_value_len);
|
*/
|
||||||
|
if (!IS_RDONLY(dentry->d_inode) &&
|
||||||
|
!IS_IMMUTABLE(dentry->d_inode))
|
||||||
|
evm_update_evmxattr(dentry, xattr_name,
|
||||||
|
xattr_value,
|
||||||
|
xattr_value_len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -19,14 +19,14 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include "integrity.h"
|
#include "integrity.h"
|
||||||
|
|
||||||
static struct rb_root integrity_iint_tree = RB_ROOT;
|
static struct rb_root integrity_iint_tree = RB_ROOT;
|
||||||
static DEFINE_RWLOCK(integrity_iint_lock);
|
static DEFINE_RWLOCK(integrity_iint_lock);
|
||||||
static struct kmem_cache *iint_cache __read_mostly;
|
static struct kmem_cache *iint_cache __read_mostly;
|
||||||
|
|
||||||
int iint_initialized;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __integrity_iint_find - return the iint associated with an inode
|
* __integrity_iint_find - return the iint associated with an inode
|
||||||
*/
|
*/
|
||||||
|
@ -166,7 +166,89 @@ static int __init integrity_iintcache_init(void)
|
||||||
iint_cache =
|
iint_cache =
|
||||||
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
|
kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
|
||||||
0, SLAB_PANIC, init_once);
|
0, SLAB_PANIC, init_once);
|
||||||
iint_initialized = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
security_initcall(integrity_iintcache_init);
|
security_initcall(integrity_iintcache_init);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* integrity_kernel_read - read data from the file
|
||||||
|
*
|
||||||
|
* This is a function for reading file content instead of kernel_read().
|
||||||
|
* It does not perform locking checks to ensure it cannot be blocked.
|
||||||
|
* It does not perform security checks because it is irrelevant for IMA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int integrity_kernel_read(struct file *file, loff_t offset,
|
||||||
|
char *addr, unsigned long count)
|
||||||
|
{
|
||||||
|
mm_segment_t old_fs;
|
||||||
|
char __user *buf = (char __user *)addr;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
if (!(file->f_mode & FMODE_READ))
|
||||||
|
return -EBADF;
|
||||||
|
|
||||||
|
old_fs = get_fs();
|
||||||
|
set_fs(get_ds());
|
||||||
|
ret = __vfs_read(file, buf, count, &offset);
|
||||||
|
set_fs(old_fs);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* integrity_read_file - read entire file content into the buffer
|
||||||
|
*
|
||||||
|
* This is function opens a file, allocates the buffer of required
|
||||||
|
* size, read entire file content to the buffer and closes the file
|
||||||
|
*
|
||||||
|
* It is used only by init code.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int __init integrity_read_file(const char *path, char **data)
|
||||||
|
{
|
||||||
|
struct file *file;
|
||||||
|
loff_t size;
|
||||||
|
char *buf;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
file = filp_open(path, O_RDONLY, 0);
|
||||||
|
if (IS_ERR(file)) {
|
||||||
|
rc = PTR_ERR(file);
|
||||||
|
pr_err("Unable to open file: %s (%d)", path, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = i_size_read(file_inode(file));
|
||||||
|
if (size <= 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
buf = kmalloc(size, GFP_KERNEL);
|
||||||
|
if (!buf) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = integrity_kernel_read(file, 0, buf, size);
|
||||||
|
if (rc < 0)
|
||||||
|
kfree(buf);
|
||||||
|
else if (rc != size)
|
||||||
|
rc = -EIO;
|
||||||
|
else
|
||||||
|
*data = buf;
|
||||||
|
out:
|
||||||
|
fput(file);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* integrity_load_keys - load integrity keys hook
|
||||||
|
*
|
||||||
|
* Hooks is called from init/main.c:kernel_init_freeable()
|
||||||
|
* when rootfs is ready
|
||||||
|
*/
|
||||||
|
void __init integrity_load_keys(void)
|
||||||
|
{
|
||||||
|
ima_load_x509();
|
||||||
|
}
|
||||||
|
|
|
@ -131,3 +131,28 @@ config IMA_TRUSTED_KEYRING
|
||||||
help
|
help
|
||||||
This option requires that all keys added to the .ima
|
This option requires that all keys added to the .ima
|
||||||
keyring be signed by a key on the system trusted keyring.
|
keyring be signed by a key on the system trusted keyring.
|
||||||
|
|
||||||
|
config IMA_LOAD_X509
|
||||||
|
bool "Load X509 certificate onto the '.ima' trusted keyring"
|
||||||
|
depends on IMA_TRUSTED_KEYRING
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
File signature verification is based on the public keys
|
||||||
|
loaded on the .ima trusted keyring. These public keys are
|
||||||
|
X509 certificates signed by a trusted key on the
|
||||||
|
.system keyring. This option enables X509 certificate
|
||||||
|
loading from the kernel onto the '.ima' trusted keyring.
|
||||||
|
|
||||||
|
config IMA_X509_PATH
|
||||||
|
string "IMA X509 certificate path"
|
||||||
|
depends on IMA_LOAD_X509
|
||||||
|
default "/etc/keys/x509_ima.der"
|
||||||
|
help
|
||||||
|
This option defines IMA X509 certificate path.
|
||||||
|
|
||||||
|
config IMA_APPRAISE_SIGNED_INIT
|
||||||
|
bool "Require signed user-space initialization"
|
||||||
|
depends on IMA_LOAD_X509
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option requires user-space init to be signed.
|
||||||
|
|
|
@ -173,8 +173,7 @@ int ima_get_action(struct inode *inode, int mask, int function)
|
||||||
{
|
{
|
||||||
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
|
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE;
|
||||||
|
|
||||||
if (!ima_appraise)
|
flags &= ima_policy_flag;
|
||||||
flags &= ~IMA_APPRAISE;
|
|
||||||
|
|
||||||
return ima_match_policy(inode, function, mask, flags);
|
return ima_match_policy(inode, function, mask, flags);
|
||||||
}
|
}
|
||||||
|
@ -325,11 +324,11 @@ const char *ima_d_path(struct path *path, char **pathbuf)
|
||||||
{
|
{
|
||||||
char *pathname = NULL;
|
char *pathname = NULL;
|
||||||
|
|
||||||
*pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
|
*pathbuf = __getname();
|
||||||
if (*pathbuf) {
|
if (*pathbuf) {
|
||||||
pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
|
pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
|
||||||
if (IS_ERR(pathname)) {
|
if (IS_ERR(pathname)) {
|
||||||
kfree(*pathbuf);
|
__putname(*pathbuf);
|
||||||
*pathbuf = NULL;
|
*pathbuf = NULL;
|
||||||
pathname = NULL;
|
pathname = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,36 +67,6 @@ MODULE_PARM_DESC(ahash_bufsize, "Maximum ahash buffer size");
|
||||||
static struct crypto_shash *ima_shash_tfm;
|
static struct crypto_shash *ima_shash_tfm;
|
||||||
static struct crypto_ahash *ima_ahash_tfm;
|
static struct crypto_ahash *ima_ahash_tfm;
|
||||||
|
|
||||||
/**
|
|
||||||
* ima_kernel_read - read file content
|
|
||||||
*
|
|
||||||
* This is a function for reading file content instead of kernel_read().
|
|
||||||
* It does not perform locking checks to ensure it cannot be blocked.
|
|
||||||
* It does not perform security checks because it is irrelevant for IMA.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static int ima_kernel_read(struct file *file, loff_t offset,
|
|
||||||
char *addr, unsigned long count)
|
|
||||||
{
|
|
||||||
mm_segment_t old_fs;
|
|
||||||
char __user *buf = addr;
|
|
||||||
ssize_t ret = -EINVAL;
|
|
||||||
|
|
||||||
if (!(file->f_mode & FMODE_READ))
|
|
||||||
return -EBADF;
|
|
||||||
|
|
||||||
old_fs = get_fs();
|
|
||||||
set_fs(get_ds());
|
|
||||||
if (file->f_op->read)
|
|
||||||
ret = file->f_op->read(file, buf, count, &offset);
|
|
||||||
else if (file->f_op->aio_read)
|
|
||||||
ret = do_sync_read(file, buf, count, &offset);
|
|
||||||
else if (file->f_op->read_iter)
|
|
||||||
ret = new_sync_read(file, buf, count, &offset);
|
|
||||||
set_fs(old_fs);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __init ima_init_crypto(void)
|
int __init ima_init_crypto(void)
|
||||||
{
|
{
|
||||||
long rc;
|
long rc;
|
||||||
|
@ -324,7 +294,8 @@ static int ima_calc_file_hash_atfm(struct file *file,
|
||||||
}
|
}
|
||||||
/* read buffer */
|
/* read buffer */
|
||||||
rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]);
|
rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]);
|
||||||
rc = ima_kernel_read(file, offset, rbuf[active], rbuf_len);
|
rc = integrity_kernel_read(file, offset, rbuf[active],
|
||||||
|
rbuf_len);
|
||||||
if (rc != rbuf_len)
|
if (rc != rbuf_len)
|
||||||
goto out3;
|
goto out3;
|
||||||
|
|
||||||
|
@ -417,7 +388,7 @@ static int ima_calc_file_hash_tfm(struct file *file,
|
||||||
while (offset < i_size) {
|
while (offset < i_size) {
|
||||||
int rbuf_len;
|
int rbuf_len;
|
||||||
|
|
||||||
rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
|
rbuf_len = integrity_kernel_read(file, offset, rbuf, PAGE_SIZE);
|
||||||
if (rbuf_len < 0) {
|
if (rbuf_len < 0) {
|
||||||
rc = rbuf_len;
|
rc = rbuf_len;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -118,6 +118,7 @@ static int ima_measurements_show(struct seq_file *m, void *v)
|
||||||
/* the list never shrinks, so we don't need a lock here */
|
/* the list never shrinks, so we don't need a lock here */
|
||||||
struct ima_queue_entry *qe = v;
|
struct ima_queue_entry *qe = v;
|
||||||
struct ima_template_entry *e;
|
struct ima_template_entry *e;
|
||||||
|
char *template_name;
|
||||||
int namelen;
|
int namelen;
|
||||||
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
|
u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX;
|
||||||
bool is_ima_template = false;
|
bool is_ima_template = false;
|
||||||
|
@ -128,6 +129,9 @@ static int ima_measurements_show(struct seq_file *m, void *v)
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
template_name = (e->template_desc->name[0] != '\0') ?
|
||||||
|
e->template_desc->name : e->template_desc->fmt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1st: PCRIndex
|
* 1st: PCRIndex
|
||||||
* PCR used is always the same (config option) in
|
* PCR used is always the same (config option) in
|
||||||
|
@ -139,14 +143,14 @@ static int ima_measurements_show(struct seq_file *m, void *v)
|
||||||
ima_putc(m, e->digest, TPM_DIGEST_SIZE);
|
ima_putc(m, e->digest, TPM_DIGEST_SIZE);
|
||||||
|
|
||||||
/* 3rd: template name size */
|
/* 3rd: template name size */
|
||||||
namelen = strlen(e->template_desc->name);
|
namelen = strlen(template_name);
|
||||||
ima_putc(m, &namelen, sizeof(namelen));
|
ima_putc(m, &namelen, sizeof(namelen));
|
||||||
|
|
||||||
/* 4th: template name */
|
/* 4th: template name */
|
||||||
ima_putc(m, e->template_desc->name, namelen);
|
ima_putc(m, template_name, namelen);
|
||||||
|
|
||||||
/* 5th: template length (except for 'ima' template) */
|
/* 5th: template length (except for 'ima' template) */
|
||||||
if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0)
|
if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
|
||||||
is_ima_template = true;
|
is_ima_template = true;
|
||||||
|
|
||||||
if (!is_ima_template)
|
if (!is_ima_template)
|
||||||
|
@ -200,6 +204,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
|
||||||
/* the list never shrinks, so we don't need a lock here */
|
/* the list never shrinks, so we don't need a lock here */
|
||||||
struct ima_queue_entry *qe = v;
|
struct ima_queue_entry *qe = v;
|
||||||
struct ima_template_entry *e;
|
struct ima_template_entry *e;
|
||||||
|
char *template_name;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* get entry */
|
/* get entry */
|
||||||
|
@ -207,6 +212,9 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
template_name = (e->template_desc->name[0] != '\0') ?
|
||||||
|
e->template_desc->name : e->template_desc->fmt;
|
||||||
|
|
||||||
/* 1st: PCR used (config option) */
|
/* 1st: PCR used (config option) */
|
||||||
seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
|
seq_printf(m, "%2d ", CONFIG_IMA_MEASURE_PCR_IDX);
|
||||||
|
|
||||||
|
@ -214,7 +222,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, void *v)
|
||||||
ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
|
ima_print_digest(m, e->digest, TPM_DIGEST_SIZE);
|
||||||
|
|
||||||
/* 3th: template name */
|
/* 3th: template name */
|
||||||
seq_printf(m, " %s", e->template_desc->name);
|
seq_printf(m, " %s", template_name);
|
||||||
|
|
||||||
/* 4th: template specific data */
|
/* 4th: template specific data */
|
||||||
for (i = 0; i < e->template_desc->num_fields; i++) {
|
for (i = 0; i < e->template_desc->num_fields; i++) {
|
||||||
|
@ -288,7 +296,12 @@ static struct dentry *runtime_measurements_count;
|
||||||
static struct dentry *violations;
|
static struct dentry *violations;
|
||||||
static struct dentry *ima_policy;
|
static struct dentry *ima_policy;
|
||||||
|
|
||||||
static atomic_t policy_opencount = ATOMIC_INIT(1);
|
enum ima_fs_flags {
|
||||||
|
IMA_FS_BUSY,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned long ima_fs_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ima_open_policy: sequentialize access to the policy file
|
* ima_open_policy: sequentialize access to the policy file
|
||||||
*/
|
*/
|
||||||
|
@ -297,9 +310,9 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
|
||||||
/* No point in being allowed to open it if you aren't going to write */
|
/* No point in being allowed to open it if you aren't going to write */
|
||||||
if (!(filp->f_flags & O_WRONLY))
|
if (!(filp->f_flags & O_WRONLY))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
if (atomic_dec_and_test(&policy_opencount))
|
if (test_and_set_bit(IMA_FS_BUSY, &ima_fs_flags))
|
||||||
return 0;
|
return -EBUSY;
|
||||||
return -EBUSY;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -311,10 +324,16 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
|
||||||
*/
|
*/
|
||||||
static int ima_release_policy(struct inode *inode, struct file *file)
|
static int ima_release_policy(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
|
const char *cause = valid_policy ? "completed" : "failed";
|
||||||
|
|
||||||
|
pr_info("IMA: policy update %s\n", cause);
|
||||||
|
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
|
||||||
|
"policy_update", cause, !valid_policy, 0);
|
||||||
|
|
||||||
if (!valid_policy) {
|
if (!valid_policy) {
|
||||||
ima_delete_rules();
|
ima_delete_rules();
|
||||||
valid_policy = 1;
|
valid_policy = 1;
|
||||||
atomic_set(&policy_opencount, 1);
|
clear_bit(IMA_FS_BUSY, &ima_fs_flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ima_update_policy();
|
ima_update_policy();
|
||||||
|
|
|
@ -24,6 +24,12 @@
|
||||||
#include <crypto/hash_info.h>
|
#include <crypto/hash_info.h>
|
||||||
#include "ima.h"
|
#include "ima.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_IMA_X509_PATH
|
||||||
|
#define IMA_X509_PATH CONFIG_IMA_X509_PATH
|
||||||
|
#else
|
||||||
|
#define IMA_X509_PATH "/etc/keys/x509_ima.der"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* name for boot aggregate entry */
|
/* name for boot aggregate entry */
|
||||||
static const char *boot_aggregate_name = "boot_aggregate";
|
static const char *boot_aggregate_name = "boot_aggregate";
|
||||||
int ima_used_chip;
|
int ima_used_chip;
|
||||||
|
@ -91,6 +97,17 @@ err_out:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_IMA_LOAD_X509
|
||||||
|
void __init ima_load_x509(void)
|
||||||
|
{
|
||||||
|
int unset_flags = ima_policy_flag & IMA_APPRAISE;
|
||||||
|
|
||||||
|
ima_policy_flag &= ~unset_flags;
|
||||||
|
integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH);
|
||||||
|
ima_policy_flag |= unset_flags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int __init ima_init(void)
|
int __init ima_init(void)
|
||||||
{
|
{
|
||||||
u8 pcr_i[TPM_DIGEST_SIZE];
|
u8 pcr_i[TPM_DIGEST_SIZE];
|
||||||
|
|
|
@ -143,7 +143,7 @@ void ima_file_free(struct file *file)
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
struct integrity_iint_cache *iint;
|
struct integrity_iint_cache *iint;
|
||||||
|
|
||||||
if (!iint_initialized || !S_ISREG(inode->i_mode))
|
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
iint = integrity_iint_find(inode);
|
iint = integrity_iint_find(inode);
|
||||||
|
@ -246,7 +246,8 @@ out_digsig:
|
||||||
rc = -EACCES;
|
rc = -EACCES;
|
||||||
kfree(xattr_value);
|
kfree(xattr_value);
|
||||||
out_free:
|
out_free:
|
||||||
kfree(pathbuf);
|
if (pathbuf)
|
||||||
|
__putname(pathbuf);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
|
if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
|
||||||
|
|
|
@ -100,7 +100,13 @@ static struct ima_rule_entry default_appraise_rules[] = {
|
||||||
{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
|
{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||||
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
||||||
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||||
|
#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
|
||||||
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
|
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
|
||||||
|
#else
|
||||||
|
/* force signature */
|
||||||
|
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID,
|
||||||
|
.flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static LIST_HEAD(ima_default_rules);
|
static LIST_HEAD(ima_default_rules);
|
||||||
|
@ -356,19 +362,8 @@ void __init ima_init_policy(void)
|
||||||
*/
|
*/
|
||||||
void ima_update_policy(void)
|
void ima_update_policy(void)
|
||||||
{
|
{
|
||||||
static const char op[] = "policy_update";
|
ima_rules = &ima_policy_rules;
|
||||||
const char *cause = "already-exists";
|
ima_update_policy_flag();
|
||||||
int result = 1;
|
|
||||||
int audit_info = 0;
|
|
||||||
|
|
||||||
if (ima_rules == &ima_default_rules) {
|
|
||||||
ima_rules = &ima_policy_rules;
|
|
||||||
ima_update_policy_flag();
|
|
||||||
cause = "complete";
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
|
|
||||||
NULL, op, cause, result, audit_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -686,13 +681,12 @@ ssize_t ima_parse_add_rule(char *rule)
|
||||||
ssize_t result, len;
|
ssize_t result, len;
|
||||||
int audit_info = 0;
|
int audit_info = 0;
|
||||||
|
|
||||||
/* Prevent installed policy from changing */
|
p = strsep(&rule, "\n");
|
||||||
if (ima_rules != &ima_default_rules) {
|
len = strlen(p) + 1;
|
||||||
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL,
|
p += strspn(p, " \t");
|
||||||
NULL, op, "already-exists",
|
|
||||||
-EACCES, audit_info);
|
if (*p == '#' || *p == '\0')
|
||||||
return -EACCES;
|
return len;
|
||||||
}
|
|
||||||
|
|
||||||
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
@ -703,14 +697,6 @@ ssize_t ima_parse_add_rule(char *rule)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&entry->list);
|
INIT_LIST_HEAD(&entry->list);
|
||||||
|
|
||||||
p = strsep(&rule, "\n");
|
|
||||||
len = strlen(p) + 1;
|
|
||||||
|
|
||||||
if (*p == '#') {
|
|
||||||
kfree(entry);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ima_parse_rule(p, entry);
|
result = ima_parse_rule(p, entry);
|
||||||
if (result) {
|
if (result) {
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
|
|
|
@ -24,6 +24,7 @@ static struct ima_template_desc defined_templates[] = {
|
||||||
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
|
{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
|
||||||
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
|
{.name = "ima-ng", .fmt = "d-ng|n-ng"},
|
||||||
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
|
{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
|
||||||
|
{.name = "", .fmt = ""}, /* placeholder for a custom format */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ima_template_field supported_fields[] = {
|
static struct ima_template_field supported_fields[] = {
|
||||||
|
@ -41,19 +42,28 @@ static struct ima_template_field supported_fields[] = {
|
||||||
|
|
||||||
static struct ima_template_desc *ima_template;
|
static struct ima_template_desc *ima_template;
|
||||||
static struct ima_template_desc *lookup_template_desc(const char *name);
|
static struct ima_template_desc *lookup_template_desc(const char *name);
|
||||||
|
static int template_desc_init_fields(const char *template_fmt,
|
||||||
|
struct ima_template_field ***fields,
|
||||||
|
int *num_fields);
|
||||||
|
|
||||||
static int __init ima_template_setup(char *str)
|
static int __init ima_template_setup(char *str)
|
||||||
{
|
{
|
||||||
struct ima_template_desc *template_desc;
|
struct ima_template_desc *template_desc;
|
||||||
int template_len = strlen(str);
|
int template_len = strlen(str);
|
||||||
|
|
||||||
|
if (ima_template)
|
||||||
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that a template with the supplied name exists.
|
* Verify that a template with the supplied name exists.
|
||||||
* If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
|
* If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
|
||||||
*/
|
*/
|
||||||
template_desc = lookup_template_desc(str);
|
template_desc = lookup_template_desc(str);
|
||||||
if (!template_desc)
|
if (!template_desc) {
|
||||||
|
pr_err("template %s not found, using %s\n",
|
||||||
|
str, CONFIG_IMA_DEFAULT_TEMPLATE);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify whether the current hash algorithm is supported
|
* Verify whether the current hash algorithm is supported
|
||||||
|
@ -70,6 +80,25 @@ static int __init ima_template_setup(char *str)
|
||||||
}
|
}
|
||||||
__setup("ima_template=", ima_template_setup);
|
__setup("ima_template=", ima_template_setup);
|
||||||
|
|
||||||
|
static int __init ima_template_fmt_setup(char *str)
|
||||||
|
{
|
||||||
|
int num_templates = ARRAY_SIZE(defined_templates);
|
||||||
|
|
||||||
|
if (ima_template)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (template_desc_init_fields(str, NULL, NULL) < 0) {
|
||||||
|
pr_err("format string '%s' not valid, using template %s\n",
|
||||||
|
str, CONFIG_IMA_DEFAULT_TEMPLATE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
defined_templates[num_templates - 1].fmt = str;
|
||||||
|
ima_template = defined_templates + num_templates - 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("ima_template_fmt=", ima_template_fmt_setup);
|
||||||
|
|
||||||
static struct ima_template_desc *lookup_template_desc(const char *name)
|
static struct ima_template_desc *lookup_template_desc(const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -113,43 +142,46 @@ static int template_desc_init_fields(const char *template_fmt,
|
||||||
struct ima_template_field ***fields,
|
struct ima_template_field ***fields,
|
||||||
int *num_fields)
|
int *num_fields)
|
||||||
{
|
{
|
||||||
char *c, *template_fmt_copy, *template_fmt_ptr;
|
const char *template_fmt_ptr;
|
||||||
|
struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
|
||||||
int template_num_fields = template_fmt_size(template_fmt);
|
int template_num_fields = template_fmt_size(template_fmt);
|
||||||
int i, result = 0;
|
int i, len;
|
||||||
|
|
||||||
if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX)
|
if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
|
||||||
|
pr_err("format string '%s' contains too many fields\n",
|
||||||
|
template_fmt);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* copying is needed as strsep() modifies the original buffer */
|
|
||||||
template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL);
|
|
||||||
if (template_fmt_copy == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
*fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL);
|
|
||||||
if (*fields == NULL) {
|
|
||||||
result = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template_fmt_ptr = template_fmt_copy;
|
for (i = 0, template_fmt_ptr = template_fmt; i < template_num_fields;
|
||||||
for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL &&
|
i++, template_fmt_ptr += len + 1) {
|
||||||
i < template_num_fields; i++) {
|
char tmp_field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN + 1];
|
||||||
struct ima_template_field *f = lookup_template_field(c);
|
|
||||||
|
|
||||||
if (!f) {
|
len = strchrnul(template_fmt_ptr, '|') - template_fmt_ptr;
|
||||||
result = -ENOENT;
|
if (len == 0 || len > IMA_TEMPLATE_FIELD_ID_MAX_LEN) {
|
||||||
goto out;
|
pr_err("Invalid field with length %d\n", len);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(tmp_field_id, template_fmt_ptr, len);
|
||||||
|
tmp_field_id[len] = '\0';
|
||||||
|
found_fields[i] = lookup_template_field(tmp_field_id);
|
||||||
|
if (!found_fields[i]) {
|
||||||
|
pr_err("field '%s' not found\n", tmp_field_id);
|
||||||
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
(*fields)[i] = f;
|
|
||||||
}
|
}
|
||||||
*num_fields = i;
|
|
||||||
out:
|
if (fields && num_fields) {
|
||||||
if (result < 0) {
|
*fields = kmalloc_array(i, sizeof(*fields), GFP_KERNEL);
|
||||||
kfree(*fields);
|
if (*fields == NULL)
|
||||||
*fields = NULL;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memcpy(*fields, found_fields, i * sizeof(*fields));
|
||||||
|
*num_fields = i;
|
||||||
}
|
}
|
||||||
kfree(template_fmt_copy);
|
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ima_template_desc *ima_template_desc_current(void)
|
struct ima_template_desc *ima_template_desc_current(void)
|
||||||
|
@ -163,8 +195,15 @@ struct ima_template_desc *ima_template_desc_current(void)
|
||||||
int __init ima_init_template(void)
|
int __init ima_init_template(void)
|
||||||
{
|
{
|
||||||
struct ima_template_desc *template = ima_template_desc_current();
|
struct ima_template_desc *template = ima_template_desc_current();
|
||||||
|
int result;
|
||||||
|
|
||||||
return template_desc_init_fields(template->fmt,
|
result = template_desc_init_fields(template->fmt,
|
||||||
&(template->fields),
|
&(template->fields),
|
||||||
&(template->num_fields));
|
&(template->num_fields));
|
||||||
|
if (result < 0)
|
||||||
|
pr_err("template %s init failed, result: %d\n",
|
||||||
|
(strlen(template->name) ?
|
||||||
|
template->name : template->fmt), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,10 @@ struct integrity_iint_cache {
|
||||||
*/
|
*/
|
||||||
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
||||||
|
|
||||||
|
int integrity_kernel_read(struct file *file, loff_t offset,
|
||||||
|
char *addr, unsigned long count);
|
||||||
|
int __init integrity_read_file(const char *path, char **data);
|
||||||
|
|
||||||
#define INTEGRITY_KEYRING_EVM 0
|
#define INTEGRITY_KEYRING_EVM 0
|
||||||
#define INTEGRITY_KEYRING_MODULE 1
|
#define INTEGRITY_KEYRING_MODULE 1
|
||||||
#define INTEGRITY_KEYRING_IMA 2
|
#define INTEGRITY_KEYRING_IMA 2
|
||||||
|
@ -129,7 +133,8 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
|
||||||
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
||||||
const char *digest, int digestlen);
|
const char *digest, int digestlen);
|
||||||
|
|
||||||
int integrity_init_keyring(const unsigned int id);
|
int __init integrity_init_keyring(const unsigned int id);
|
||||||
|
int __init integrity_load_x509(const unsigned int id, char *path);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static inline int integrity_digsig_verify(const unsigned int id,
|
static inline int integrity_digsig_verify(const unsigned int id,
|
||||||
|
@ -143,6 +148,7 @@ static inline int integrity_init_keyring(const unsigned int id)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_INTEGRITY_SIGNATURE */
|
#endif /* CONFIG_INTEGRITY_SIGNATURE */
|
||||||
|
|
||||||
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
|
#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
|
||||||
|
@ -156,6 +162,14 @@ static inline int asymmetric_verify(struct key *keyring, const char *sig,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_IMA_LOAD_X509
|
||||||
|
void __init ima_load_x509(void);
|
||||||
|
#else
|
||||||
|
static inline void ima_load_x509(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_INTEGRITY_AUDIT
|
#ifdef CONFIG_INTEGRITY_AUDIT
|
||||||
/* declarations */
|
/* declarations */
|
||||||
void integrity_audit_msg(int audit_msgno, struct inode *inode,
|
void integrity_audit_msg(int audit_msgno, struct inode *inode,
|
||||||
|
@ -169,6 +183,3 @@ static inline void integrity_audit_msg(int audit_msgno, struct inode *inode,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* set during initialization */
|
|
||||||
extern int iint_initialized;
|
|
||||||
|
|
Loading…
Reference in New Issue