mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity into next
This commit is contained in:
commit
481873d06f
22 changed files with 606 additions and 369 deletions
|
@ -27,6 +27,7 @@ Description:
|
|||
|
||||
base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK]
|
||||
[FIRMWARE_CHECK]
|
||||
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
|
||||
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
|
||||
[[^]MAY_EXEC]
|
||||
fsmagic:= hex value
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/suspend.h>
|
||||
|
@ -291,40 +292,19 @@ static const char * const fw_path[] = {
|
|||
module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644);
|
||||
MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path");
|
||||
|
||||
static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
|
||||
static void fw_finish_direct_load(struct device *device,
|
||||
struct firmware_buf *buf)
|
||||
{
|
||||
int size;
|
||||
char *buf;
|
||||
int rc;
|
||||
|
||||
if (!S_ISREG(file_inode(file)->i_mode))
|
||||
return -EINVAL;
|
||||
size = i_size_read(file_inode(file));
|
||||
if (size <= 0)
|
||||
return -EINVAL;
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
rc = kernel_read(file, 0, buf, size);
|
||||
if (rc != size) {
|
||||
if (rc > 0)
|
||||
rc = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
rc = security_kernel_fw_from_file(file, buf, size);
|
||||
if (rc)
|
||||
goto fail;
|
||||
fw_buf->data = buf;
|
||||
fw_buf->size = size;
|
||||
return 0;
|
||||
fail:
|
||||
vfree(buf);
|
||||
return rc;
|
||||
mutex_lock(&fw_lock);
|
||||
set_bit(FW_STATUS_DONE, &buf->status);
|
||||
complete_all(&buf->completion);
|
||||
mutex_unlock(&fw_lock);
|
||||
}
|
||||
|
||||
static int fw_get_filesystem_firmware(struct device *device,
|
||||
struct firmware_buf *buf)
|
||||
{
|
||||
loff_t size;
|
||||
int i, len;
|
||||
int rc = -ENOENT;
|
||||
char *path;
|
||||
|
@ -334,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device,
|
|||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
|
||||
struct file *file;
|
||||
|
||||
/* skip the unset customized path */
|
||||
if (!fw_path[i][0])
|
||||
continue;
|
||||
|
@ -347,28 +325,21 @@ static int fw_get_filesystem_firmware(struct device *device,
|
|||
break;
|
||||
}
|
||||
|
||||
file = filp_open(path, O_RDONLY, 0);
|
||||
if (IS_ERR(file))
|
||||
buf->size = 0;
|
||||
rc = kernel_read_file_from_path(path, &buf->data, &size,
|
||||
INT_MAX, READING_FIRMWARE);
|
||||
if (rc) {
|
||||
dev_warn(device, "loading %s failed with error %d\n",
|
||||
path, rc);
|
||||
continue;
|
||||
rc = fw_read_file_contents(file, buf);
|
||||
fput(file);
|
||||
if (rc)
|
||||
dev_warn(device, "firmware, attempted to load %s, but failed with error %d\n",
|
||||
path, rc);
|
||||
else
|
||||
break;
|
||||
}
|
||||
dev_dbg(device, "direct-loading %s\n", buf->fw_id);
|
||||
buf->size = size;
|
||||
fw_finish_direct_load(device, buf);
|
||||
break;
|
||||
}
|
||||
__putname(path);
|
||||
|
||||
if (!rc) {
|
||||
dev_dbg(device, "firmware: direct-loading firmware %s\n",
|
||||
buf->fw_id);
|
||||
mutex_lock(&fw_lock);
|
||||
set_bit(FW_STATUS_DONE, &buf->status);
|
||||
complete_all(&buf->completion);
|
||||
mutex_unlock(&fw_lock);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -685,8 +656,9 @@ static ssize_t firmware_loading_store(struct device *dev,
|
|||
dev_err(dev, "%s: map pages failed\n",
|
||||
__func__);
|
||||
else
|
||||
rc = security_kernel_fw_from_file(NULL,
|
||||
fw_buf->data, fw_buf->size);
|
||||
rc = security_kernel_post_read_file(NULL,
|
||||
fw_buf->data, fw_buf->size,
|
||||
READING_FIRMWARE);
|
||||
|
||||
/*
|
||||
* Same logic as fw_load_abort, only the DONE bit
|
||||
|
@ -1051,7 +1023,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
|
|||
}
|
||||
|
||||
if (fw_get_builtin_firmware(firmware, name)) {
|
||||
dev_dbg(device, "firmware: using built-in firmware %s\n", name);
|
||||
dev_dbg(device, "using built-in %s\n", name);
|
||||
return 0; /* assigned */
|
||||
}
|
||||
|
||||
|
|
92
fs/exec.c
92
fs/exec.c
|
@ -56,6 +56,7 @@
|
|||
#include <linux/pipe_fs_i.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
@ -831,6 +832,97 @@ int kernel_read(struct file *file, loff_t offset,
|
|||
|
||||
EXPORT_SYMBOL(kernel_read);
|
||||
|
||||
int kernel_read_file(struct file *file, void **buf, loff_t *size,
|
||||
loff_t max_size, enum kernel_read_file_id id)
|
||||
{
|
||||
loff_t i_size, pos;
|
||||
ssize_t bytes = 0;
|
||||
int ret;
|
||||
|
||||
if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ret = security_kernel_read_file(file, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i_size = i_size_read(file_inode(file));
|
||||
if (max_size > 0 && i_size > max_size)
|
||||
return -EFBIG;
|
||||
if (i_size <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
*buf = vmalloc(i_size);
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = 0;
|
||||
while (pos < i_size) {
|
||||
bytes = kernel_read(file, pos, (char *)(*buf) + pos,
|
||||
i_size - pos);
|
||||
if (bytes < 0) {
|
||||
ret = bytes;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
break;
|
||||
pos += bytes;
|
||||
}
|
||||
|
||||
if (pos != i_size) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = security_kernel_post_read_file(file, *buf, i_size, id);
|
||||
if (!ret)
|
||||
*size = pos;
|
||||
|
||||
out:
|
||||
if (ret < 0) {
|
||||
vfree(*buf);
|
||||
*buf = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_read_file);
|
||||
|
||||
int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
|
||||
loff_t max_size, enum kernel_read_file_id id)
|
||||
{
|
||||
struct file *file;
|
||||
int ret;
|
||||
|
||||
if (!path || !*path)
|
||||
return -EINVAL;
|
||||
|
||||
file = filp_open(path, O_RDONLY, 0);
|
||||
if (IS_ERR(file))
|
||||
return PTR_ERR(file);
|
||||
|
||||
ret = kernel_read_file(file, buf, size, max_size, id);
|
||||
fput(file);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_read_file_from_path);
|
||||
|
||||
int kernel_read_file_from_fd(int fd, void **buf, loff_t *size, loff_t max_size,
|
||||
enum kernel_read_file_id id)
|
||||
{
|
||||
struct fd f = fdget(fd);
|
||||
int ret = -EBADF;
|
||||
|
||||
if (!f.file)
|
||||
goto out;
|
||||
|
||||
ret = kernel_read_file(f.file, buf, size, max_size, id);
|
||||
out:
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(kernel_read_file_from_fd);
|
||||
|
||||
ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
|
||||
{
|
||||
ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
|
||||
|
|
|
@ -2576,7 +2576,22 @@ static inline void i_readcount_inc(struct inode *inode)
|
|||
#endif
|
||||
extern int do_pipe_flags(int *, int);
|
||||
|
||||
enum kernel_read_file_id {
|
||||
READING_FIRMWARE = 1,
|
||||
READING_MODULE,
|
||||
READING_KEXEC_IMAGE,
|
||||
READING_KEXEC_INITRAMFS,
|
||||
READING_POLICY,
|
||||
READING_MAX_ID
|
||||
};
|
||||
|
||||
extern int kernel_read(struct file *, loff_t, char *, unsigned long);
|
||||
extern int kernel_read_file(struct file *, void **, loff_t *, loff_t,
|
||||
enum kernel_read_file_id);
|
||||
extern int kernel_read_file_from_path(char *, void **, loff_t *, loff_t,
|
||||
enum kernel_read_file_id);
|
||||
extern int kernel_read_file_from_fd(int, void **, loff_t *, loff_t,
|
||||
enum kernel_read_file_id);
|
||||
extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t);
|
||||
extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
|
||||
extern struct file * open_exec(const char *);
|
||||
|
|
|
@ -18,8 +18,9 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
|
|||
extern int ima_file_check(struct file *file, int mask, int opened);
|
||||
extern void ima_file_free(struct file *file);
|
||||
extern int ima_file_mmap(struct file *file, unsigned long prot);
|
||||
extern int ima_module_check(struct file *file);
|
||||
extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
|
||||
extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
|
||||
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
||||
enum kernel_read_file_id id);
|
||||
|
||||
#else
|
||||
static inline int ima_bprm_check(struct linux_binprm *bprm)
|
||||
|
@ -42,12 +43,13 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int ima_module_check(struct file *file)
|
||||
static inline int ima_read_file(struct file *file, enum kernel_read_file_id id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ima_fw_from_file(struct file *file, char *buf, size_t size)
|
||||
static inline int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
||||
enum kernel_read_file_id id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -541,25 +541,24 @@
|
|||
* @inode points to the inode to use as a reference.
|
||||
* The current task must be the one that nominated @inode.
|
||||
* Return 0 if successful.
|
||||
* @kernel_fw_from_file:
|
||||
* Load firmware from userspace (not called for built-in firmware).
|
||||
* @file contains the file structure pointing to the file containing
|
||||
* the firmware to load. This argument will be NULL if the firmware
|
||||
* was loaded via the uevent-triggered blob-based interface exposed
|
||||
* by CONFIG_FW_LOADER_USER_HELPER.
|
||||
* @buf pointer to buffer containing firmware contents.
|
||||
* @size length of the firmware contents.
|
||||
* Return 0 if permission is granted.
|
||||
* @kernel_module_request:
|
||||
* Ability to trigger the kernel to automatically upcall to userspace for
|
||||
* userspace to load a kernel module with the given name.
|
||||
* @kmod_name name of the module requested by the kernel
|
||||
* Return 0 if successful.
|
||||
* @kernel_module_from_file:
|
||||
* Load a kernel module from userspace.
|
||||
* @file contains the file structure pointing to the file containing
|
||||
* the kernel module to load. If the module is being loaded from a blob,
|
||||
* this argument will be NULL.
|
||||
* @kernel_read_file:
|
||||
* Read a file specified by userspace.
|
||||
* @file contains the file structure pointing to the file being read
|
||||
* by the kernel.
|
||||
* @id kernel read file identifier
|
||||
* Return 0 if permission is granted.
|
||||
* @kernel_post_read_file:
|
||||
* Read a file specified by userspace.
|
||||
* @file contains the file structure pointing to the file being read
|
||||
* by the kernel.
|
||||
* @buf pointer to buffer containing the file contents.
|
||||
* @size length of the file contents.
|
||||
* @id kernel read file identifier
|
||||
* Return 0 if permission is granted.
|
||||
* @task_fix_setuid:
|
||||
* Update the module's state after setting one or more of the user
|
||||
|
@ -1454,9 +1453,11 @@ union security_list_options {
|
|||
void (*cred_transfer)(struct cred *new, const struct cred *old);
|
||||
int (*kernel_act_as)(struct cred *new, u32 secid);
|
||||
int (*kernel_create_files_as)(struct cred *new, struct inode *inode);
|
||||
int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size);
|
||||
int (*kernel_module_request)(char *kmod_name);
|
||||
int (*kernel_module_from_file)(struct file *file);
|
||||
int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id);
|
||||
int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size,
|
||||
enum kernel_read_file_id id);
|
||||
int (*task_fix_setuid)(struct cred *new, const struct cred *old,
|
||||
int flags);
|
||||
int (*task_setpgid)(struct task_struct *p, pid_t pgid);
|
||||
|
@ -1715,9 +1716,9 @@ struct security_hook_heads {
|
|||
struct list_head cred_transfer;
|
||||
struct list_head kernel_act_as;
|
||||
struct list_head kernel_create_files_as;
|
||||
struct list_head kernel_fw_from_file;
|
||||
struct list_head kernel_read_file;
|
||||
struct list_head kernel_post_read_file;
|
||||
struct list_head kernel_module_request;
|
||||
struct list_head kernel_module_from_file;
|
||||
struct list_head task_fix_setuid;
|
||||
struct list_head task_setpgid;
|
||||
struct list_head task_getpgid;
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
|
||||
#include <linux/key.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
struct linux_binprm;
|
||||
struct cred;
|
||||
|
@ -298,9 +300,11 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp);
|
|||
void security_transfer_creds(struct cred *new, const struct cred *old);
|
||||
int security_kernel_act_as(struct cred *new, u32 secid);
|
||||
int security_kernel_create_files_as(struct cred *new, struct inode *inode);
|
||||
int security_kernel_fw_from_file(struct file *file, char *buf, size_t size);
|
||||
int security_kernel_module_request(char *kmod_name);
|
||||
int security_kernel_module_from_file(struct file *file);
|
||||
int security_kernel_read_file(struct file *file, enum kernel_read_file_id id);
|
||||
int security_kernel_post_read_file(struct file *file, char *buf, loff_t size,
|
||||
enum kernel_read_file_id id);
|
||||
int security_task_fix_setuid(struct cred *new, const struct cred *old,
|
||||
int flags);
|
||||
int security_task_setpgid(struct task_struct *p, pid_t pgid);
|
||||
|
@ -850,18 +854,20 @@ static inline int security_kernel_create_files_as(struct cred *cred,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_kernel_fw_from_file(struct file *file,
|
||||
char *buf, size_t size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_kernel_module_request(char *kmod_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_kernel_module_from_file(struct file *file)
|
||||
static inline int security_kernel_read_file(struct file *file,
|
||||
enum kernel_read_file_id id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_kernel_post_read_file(struct file *file,
|
||||
char *buf, loff_t size,
|
||||
enum kernel_read_file_id id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/kexec.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/fs.h>
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <linux/syscalls.h>
|
||||
|
@ -33,65 +34,6 @@ size_t __weak kexec_purgatory_size = 0;
|
|||
|
||||
static int kexec_calculate_store_digests(struct kimage *image);
|
||||
|
||||
static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
|
||||
{
|
||||
struct fd f = fdget(fd);
|
||||
int ret;
|
||||
struct kstat stat;
|
||||
loff_t pos;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
ret = vfs_getattr(&f.file->f_path, &stat);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (stat.size > INT_MAX) {
|
||||
ret = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Don't hand 0 to vmalloc, it whines. */
|
||||
if (stat.size == 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*buf = vmalloc(stat.size);
|
||||
if (!*buf) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
while (pos < stat.size) {
|
||||
bytes = kernel_read(f.file, pos, (char *)(*buf) + pos,
|
||||
stat.size - pos);
|
||||
if (bytes < 0) {
|
||||
vfree(*buf);
|
||||
ret = bytes;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
break;
|
||||
pos += bytes;
|
||||
}
|
||||
|
||||
if (pos != stat.size) {
|
||||
ret = -EBADF;
|
||||
vfree(*buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*buf_len = pos;
|
||||
out:
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Architectures can provide this probe function */
|
||||
int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
|
||||
unsigned long buf_len)
|
||||
|
@ -182,16 +124,17 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
|
|||
{
|
||||
int ret = 0;
|
||||
void *ldata;
|
||||
loff_t size;
|
||||
|
||||
ret = copy_file_from_fd(kernel_fd, &image->kernel_buf,
|
||||
&image->kernel_buf_len);
|
||||
ret = kernel_read_file_from_fd(kernel_fd, &image->kernel_buf,
|
||||
&size, INT_MAX, READING_KEXEC_IMAGE);
|
||||
if (ret)
|
||||
return ret;
|
||||
image->kernel_buf_len = size;
|
||||
|
||||
/* Call arch image probe handlers */
|
||||
ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
|
||||
image->kernel_buf_len);
|
||||
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
|
@ -206,10 +149,12 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
|
|||
#endif
|
||||
/* It is possible that there no initramfs is being loaded */
|
||||
if (!(flags & KEXEC_FILE_NO_INITRAMFS)) {
|
||||
ret = copy_file_from_fd(initrd_fd, &image->initrd_buf,
|
||||
&image->initrd_buf_len);
|
||||
ret = kernel_read_file_from_fd(initrd_fd, &image->initrd_buf,
|
||||
&size, INT_MAX,
|
||||
READING_KEXEC_INITRAMFS);
|
||||
if (ret)
|
||||
goto out;
|
||||
image->initrd_buf_len = size;
|
||||
}
|
||||
|
||||
if (cmdline_len) {
|
||||
|
|
|
@ -2654,7 +2654,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
|
|||
if (info->len < sizeof(*(info->hdr)))
|
||||
return -ENOEXEC;
|
||||
|
||||
err = security_kernel_module_from_file(NULL);
|
||||
err = security_kernel_read_file(NULL, READING_MODULE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -2672,63 +2672,6 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Sets info->hdr and info->len. */
|
||||
static int copy_module_from_fd(int fd, struct load_info *info)
|
||||
{
|
||||
struct fd f = fdget(fd);
|
||||
int err;
|
||||
struct kstat stat;
|
||||
loff_t pos;
|
||||
ssize_t bytes = 0;
|
||||
|
||||
if (!f.file)
|
||||
return -ENOEXEC;
|
||||
|
||||
err = security_kernel_module_from_file(f.file);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = vfs_getattr(&f.file->f_path, &stat);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (stat.size > INT_MAX) {
|
||||
err = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Don't hand 0 to vmalloc, it whines. */
|
||||
if (stat.size == 0) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
info->hdr = vmalloc(stat.size);
|
||||
if (!info->hdr) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
while (pos < stat.size) {
|
||||
bytes = kernel_read(f.file, pos, (char *)(info->hdr) + pos,
|
||||
stat.size - pos);
|
||||
if (bytes < 0) {
|
||||
vfree(info->hdr);
|
||||
err = bytes;
|
||||
goto out;
|
||||
}
|
||||
if (bytes == 0)
|
||||
break;
|
||||
pos += bytes;
|
||||
}
|
||||
info->len = pos;
|
||||
|
||||
out:
|
||||
fdput(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void free_copy(struct load_info *info)
|
||||
{
|
||||
vfree(info->hdr);
|
||||
|
@ -3589,8 +3532,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
|
|||
|
||||
SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
||||
{
|
||||
int err;
|
||||
struct load_info info = { };
|
||||
loff_t size;
|
||||
void *hdr;
|
||||
int err;
|
||||
|
||||
err = may_init_module();
|
||||
if (err)
|
||||
|
@ -3602,9 +3547,12 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags)
|
|||
|MODULE_INIT_IGNORE_VERMAGIC))
|
||||
return -EINVAL;
|
||||
|
||||
err = copy_module_from_fd(fd, &info);
|
||||
err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX,
|
||||
READING_MODULE);
|
||||
if (err)
|
||||
return err;
|
||||
info.hdr = hdr;
|
||||
info.len = size;
|
||||
|
||||
return load_module(&info, uargs, flags);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
|
|||
* 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 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
|
|||
* 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;
|
||||
hash.hdr.algo = algo;
|
||||
|
||||
if (xattr_value)
|
||||
ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
|
||||
|
||||
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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 @@ static int process_measurement(struct file *file, int mask, int function,
|
|||
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)
|
||||
|
|
|
@ -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 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
|||
* 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)
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
#include "ima.h"
|
||||
#include "ima_template_lib.h"
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
* File: ima_template_lib.c
|
||||
* Library of supported template fields.
|
||||
*/
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
#include "ima_template_lib.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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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 ret;
|
||||
|
||||
ret = call_int_hook(kernel_fw_from_file, 0, file, buf, size);
|
||||
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);
|
||||
}
|
||||
|
||||
int security_kernel_module_from_file(struct file *file)
|
||||
int security_kernel_read_file(struct file *file, enum kernel_read_file_id id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = call_int_hook(kernel_module_from_file, 0, file);
|
||||
ret = call_int_hook(kernel_read_file, 0, file, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
return ima_module_check(file);
|
||||
return ima_read_file(file, id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(security_kernel_read_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_post_read_file, 0, file, buf, size, id);
|
||||
if (ret)
|
||||
return ret;
|
||||
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),
|
||||
|
|
Loading…
Reference in a new issue