You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
"The main change in this kernel is Casey's generalized LSM stacking
work, which removes the hard-coding of Capabilities and Yama stacking,
allowing multiple arbitrary "small" LSMs to be stacked with a default
monolithic module (e.g. SELinux, Smack, AppArmor).
See
https://lwn.net/Articles/636056/
This will allow smaller, simpler LSMs to be incorporated into the
mainline kernel and arbitrarily stacked by users. Also, this is a
useful cleanup of the LSM code in its own right"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (38 commits)
tpm, tpm_crb: fix le64_to_cpu conversions in crb_acpi_add()
vTPM: set virtual device before passing to ibmvtpm_reset_crq
tpm_ibmvtpm: remove unneccessary message level.
ima: update builtin policies
ima: extend "mask" policy matching support
ima: add support for new "euid" policy condition
ima: fix ima_show_template_data_ascii()
Smack: freeing an error pointer in smk_write_revoke_subj()
selinux: fix setting of security labels on NFS
selinux: Remove unused permission definitions
selinux: enable genfscon labeling for sysfs and pstore files
selinux: enable per-file labeling for debugfs files.
selinux: update netlink socket classes
signals: don't abuse __flush_signals() in selinux_bprm_committed_creds()
selinux: Print 'sclass' as string when unrecognized netlink message occurs
Smack: allow multiple labels in onlycap
Smack: fix seq operations in smackfs
ima: pass iint to ima_add_violation()
ima: wrap event related data to the new ima_event_data structure
integrity: add validity checks for 'path' parameter
...
This commit is contained in:
+1
-1
@@ -14,7 +14,7 @@ obj-y += commoncap.o
|
||||
obj-$(CONFIG_MMU) += min_addr.o
|
||||
|
||||
# Object file lists
|
||||
obj-$(CONFIG_SECURITY) += security.o capability.o
|
||||
obj-$(CONFIG_SECURITY) += security.o
|
||||
obj-$(CONFIG_SECURITYFS) += inode.o
|
||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
|
||||
obj-$(CONFIG_SECURITY_SMACK) += smack/
|
||||
|
||||
@@ -347,9 +347,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
|
||||
file_inode(bprm->file)->i_mode
|
||||
};
|
||||
const char *name = NULL, *target = NULL, *info = NULL;
|
||||
int error = cap_bprm_set_creds(bprm);
|
||||
if (error)
|
||||
return error;
|
||||
int error = 0;
|
||||
|
||||
if (bprm->cred_prepared)
|
||||
return 0;
|
||||
@@ -531,15 +529,13 @@ cleanup:
|
||||
*/
|
||||
int apparmor_bprm_secureexec(struct linux_binprm *bprm)
|
||||
{
|
||||
int ret = cap_bprm_secureexec(bprm);
|
||||
|
||||
/* the decision to use secure exec is computed in set_creds
|
||||
* and stored in bprm->unsafe.
|
||||
*/
|
||||
if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
|
||||
ret = 1;
|
||||
if (bprm->unsafe & AA_SECURE_X_NEEDED)
|
||||
return 1;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+48
-71
@@ -12,7 +12,7 @@
|
||||
* License.
|
||||
*/
|
||||
|
||||
#include <linux/security.h>
|
||||
#include <linux/lsm_hooks.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
@@ -96,19 +96,11 @@ static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
|
||||
static int apparmor_ptrace_access_check(struct task_struct *child,
|
||||
unsigned int mode)
|
||||
{
|
||||
int error = cap_ptrace_access_check(child, mode);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return aa_ptrace(current, child, mode);
|
||||
}
|
||||
|
||||
static int apparmor_ptrace_traceme(struct task_struct *parent)
|
||||
{
|
||||
int error = cap_ptrace_traceme(parent);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
|
||||
}
|
||||
|
||||
@@ -123,10 +115,10 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
|
||||
cred = __task_cred(target);
|
||||
profile = aa_cred_profile(cred);
|
||||
|
||||
*effective = cred->cap_effective;
|
||||
*inheritable = cred->cap_inheritable;
|
||||
*permitted = cred->cap_permitted;
|
||||
|
||||
/*
|
||||
* cap_capget is stacked ahead of this and will
|
||||
* initialize effective and permitted.
|
||||
*/
|
||||
if (!unconfined(profile) && !COMPLAIN_MODE(profile)) {
|
||||
*effective = cap_intersect(*effective, profile->caps.allow);
|
||||
*permitted = cap_intersect(*permitted, profile->caps.allow);
|
||||
@@ -140,13 +132,11 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit)
|
||||
{
|
||||
struct aa_profile *profile;
|
||||
/* cap_capable returns 0 on success, else -EPERM */
|
||||
int error = cap_capable(cred, ns, cap, audit);
|
||||
if (!error) {
|
||||
profile = aa_cred_profile(cred);
|
||||
if (!unconfined(profile))
|
||||
error = aa_capable(profile, cap, audit);
|
||||
}
|
||||
int error = 0;
|
||||
|
||||
profile = aa_cred_profile(cred);
|
||||
if (!unconfined(profile))
|
||||
error = aa_capable(profile, cap, audit);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -615,49 +605,46 @@ static int apparmor_task_setrlimit(struct task_struct *task,
|
||||
return error;
|
||||
}
|
||||
|
||||
static struct security_operations apparmor_ops = {
|
||||
.name = "apparmor",
|
||||
static struct security_hook_list apparmor_hooks[] = {
|
||||
LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
|
||||
LSM_HOOK_INIT(capget, apparmor_capget),
|
||||
LSM_HOOK_INIT(capable, apparmor_capable),
|
||||
|
||||
.ptrace_access_check = apparmor_ptrace_access_check,
|
||||
.ptrace_traceme = apparmor_ptrace_traceme,
|
||||
.capget = apparmor_capget,
|
||||
.capable = apparmor_capable,
|
||||
LSM_HOOK_INIT(path_link, apparmor_path_link),
|
||||
LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
|
||||
LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
|
||||
LSM_HOOK_INIT(path_mkdir, apparmor_path_mkdir),
|
||||
LSM_HOOK_INIT(path_rmdir, apparmor_path_rmdir),
|
||||
LSM_HOOK_INIT(path_mknod, apparmor_path_mknod),
|
||||
LSM_HOOK_INIT(path_rename, apparmor_path_rename),
|
||||
LSM_HOOK_INIT(path_chmod, apparmor_path_chmod),
|
||||
LSM_HOOK_INIT(path_chown, apparmor_path_chown),
|
||||
LSM_HOOK_INIT(path_truncate, apparmor_path_truncate),
|
||||
LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr),
|
||||
|
||||
.path_link = apparmor_path_link,
|
||||
.path_unlink = apparmor_path_unlink,
|
||||
.path_symlink = apparmor_path_symlink,
|
||||
.path_mkdir = apparmor_path_mkdir,
|
||||
.path_rmdir = apparmor_path_rmdir,
|
||||
.path_mknod = apparmor_path_mknod,
|
||||
.path_rename = apparmor_path_rename,
|
||||
.path_chmod = apparmor_path_chmod,
|
||||
.path_chown = apparmor_path_chown,
|
||||
.path_truncate = apparmor_path_truncate,
|
||||
.inode_getattr = apparmor_inode_getattr,
|
||||
LSM_HOOK_INIT(file_open, apparmor_file_open),
|
||||
LSM_HOOK_INIT(file_permission, apparmor_file_permission),
|
||||
LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security),
|
||||
LSM_HOOK_INIT(file_free_security, apparmor_file_free_security),
|
||||
LSM_HOOK_INIT(mmap_file, apparmor_mmap_file),
|
||||
LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect),
|
||||
LSM_HOOK_INIT(file_lock, apparmor_file_lock),
|
||||
|
||||
.file_open = apparmor_file_open,
|
||||
.file_permission = apparmor_file_permission,
|
||||
.file_alloc_security = apparmor_file_alloc_security,
|
||||
.file_free_security = apparmor_file_free_security,
|
||||
.mmap_file = apparmor_mmap_file,
|
||||
.mmap_addr = cap_mmap_addr,
|
||||
.file_mprotect = apparmor_file_mprotect,
|
||||
.file_lock = apparmor_file_lock,
|
||||
LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
|
||||
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
|
||||
|
||||
.getprocattr = apparmor_getprocattr,
|
||||
.setprocattr = apparmor_setprocattr,
|
||||
LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
|
||||
LSM_HOOK_INIT(cred_free, apparmor_cred_free),
|
||||
LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
|
||||
LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer),
|
||||
|
||||
.cred_alloc_blank = apparmor_cred_alloc_blank,
|
||||
.cred_free = apparmor_cred_free,
|
||||
.cred_prepare = apparmor_cred_prepare,
|
||||
.cred_transfer = apparmor_cred_transfer,
|
||||
LSM_HOOK_INIT(bprm_set_creds, apparmor_bprm_set_creds),
|
||||
LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds),
|
||||
LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
|
||||
LSM_HOOK_INIT(bprm_secureexec, apparmor_bprm_secureexec),
|
||||
|
||||
.bprm_set_creds = apparmor_bprm_set_creds,
|
||||
.bprm_committing_creds = apparmor_bprm_committing_creds,
|
||||
.bprm_committed_creds = apparmor_bprm_committed_creds,
|
||||
.bprm_secureexec = apparmor_bprm_secureexec,
|
||||
|
||||
.task_setrlimit = apparmor_task_setrlimit,
|
||||
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -898,7 +885,7 @@ static int __init apparmor_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
|
||||
if (!apparmor_enabled || !security_module_enable("apparmor")) {
|
||||
aa_info_message("AppArmor disabled by boot time parameter");
|
||||
apparmor_enabled = 0;
|
||||
return 0;
|
||||
@@ -913,17 +900,10 @@ static int __init apparmor_init(void)
|
||||
error = set_init_cxt();
|
||||
if (error) {
|
||||
AA_ERROR("Failed to set context on init task\n");
|
||||
goto register_security_out;
|
||||
}
|
||||
|
||||
error = register_security(&apparmor_ops);
|
||||
if (error) {
|
||||
struct cred *cred = (struct cred *)current->real_cred;
|
||||
aa_free_task_context(cred_cxt(cred));
|
||||
cred_cxt(cred) = NULL;
|
||||
AA_ERROR("Unable to register AppArmor\n");
|
||||
goto register_security_out;
|
||||
aa_free_root_ns();
|
||||
goto alloc_out;
|
||||
}
|
||||
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks));
|
||||
|
||||
/* Report that AppArmor successfully initialized */
|
||||
apparmor_initialized = 1;
|
||||
@@ -936,9 +916,6 @@ static int __init apparmor_init(void)
|
||||
|
||||
return error;
|
||||
|
||||
register_security_out:
|
||||
aa_free_root_ns();
|
||||
|
||||
alloc_out:
|
||||
aa_destroy_aafs();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+33
-8
@@ -12,7 +12,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/lsm_hooks.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
@@ -53,11 +53,6 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
|
||||
}
|
||||
}
|
||||
|
||||
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cap_capable - Determine whether a task has a particular effective capability
|
||||
* @cred: The credentials to use
|
||||
@@ -941,7 +936,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
* @pages: The size of the mapping
|
||||
*
|
||||
* Determine whether the allocation of a new virtual mapping by the current
|
||||
* task is permitted, returning 0 if permission is granted, -ve if not.
|
||||
* task is permitted, returning 1 if permission is granted, 0 if not.
|
||||
*/
|
||||
int cap_vm_enough_memory(struct mm_struct *mm, long pages)
|
||||
{
|
||||
@@ -950,7 +945,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
|
||||
if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
|
||||
SECURITY_CAP_NOAUDIT) == 0)
|
||||
cap_sys_admin = 1;
|
||||
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
||||
return cap_sys_admin;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -981,3 +976,33 @@ int cap_mmap_file(struct file *file, unsigned long reqprot,
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY
|
||||
|
||||
struct security_hook_list capability_hooks[] = {
|
||||
LSM_HOOK_INIT(capable, cap_capable),
|
||||
LSM_HOOK_INIT(settime, cap_settime),
|
||||
LSM_HOOK_INIT(ptrace_access_check, cap_ptrace_access_check),
|
||||
LSM_HOOK_INIT(ptrace_traceme, cap_ptrace_traceme),
|
||||
LSM_HOOK_INIT(capget, cap_capget),
|
||||
LSM_HOOK_INIT(capset, cap_capset),
|
||||
LSM_HOOK_INIT(bprm_set_creds, cap_bprm_set_creds),
|
||||
LSM_HOOK_INIT(bprm_secureexec, cap_bprm_secureexec),
|
||||
LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv),
|
||||
LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv),
|
||||
LSM_HOOK_INIT(mmap_addr, cap_mmap_addr),
|
||||
LSM_HOOK_INIT(mmap_file, cap_mmap_file),
|
||||
LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid),
|
||||
LSM_HOOK_INIT(task_prctl, cap_task_prctl),
|
||||
LSM_HOOK_INIT(task_setscheduler, cap_task_setscheduler),
|
||||
LSM_HOOK_INIT(task_setioprio, cap_task_setioprio),
|
||||
LSM_HOOK_INIT(task_setnice, cap_task_setnice),
|
||||
LSM_HOOK_INIT(vm_enough_memory, cap_vm_enough_memory),
|
||||
};
|
||||
|
||||
void __init capability_add_hooks(void)
|
||||
{
|
||||
security_add_hooks(capability_hooks, ARRAY_SIZE(capability_hooks));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_SECURITY */
|
||||
|
||||
@@ -85,7 +85,7 @@ int __init integrity_init_keyring(const unsigned int id)
|
||||
return err;
|
||||
}
|
||||
|
||||
int __init integrity_load_x509(const unsigned int id, char *path)
|
||||
int __init integrity_load_x509(const unsigned int id, const char *path)
|
||||
{
|
||||
key_ref_t key;
|
||||
char *data;
|
||||
|
||||
@@ -296,6 +296,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
|
||||
iint = integrity_iint_find(d_backing_inode(dentry));
|
||||
if (iint && (iint->flags & IMA_NEW_FILE))
|
||||
return 0;
|
||||
|
||||
/* exception for pseudo filesystems */
|
||||
if (dentry->d_inode->i_sb->s_magic == TMPFS_MAGIC
|
||||
|| dentry->d_inode->i_sb->s_magic == SYSFS_MAGIC)
|
||||
return 0;
|
||||
|
||||
integrity_audit_msg(AUDIT_INTEGRITY_METADATA,
|
||||
dentry->d_inode, dentry->d_name.name,
|
||||
"update_metadata",
|
||||
integrity_status_msg[evm_status],
|
||||
-EPERM, 0);
|
||||
}
|
||||
out:
|
||||
if (evm_status != INTEGRITY_PASS)
|
||||
@@ -376,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
|
||||
* @xattr_name: pointer to the affected extended attribute name
|
||||
*
|
||||
* Update the HMAC stored in 'security.evm' to reflect removal of the xattr.
|
||||
*
|
||||
* No need to take the i_mutex lock here, as this function is called from
|
||||
* vfs_removexattr() which takes the i_mutex.
|
||||
*/
|
||||
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
|
||||
{
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
|
||||
if (!evm_initialized || !evm_protected_xattr(xattr_name))
|
||||
return;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
evm_update_evmxattr(dentry, xattr_name, NULL, 0);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -213,6 +213,9 @@ int __init integrity_read_file(const char *path, char **data)
|
||||
char *buf;
|
||||
int rc = -EINVAL;
|
||||
|
||||
if (!path || !*path)
|
||||
return -EINVAL;
|
||||
|
||||
file = filp_open(path, O_RDONLY, 0);
|
||||
if (IS_ERR(file)) {
|
||||
rc = PTR_ERR(file);
|
||||
|
||||
@@ -52,6 +52,16 @@ extern int ima_used_chip;
|
||||
extern int ima_hash_algo;
|
||||
extern int ima_appraise;
|
||||
|
||||
/* IMA event related data */
|
||||
struct ima_event_data {
|
||||
struct integrity_iint_cache *iint;
|
||||
struct file *file;
|
||||
const unsigned char *filename;
|
||||
struct evm_ima_xattr_data *xattr_value;
|
||||
int xattr_len;
|
||||
const char *violation;
|
||||
};
|
||||
|
||||
/* IMA template field data definition */
|
||||
struct ima_field_data {
|
||||
u8 *data;
|
||||
@@ -61,12 +71,10 @@ struct ima_field_data {
|
||||
/* IMA template field definition */
|
||||
struct ima_template_field {
|
||||
const char field_id[IMA_TEMPLATE_FIELD_ID_MAX_LEN];
|
||||
int (*field_init) (struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, struct ima_field_data *field_data);
|
||||
void (*field_show) (struct seq_file *m, enum ima_show_type show,
|
||||
struct ima_field_data *field_data);
|
||||
int (*field_init)(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
void (*field_show)(struct seq_file *m, enum ima_show_type show,
|
||||
struct ima_field_data *field_data);
|
||||
};
|
||||
|
||||
/* IMA template descriptor definition */
|
||||
@@ -103,10 +111,11 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data,
|
||||
struct ima_digest_data *hash);
|
||||
int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
|
||||
void ima_add_violation(struct file *file, const unsigned char *filename,
|
||||
struct integrity_iint_cache *iint,
|
||||
const char *op, const char *cause);
|
||||
int ima_init_crypto(void);
|
||||
void ima_putc(struct seq_file *m, void *data, int datalen);
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, int size);
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
|
||||
struct ima_template_desc *ima_template_desc_current(void);
|
||||
int ima_init_template(void);
|
||||
|
||||
@@ -140,10 +149,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
|
||||
int xattr_len);
|
||||
void ima_audit_measurement(struct integrity_iint_cache *iint,
|
||||
const unsigned char *filename);
|
||||
int ima_alloc_init_template(struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, struct ima_template_entry **entry);
|
||||
int ima_alloc_init_template(struct ima_event_data *event_data,
|
||||
struct ima_template_entry **entry);
|
||||
int ima_store_template(struct ima_template_entry *entry, int violation,
|
||||
struct inode *inode, const unsigned char *filename);
|
||||
void ima_free_template_entry(struct ima_template_entry *entry);
|
||||
|
||||
@@ -37,10 +37,8 @@ void ima_free_template_entry(struct ima_template_entry *entry)
|
||||
/*
|
||||
* ima_alloc_init_template - create and initialize a new template entry
|
||||
*/
|
||||
int ima_alloc_init_template(struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, struct ima_template_entry **entry)
|
||||
int ima_alloc_init_template(struct ima_event_data *event_data,
|
||||
struct ima_template_entry **entry)
|
||||
{
|
||||
struct ima_template_desc *template_desc = ima_template_desc_current();
|
||||
int i, result = 0;
|
||||
@@ -55,8 +53,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint,
|
||||
struct ima_template_field *field = template_desc->fields[i];
|
||||
u32 len;
|
||||
|
||||
result = field->field_init(iint, file, filename,
|
||||
xattr_value, xattr_len,
|
||||
result = field->field_init(event_data,
|
||||
&((*entry)->template_data[i]));
|
||||
if (result != 0)
|
||||
goto out;
|
||||
@@ -129,18 +126,20 @@ int ima_store_template(struct ima_template_entry *entry,
|
||||
* value is invalidated.
|
||||
*/
|
||||
void ima_add_violation(struct file *file, const unsigned char *filename,
|
||||
struct integrity_iint_cache *iint,
|
||||
const char *op, const char *cause)
|
||||
{
|
||||
struct ima_template_entry *entry;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct ima_event_data event_data = {iint, file, filename, NULL, 0,
|
||||
cause};
|
||||
int violation = 1;
|
||||
int result;
|
||||
|
||||
/* can overflow, only indicator */
|
||||
atomic_long_inc(&ima_htable.violations);
|
||||
|
||||
result = ima_alloc_init_template(NULL, file, filename,
|
||||
NULL, 0, &entry);
|
||||
result = ima_alloc_init_template(&event_data, &entry);
|
||||
if (result < 0) {
|
||||
result = -ENOMEM;
|
||||
goto err_out;
|
||||
@@ -267,13 +266,14 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
|
||||
int result = -ENOMEM;
|
||||
struct inode *inode = file_inode(file);
|
||||
struct ima_template_entry *entry;
|
||||
struct ima_event_data event_data = {iint, file, filename, xattr_value,
|
||||
xattr_len, NULL};
|
||||
int violation = 0;
|
||||
|
||||
if (iint->flags & IMA_MEASURED)
|
||||
return;
|
||||
|
||||
result = ima_alloc_init_template(iint, file, filename,
|
||||
xattr_value, xattr_len, &entry);
|
||||
result = ima_alloc_init_template(&event_data, &entry);
|
||||
if (result < 0) {
|
||||
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
|
||||
op, audit_cause, result, 0);
|
||||
|
||||
@@ -378,10 +378,14 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
|
||||
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
|
||||
xattr_value_len);
|
||||
if (result == 1) {
|
||||
bool digsig;
|
||||
|
||||
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
|
||||
return -EINVAL;
|
||||
ima_reset_appraise_flags(d_backing_inode(dentry),
|
||||
(xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
|
||||
digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
|
||||
if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE))
|
||||
return -EPERM;
|
||||
ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -190,9 +190,9 @@ static const struct file_operations ima_measurements_ops = {
|
||||
.release = seq_release,
|
||||
};
|
||||
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, int size)
|
||||
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
|
||||
{
|
||||
int i;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
seq_printf(m, "%02x", *(digest + i));
|
||||
|
||||
@@ -24,12 +24,6 @@
|
||||
#include <crypto/hash_info.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 */
|
||||
static const char *boot_aggregate_name = "boot_aggregate";
|
||||
int ima_used_chip;
|
||||
@@ -55,6 +49,8 @@ static int __init ima_add_boot_aggregate(void)
|
||||
const char *audit_cause = "ENOMEM";
|
||||
struct ima_template_entry *entry;
|
||||
struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
|
||||
struct ima_event_data event_data = {iint, NULL, boot_aggregate_name,
|
||||
NULL, 0, NULL};
|
||||
int result = -ENOMEM;
|
||||
int violation = 0;
|
||||
struct {
|
||||
@@ -76,8 +72,7 @@ static int __init ima_add_boot_aggregate(void)
|
||||
}
|
||||
}
|
||||
|
||||
result = ima_alloc_init_template(iint, NULL, boot_aggregate_name,
|
||||
NULL, 0, &entry);
|
||||
result = ima_alloc_init_template(&event_data, &entry);
|
||||
if (result < 0) {
|
||||
audit_cause = "alloc_entry";
|
||||
goto err_out;
|
||||
@@ -103,7 +98,7 @@ 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);
|
||||
integrity_load_x509(INTEGRITY_KEYRING_IMA, CONFIG_IMA_X509_PATH);
|
||||
ima_policy_flag |= unset_flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -106,9 +106,10 @@ static void ima_rdwr_violation_check(struct file *file,
|
||||
*pathname = ima_d_path(&file->f_path, pathbuf);
|
||||
|
||||
if (send_tomtou)
|
||||
ima_add_violation(file, *pathname, "invalid_pcr", "ToMToU");
|
||||
ima_add_violation(file, *pathname, iint,
|
||||
"invalid_pcr", "ToMToU");
|
||||
if (send_writers)
|
||||
ima_add_violation(file, *pathname,
|
||||
ima_add_violation(file, *pathname, iint,
|
||||
"invalid_pcr", "open_writers");
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#define IMA_UID 0x0008
|
||||
#define IMA_FOWNER 0x0010
|
||||
#define IMA_FSUUID 0x0020
|
||||
#define IMA_INMASK 0x0040
|
||||
#define IMA_EUID 0x0080
|
||||
|
||||
#define UNKNOWN 0
|
||||
#define MEASURE 0x0001 /* same as IMA_MEASURE */
|
||||
@@ -42,6 +44,8 @@ enum lsm_rule_types { LSM_OBJ_USER, LSM_OBJ_ROLE, LSM_OBJ_TYPE,
|
||||
LSM_SUBJ_USER, LSM_SUBJ_ROLE, LSM_SUBJ_TYPE
|
||||
};
|
||||
|
||||
enum policy_types { ORIGINAL_TCB = 1, DEFAULT_TCB };
|
||||
|
||||
struct ima_rule_entry {
|
||||
struct list_head list;
|
||||
int action;
|
||||
@@ -70,7 +74,7 @@ struct ima_rule_entry {
|
||||
* normal users can easily run the machine out of memory simply building
|
||||
* and running executables.
|
||||
*/
|
||||
static struct ima_rule_entry default_rules[] = {
|
||||
static struct ima_rule_entry dont_measure_rules[] = {
|
||||
{.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
@@ -79,12 +83,31 @@ static struct ima_rule_entry default_rules[] = {
|
||||
{.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
|
||||
.flags = IMA_FSMAGIC},
|
||||
{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
|
||||
};
|
||||
|
||||
static struct ima_rule_entry original_measurement_rules[] = {
|
||||
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
|
||||
.flags = IMA_FUNC | IMA_MASK | IMA_UID},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_MASK | IMA_UID},
|
||||
{.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
|
||||
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
|
||||
};
|
||||
|
||||
static struct ima_rule_entry default_measurement_rules[] = {
|
||||
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
|
||||
.flags = IMA_FUNC | IMA_MASK},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_EUID},
|
||||
{.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ,
|
||||
.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},
|
||||
};
|
||||
@@ -99,6 +122,7 @@ static struct ima_rule_entry default_appraise_rules[] = {
|
||||
{.action = DONT_APPRAISE, .fsmagic = BINFMTFS_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 = NSFS_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},
|
||||
@@ -115,14 +139,29 @@ static struct list_head *ima_rules;
|
||||
|
||||
static DEFINE_MUTEX(ima_rules_mutex);
|
||||
|
||||
static bool ima_use_tcb __initdata;
|
||||
static int ima_policy __initdata;
|
||||
static int __init default_measure_policy_setup(char *str)
|
||||
{
|
||||
ima_use_tcb = 1;
|
||||
if (ima_policy)
|
||||
return 1;
|
||||
|
||||
ima_policy = ORIGINAL_TCB;
|
||||
return 1;
|
||||
}
|
||||
__setup("ima_tcb", default_measure_policy_setup);
|
||||
|
||||
static int __init policy_setup(char *str)
|
||||
{
|
||||
if (ima_policy)
|
||||
return 1;
|
||||
|
||||
if (strcmp(str, "tcb") == 0)
|
||||
ima_policy = DEFAULT_TCB;
|
||||
|
||||
return 1;
|
||||
}
|
||||
__setup("ima_policy=", policy_setup);
|
||||
|
||||
static bool ima_use_appraise_tcb __initdata;
|
||||
static int __init default_appraise_policy_setup(char *str)
|
||||
{
|
||||
@@ -182,6 +221,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
||||
if ((rule->flags & IMA_MASK) &&
|
||||
(rule->mask != mask && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_INMASK) &&
|
||||
(!(rule->mask & mask) && func != POST_SETATTR))
|
||||
return false;
|
||||
if ((rule->flags & IMA_FSMAGIC)
|
||||
&& rule->fsmagic != inode->i_sb->s_magic)
|
||||
return false;
|
||||
@@ -190,6 +232,16 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
||||
return false;
|
||||
if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
|
||||
return false;
|
||||
if (rule->flags & IMA_EUID) {
|
||||
if (has_capability_noaudit(current, CAP_SETUID)) {
|
||||
if (!uid_eq(rule->uid, cred->euid)
|
||||
&& !uid_eq(rule->uid, cred->suid)
|
||||
&& !uid_eq(rule->uid, cred->uid))
|
||||
return false;
|
||||
} else if (!uid_eq(rule->uid, cred->euid))
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
|
||||
return false;
|
||||
for (i = 0; i < MAX_LSM_RULES; i++) {
|
||||
@@ -333,21 +385,31 @@ void __init ima_init_policy(void)
|
||||
{
|
||||
int i, measure_entries, appraise_entries;
|
||||
|
||||
/* if !ima_use_tcb set entries = 0 so we load NO default rules */
|
||||
measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
|
||||
/* if !ima_policy set entries = 0 so we load NO default rules */
|
||||
measure_entries = ima_policy ? ARRAY_SIZE(dont_measure_rules) : 0;
|
||||
appraise_entries = ima_use_appraise_tcb ?
|
||||
ARRAY_SIZE(default_appraise_rules) : 0;
|
||||
|
||||
for (i = 0; i < measure_entries + appraise_entries; i++) {
|
||||
if (i < measure_entries)
|
||||
list_add_tail(&default_rules[i].list,
|
||||
&ima_default_rules);
|
||||
else {
|
||||
int j = i - measure_entries;
|
||||
for (i = 0; i < measure_entries; i++)
|
||||
list_add_tail(&dont_measure_rules[i].list, &ima_default_rules);
|
||||
|
||||
list_add_tail(&default_appraise_rules[j].list,
|
||||
switch (ima_policy) {
|
||||
case ORIGINAL_TCB:
|
||||
for (i = 0; i < ARRAY_SIZE(original_measurement_rules); i++)
|
||||
list_add_tail(&original_measurement_rules[i].list,
|
||||
&ima_default_rules);
|
||||
}
|
||||
break;
|
||||
case DEFAULT_TCB:
|
||||
for (i = 0; i < ARRAY_SIZE(default_measurement_rules); i++)
|
||||
list_add_tail(&default_measurement_rules[i].list,
|
||||
&ima_default_rules);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < appraise_entries; i++) {
|
||||
list_add_tail(&default_appraise_rules[i].list,
|
||||
&ima_default_rules);
|
||||
}
|
||||
|
||||
ima_rules = &ima_default_rules;
|
||||
@@ -373,7 +435,8 @@ enum {
|
||||
Opt_audit,
|
||||
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
||||
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
||||
Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
|
||||
Opt_func, Opt_mask, Opt_fsmagic,
|
||||
Opt_uid, Opt_euid, Opt_fowner,
|
||||
Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
|
||||
};
|
||||
|
||||
@@ -394,6 +457,7 @@ static match_table_t policy_tokens = {
|
||||
{Opt_fsmagic, "fsmagic=%s"},
|
||||
{Opt_fsuuid, "fsuuid=%s"},
|
||||
{Opt_uid, "uid=%s"},
|
||||
{Opt_euid, "euid=%s"},
|
||||
{Opt_fowner, "fowner=%s"},
|
||||
{Opt_appraise_type, "appraise_type=%s"},
|
||||
{Opt_permit_directio, "permit_directio"},
|
||||
@@ -435,6 +499,7 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
|
||||
static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
char *from;
|
||||
char *p;
|
||||
int result = 0;
|
||||
|
||||
@@ -525,18 +590,23 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
if (entry->mask)
|
||||
result = -EINVAL;
|
||||
|
||||
if ((strcmp(args[0].from, "MAY_EXEC")) == 0)
|
||||
from = args[0].from;
|
||||
if (*from == '^')
|
||||
from++;
|
||||
|
||||
if ((strcmp(from, "MAY_EXEC")) == 0)
|
||||
entry->mask = MAY_EXEC;
|
||||
else if (strcmp(args[0].from, "MAY_WRITE") == 0)
|
||||
else if (strcmp(from, "MAY_WRITE") == 0)
|
||||
entry->mask = MAY_WRITE;
|
||||
else if (strcmp(args[0].from, "MAY_READ") == 0)
|
||||
else if (strcmp(from, "MAY_READ") == 0)
|
||||
entry->mask = MAY_READ;
|
||||
else if (strcmp(args[0].from, "MAY_APPEND") == 0)
|
||||
else if (strcmp(from, "MAY_APPEND") == 0)
|
||||
entry->mask = MAY_APPEND;
|
||||
else
|
||||
result = -EINVAL;
|
||||
if (!result)
|
||||
entry->flags |= IMA_MASK;
|
||||
entry->flags |= (*args[0].from == '^')
|
||||
? IMA_INMASK : IMA_MASK;
|
||||
break;
|
||||
case Opt_fsmagic:
|
||||
ima_log_string(ab, "fsmagic", args[0].from);
|
||||
@@ -566,6 +636,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
break;
|
||||
case Opt_uid:
|
||||
ima_log_string(ab, "uid", args[0].from);
|
||||
case Opt_euid:
|
||||
if (token == Opt_euid)
|
||||
ima_log_string(ab, "euid", args[0].from);
|
||||
|
||||
if (uid_valid(entry->uid)) {
|
||||
result = -EINVAL;
|
||||
@@ -574,11 +647,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||
|
||||
result = kstrtoul(args[0].from, 10, &lnum);
|
||||
if (!result) {
|
||||
entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
|
||||
if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
|
||||
entry->uid = make_kuid(current_user_ns(),
|
||||
(uid_t) lnum);
|
||||
if (!uid_valid(entry->uid) ||
|
||||
(uid_t)lnum != lnum)
|
||||
result = -EINVAL;
|
||||
else
|
||||
entry->flags |= IMA_UID;
|
||||
entry->flags |= (token == Opt_uid)
|
||||
? IMA_UID : IMA_EUID;
|
||||
}
|
||||
break;
|
||||
case Opt_fowner:
|
||||
|
||||
@@ -70,7 +70,8 @@ static void ima_show_template_data_ascii(struct seq_file *m,
|
||||
enum data_formats datafmt,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
u8 *buf_ptr = field_data->data, buflen = field_data->len;
|
||||
u8 *buf_ptr = field_data->data;
|
||||
u32 buflen = field_data->len;
|
||||
|
||||
switch (datafmt) {
|
||||
case DATA_FMT_DIGEST_WITH_ALGO:
|
||||
@@ -195,9 +196,7 @@ static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo,
|
||||
/*
|
||||
* This function writes the digest of an event (with size limit).
|
||||
*/
|
||||
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventdigest_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
struct {
|
||||
@@ -211,25 +210,25 @@ int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
|
||||
memset(&hash, 0, sizeof(hash));
|
||||
|
||||
if (!iint) /* recording a violation. */
|
||||
if (event_data->violation) /* recording a violation. */
|
||||
goto out;
|
||||
|
||||
if (ima_template_hash_algo_allowed(iint->ima_hash->algo)) {
|
||||
cur_digest = iint->ima_hash->digest;
|
||||
cur_digestsize = iint->ima_hash->length;
|
||||
if (ima_template_hash_algo_allowed(event_data->iint->ima_hash->algo)) {
|
||||
cur_digest = event_data->iint->ima_hash->digest;
|
||||
cur_digestsize = event_data->iint->ima_hash->length;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!file) /* missing info to re-calculate the digest */
|
||||
if (!event_data->file) /* missing info to re-calculate the digest */
|
||||
return -EINVAL;
|
||||
|
||||
inode = file_inode(file);
|
||||
inode = file_inode(event_data->file);
|
||||
hash.hdr.algo = ima_template_hash_algo_allowed(ima_hash_algo) ?
|
||||
ima_hash_algo : HASH_ALGO_SHA1;
|
||||
result = ima_calc_file_hash(file, &hash.hdr);
|
||||
result = ima_calc_file_hash(event_data->file, &hash.hdr);
|
||||
if (result) {
|
||||
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
|
||||
filename, "collect_data",
|
||||
event_data->filename, "collect_data",
|
||||
"failed", result, 0);
|
||||
return result;
|
||||
}
|
||||
@@ -243,48 +242,43 @@ out:
|
||||
/*
|
||||
* This function writes the digest of an event (without size limit).
|
||||
*/
|
||||
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, struct ima_field_data *field_data)
|
||||
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1;
|
||||
u32 cur_digestsize = 0;
|
||||
|
||||
/* If iint is NULL, we are recording a violation. */
|
||||
if (!iint)
|
||||
if (event_data->violation) /* recording a violation. */
|
||||
goto out;
|
||||
|
||||
cur_digest = iint->ima_hash->digest;
|
||||
cur_digestsize = iint->ima_hash->length;
|
||||
cur_digest = event_data->iint->ima_hash->digest;
|
||||
cur_digestsize = event_data->iint->ima_hash->length;
|
||||
|
||||
hash_algo = iint->ima_hash->algo;
|
||||
hash_algo = event_data->iint->ima_hash->algo;
|
||||
out:
|
||||
return ima_eventdigest_init_common(cur_digest, cur_digestsize,
|
||||
hash_algo, field_data);
|
||||
}
|
||||
|
||||
static int ima_eventname_init_common(struct integrity_iint_cache *iint,
|
||||
struct file *file,
|
||||
const unsigned char *filename,
|
||||
static int ima_eventname_init_common(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data,
|
||||
bool size_limit)
|
||||
{
|
||||
const char *cur_filename = NULL;
|
||||
u32 cur_filename_len = 0;
|
||||
|
||||
BUG_ON(filename == NULL && file == NULL);
|
||||
BUG_ON(event_data->filename == NULL && event_data->file == NULL);
|
||||
|
||||
if (filename) {
|
||||
cur_filename = filename;
|
||||
cur_filename_len = strlen(filename);
|
||||
if (event_data->filename) {
|
||||
cur_filename = event_data->filename;
|
||||
cur_filename_len = strlen(event_data->filename);
|
||||
|
||||
if (!size_limit || cur_filename_len <= IMA_EVENT_NAME_LEN_MAX)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
cur_filename = file->f_path.dentry->d_name.name;
|
||||
if (event_data->file) {
|
||||
cur_filename = event_data->file->f_path.dentry->d_name.name;
|
||||
cur_filename_len = strlen(cur_filename);
|
||||
} else
|
||||
/*
|
||||
@@ -300,36 +294,30 @@ out:
|
||||
/*
|
||||
* This function writes the name of an event (with size limit).
|
||||
*/
|
||||
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventname_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
return ima_eventname_init_common(iint, file, filename,
|
||||
field_data, true);
|
||||
return ima_eventname_init_common(event_data, field_data, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function writes the name of an event (without size limit).
|
||||
*/
|
||||
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventname_ng_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
return ima_eventname_init_common(iint, file, filename,
|
||||
field_data, false);
|
||||
return ima_eventname_init_common(event_data, field_data, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* ima_eventsig_init - include the file signature as part of the template data
|
||||
*/
|
||||
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventsig_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data)
|
||||
{
|
||||
enum data_formats fmt = DATA_FMT_HEX;
|
||||
struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
|
||||
int xattr_len = event_data->xattr_len;
|
||||
int rc = 0;
|
||||
|
||||
if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
|
||||
|
||||
@@ -26,24 +26,14 @@ void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
|
||||
struct ima_field_data *field_data);
|
||||
void ima_show_template_sig(struct seq_file *m, enum ima_show_type show,
|
||||
struct ima_field_data *field_data);
|
||||
int ima_eventdigest_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventdigest_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
int ima_eventname_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventname_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
int ima_eventdigest_ng_init(struct integrity_iint_cache *iint,
|
||||
struct file *file, const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value,
|
||||
int xattr_len, struct ima_field_data *field_data);
|
||||
int ima_eventname_ng_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventdigest_ng_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
int ima_eventname_ng_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
int ima_eventsig_init(struct integrity_iint_cache *iint, struct file *file,
|
||||
const unsigned char *filename,
|
||||
struct evm_ima_xattr_data *xattr_value, int xattr_len,
|
||||
int ima_eventsig_init(struct ima_event_data *event_data,
|
||||
struct ima_field_data *field_data);
|
||||
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
|
||||
|
||||
@@ -135,7 +135,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
|
||||
const char *digest, int digestlen);
|
||||
|
||||
int __init integrity_init_keyring(const unsigned int id);
|
||||
int __init integrity_load_x509(const unsigned int id, char *path);
|
||||
int __init integrity_load_x509(const unsigned int id, const char *path);
|
||||
#else
|
||||
|
||||
static inline int integrity_digsig_verify(const unsigned int id,
|
||||
|
||||
+676
-279
File diff suppressed because it is too large
Load Diff
+243
-286
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user