integrity-v6.19
-----BEGIN PGP SIGNATURE-----
iIoEABYKADIWIQQdXVVFGN5XqKr1Hj7LwZzRsCrn5QUCaS896BQcem9oYXJAbGlu
dXguaWJtLmNvbQAKCRDLwZzRsCrn5RDuAQDx4fmvctP8kc9PeRjd5X/UV1ip1pPD
beMKt8ghEThQiAEAzjFJbNGUDKhfR8yWODifAvYRurU5YQJZZI9wJ8skNw0=
=3Vc4
-----END PGP SIGNATURE-----
Merge tag 'integrity-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull integrity updates from Mimi Zohar:
"Bug fixes:
- defer credentials checking from the bprm_check_security hook to the
bprm_creds_from_file security hook
- properly ignore IMA policy rules based on undefined SELinux labels
IMA policy rule extensions:
- extend IMA to limit including file hashes in the audit logs
(dont_audit action)
- define a new filesystem subtype policy option (fs_subtype)
Misc:
- extend IMA to support in-kernel module decompression by deferring
the IMA signature verification in kernel_read_file() to after the
kernel module is decompressed"
* tag 'integrity-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
ima: Handle error code returned by ima_filter_rule_match()
ima: Access decompressed kernel module to verify appended signature
ima: add fs_subtype condition for distinguishing FUSE instances
ima: add dont_audit action to suppress audit actions
ima: Attach CREDS_CHECK IMA hook to bprm_creds_from_file LSM hook
pull/1354/merge
commit
777f817160
|
|
@ -20,9 +20,10 @@ Description:
|
||||||
rule format: action [condition ...]
|
rule format: action [condition ...]
|
||||||
|
|
||||||
action: measure | dont_measure | appraise | dont_appraise |
|
action: measure | dont_measure | appraise | dont_appraise |
|
||||||
audit | hash | dont_hash
|
audit | dont_audit | hash | dont_hash
|
||||||
condition:= base | lsm [option]
|
condition:= base | lsm [option]
|
||||||
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [fsname=]
|
base: [[func=] [mask=] [fsmagic=] [fsuuid=] [fsname=]
|
||||||
|
[fs_subtype=]
|
||||||
[uid=] [euid=] [gid=] [egid=]
|
[uid=] [euid=] [gid=] [egid=]
|
||||||
[fowner=] [fgroup=]]
|
[fowner=] [fgroup=]]
|
||||||
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
lsm: [[subj_user=] [subj_role=] [subj_type=]
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
id(KEXEC_INITRAMFS, kexec-initramfs) \
|
id(KEXEC_INITRAMFS, kexec-initramfs) \
|
||||||
id(POLICY, security-policy) \
|
id(POLICY, security-policy) \
|
||||||
id(X509_CERTIFICATE, x509-certificate) \
|
id(X509_CERTIFICATE, x509-certificate) \
|
||||||
|
id(MODULE_COMPRESSED, kernel-module-compressed) \
|
||||||
id(MAX_ID, )
|
id(MAX_ID, )
|
||||||
|
|
||||||
#define __fid_enumify(ENUM, dummy) READING_ ## ENUM,
|
#define __fid_enumify(ENUM, dummy) READING_ ## ENUM,
|
||||||
|
|
|
||||||
|
|
@ -3675,24 +3675,35 @@ static int idempotent_wait_for_completion(struct idempotent *u)
|
||||||
|
|
||||||
static int init_module_from_file(struct file *f, const char __user * uargs, int flags)
|
static int init_module_from_file(struct file *f, const char __user * uargs, int flags)
|
||||||
{
|
{
|
||||||
|
bool compressed = !!(flags & MODULE_INIT_COMPRESSED_FILE);
|
||||||
struct load_info info = { };
|
struct load_info info = { };
|
||||||
void *buf = NULL;
|
void *buf = NULL;
|
||||||
int len;
|
int len;
|
||||||
|
int err;
|
||||||
|
|
||||||
len = kernel_read_file(f, 0, &buf, INT_MAX, NULL, READING_MODULE);
|
len = kernel_read_file(f, 0, &buf, INT_MAX, NULL,
|
||||||
|
compressed ? READING_MODULE_COMPRESSED :
|
||||||
|
READING_MODULE);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
mod_stat_inc(&failed_kreads);
|
mod_stat_inc(&failed_kreads);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & MODULE_INIT_COMPRESSED_FILE) {
|
if (compressed) {
|
||||||
int err = module_decompress(&info, buf, len);
|
err = module_decompress(&info, buf, len);
|
||||||
vfree(buf); /* compressed data is no longer needed */
|
vfree(buf); /* compressed data is no longer needed */
|
||||||
if (err) {
|
if (err) {
|
||||||
mod_stat_inc(&failed_decompress);
|
mod_stat_inc(&failed_decompress);
|
||||||
mod_stat_add_long(len, &invalid_decompress_bytes);
|
mod_stat_add_long(len, &invalid_decompress_bytes);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
err = security_kernel_post_read_file(f, (char *)info.hdr, info.len,
|
||||||
|
READING_MODULE);
|
||||||
|
if (err) {
|
||||||
|
mod_stat_inc(&failed_kreads);
|
||||||
|
free_copy(&info, flags);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
info.hdr = buf;
|
info.hdr = buf;
|
||||||
info.len = len;
|
info.len = len;
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,8 @@ static void ima_file_free(struct file *file)
|
||||||
|
|
||||||
static int process_measurement(struct file *file, const struct cred *cred,
|
static int process_measurement(struct file *file, const struct cred *cred,
|
||||||
struct lsm_prop *prop, char *buf, loff_t size,
|
struct lsm_prop *prop, char *buf, loff_t size,
|
||||||
int mask, enum ima_hooks func)
|
int mask, enum ima_hooks func,
|
||||||
|
enum kernel_read_file_id read_id)
|
||||||
{
|
{
|
||||||
struct inode *real_inode, *inode = file_inode(file);
|
struct inode *real_inode, *inode = file_inode(file);
|
||||||
struct ima_iint_cache *iint = NULL;
|
struct ima_iint_cache *iint = NULL;
|
||||||
|
|
@ -406,6 +407,12 @@ static int process_measurement(struct file *file, const struct cred *cred,
|
||||||
if (rc != 0 && rc != -EBADF && rc != -EINVAL)
|
if (rc != 0 && rc != -EBADF && rc != -EINVAL)
|
||||||
goto out_locked;
|
goto out_locked;
|
||||||
|
|
||||||
|
/* Defer measuring/appraising kernel modules to READING_MODULE */
|
||||||
|
if (read_id == READING_MODULE_COMPRESSED) {
|
||||||
|
must_appraise = 0;
|
||||||
|
goto out_locked;
|
||||||
|
}
|
||||||
|
|
||||||
if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
|
if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
|
||||||
pathname = ima_d_path(&file->f_path, &pathbuf, filename);
|
pathname = ima_d_path(&file->f_path, &pathbuf, filename);
|
||||||
|
|
||||||
|
|
@ -486,14 +493,14 @@ static int ima_file_mmap(struct file *file, unsigned long reqprot,
|
||||||
|
|
||||||
if (reqprot & PROT_EXEC) {
|
if (reqprot & PROT_EXEC) {
|
||||||
ret = process_measurement(file, current_cred(), &prop, NULL,
|
ret = process_measurement(file, current_cred(), &prop, NULL,
|
||||||
0, MAY_EXEC, MMAP_CHECK_REQPROT);
|
0, MAY_EXEC, MMAP_CHECK_REQPROT, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prot & PROT_EXEC)
|
if (prot & PROT_EXEC)
|
||||||
return process_measurement(file, current_cred(), &prop, NULL,
|
return process_measurement(file, current_cred(), &prop, NULL,
|
||||||
0, MAY_EXEC, MMAP_CHECK);
|
0, MAY_EXEC, MMAP_CHECK, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -573,18 +580,41 @@ static int ima_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
|
||||||
*/
|
*/
|
||||||
static int ima_bprm_check(struct linux_binprm *bprm)
|
static int ima_bprm_check(struct linux_binprm *bprm)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct lsm_prop prop;
|
struct lsm_prop prop;
|
||||||
|
|
||||||
security_current_getlsmprop_subj(&prop);
|
security_current_getlsmprop_subj(&prop);
|
||||||
ret = process_measurement(bprm->file, current_cred(),
|
return process_measurement(bprm->file, current_cred(),
|
||||||
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK);
|
&prop, NULL, 0, MAY_EXEC, BPRM_CHECK, 0);
|
||||||
if (ret)
|
}
|
||||||
return ret;
|
|
||||||
|
|
||||||
security_cred_getlsmprop(bprm->cred, &prop);
|
/**
|
||||||
return process_measurement(bprm->file, bprm->cred, &prop, NULL, 0,
|
* ima_creds_check - based on policy, collect/store measurement.
|
||||||
MAY_EXEC, CREDS_CHECK);
|
* @bprm: contains the linux_binprm structure
|
||||||
|
* @file: contains the file descriptor of the binary being executed
|
||||||
|
*
|
||||||
|
* The OS protects against an executable file, already open for write,
|
||||||
|
* from being executed in deny_write_access() and an executable file,
|
||||||
|
* already open for execute, from being modified in get_write_access().
|
||||||
|
* So we can be certain that what we verify and measure here is actually
|
||||||
|
* what is being executed.
|
||||||
|
*
|
||||||
|
* The difference from ima_bprm_check() is that ima_creds_check() is invoked
|
||||||
|
* only after determining the final binary to be executed without interpreter,
|
||||||
|
* and not when searching for intermediate binaries. The reason is that since
|
||||||
|
* commit 56305aa9b6fab ("exec: Compute file based creds only once"), the
|
||||||
|
* credentials to be applied to the process are calculated only at that stage
|
||||||
|
* (bprm_creds_from_file security hook instead of bprm_check_security).
|
||||||
|
*
|
||||||
|
* On success return 0. On integrity appraisal error, assuming the file
|
||||||
|
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
||||||
|
*/
|
||||||
|
static int ima_creds_check(struct linux_binprm *bprm, const struct file *file)
|
||||||
|
{
|
||||||
|
struct lsm_prop prop;
|
||||||
|
|
||||||
|
security_current_getlsmprop_subj(&prop);
|
||||||
|
return process_measurement((struct file *)file, bprm->cred, &prop, NULL,
|
||||||
|
0, MAY_EXEC, CREDS_CHECK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -632,7 +662,7 @@ static int ima_file_check(struct file *file, int mask)
|
||||||
security_current_getlsmprop_subj(&prop);
|
security_current_getlsmprop_subj(&prop);
|
||||||
return process_measurement(file, current_cred(), &prop, NULL, 0,
|
return process_measurement(file, current_cred(), &prop, NULL, 0,
|
||||||
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
|
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
|
||||||
MAY_APPEND), FILE_CHECK);
|
MAY_APPEND), FILE_CHECK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
|
static int __ima_inode_hash(struct inode *inode, struct file *file, char *buf,
|
||||||
|
|
@ -851,12 +881,13 @@ static int ima_read_file(struct file *file, enum kernel_read_file_id read_id,
|
||||||
func = read_idmap[read_id] ?: FILE_CHECK;
|
func = read_idmap[read_id] ?: FILE_CHECK;
|
||||||
security_current_getlsmprop_subj(&prop);
|
security_current_getlsmprop_subj(&prop);
|
||||||
return process_measurement(file, current_cred(), &prop, NULL, 0,
|
return process_measurement(file, current_cred(), &prop, NULL, 0,
|
||||||
MAY_READ, func);
|
MAY_READ, func, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int read_idmap[READING_MAX_ID] = {
|
const int read_idmap[READING_MAX_ID] = {
|
||||||
[READING_FIRMWARE] = FIRMWARE_CHECK,
|
[READING_FIRMWARE] = FIRMWARE_CHECK,
|
||||||
[READING_MODULE] = MODULE_CHECK,
|
[READING_MODULE] = MODULE_CHECK,
|
||||||
|
[READING_MODULE_COMPRESSED] = MODULE_CHECK,
|
||||||
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
|
[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
|
||||||
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
|
[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
|
||||||
[READING_POLICY] = POLICY_CHECK
|
[READING_POLICY] = POLICY_CHECK
|
||||||
|
|
@ -894,7 +925,7 @@ static int ima_post_read_file(struct file *file, char *buf, loff_t size,
|
||||||
func = read_idmap[read_id] ?: FILE_CHECK;
|
func = read_idmap[read_id] ?: FILE_CHECK;
|
||||||
security_current_getlsmprop_subj(&prop);
|
security_current_getlsmprop_subj(&prop);
|
||||||
return process_measurement(file, current_cred(), &prop, buf, size,
|
return process_measurement(file, current_cred(), &prop, buf, size,
|
||||||
MAY_READ, func);
|
MAY_READ, func, read_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1242,6 +1273,7 @@ static int __init init_ima(void)
|
||||||
static struct security_hook_list ima_hooks[] __ro_after_init = {
|
static struct security_hook_list ima_hooks[] __ro_after_init = {
|
||||||
LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
|
LSM_HOOK_INIT(bprm_check_security, ima_bprm_check),
|
||||||
LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
|
LSM_HOOK_INIT(bprm_creds_for_exec, ima_bprm_creds_for_exec),
|
||||||
|
LSM_HOOK_INIT(bprm_creds_from_file, ima_creds_check),
|
||||||
LSM_HOOK_INIT(file_post_open, ima_file_check),
|
LSM_HOOK_INIT(file_post_open, ima_file_check),
|
||||||
LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile),
|
LSM_HOOK_INIT(inode_post_create_tmpfile, ima_post_create_tmpfile),
|
||||||
LSM_HOOK_INIT(file_release, ima_file_free),
|
LSM_HOOK_INIT(file_release, ima_file_free),
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#define IMA_GID 0x2000
|
#define IMA_GID 0x2000
|
||||||
#define IMA_EGID 0x4000
|
#define IMA_EGID 0x4000
|
||||||
#define IMA_FGROUP 0x8000
|
#define IMA_FGROUP 0x8000
|
||||||
|
#define IMA_FS_SUBTYPE 0x10000
|
||||||
|
|
||||||
#define UNKNOWN 0
|
#define UNKNOWN 0
|
||||||
#define MEASURE 0x0001 /* same as IMA_MEASURE */
|
#define MEASURE 0x0001 /* same as IMA_MEASURE */
|
||||||
|
|
@ -45,6 +46,7 @@
|
||||||
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
|
#define APPRAISE 0x0004 /* same as IMA_APPRAISE */
|
||||||
#define DONT_APPRAISE 0x0008
|
#define DONT_APPRAISE 0x0008
|
||||||
#define AUDIT 0x0040
|
#define AUDIT 0x0040
|
||||||
|
#define DONT_AUDIT 0x0080
|
||||||
#define HASH 0x0100
|
#define HASH 0x0100
|
||||||
#define DONT_HASH 0x0200
|
#define DONT_HASH 0x0200
|
||||||
|
|
||||||
|
|
@ -119,6 +121,7 @@ struct ima_rule_entry {
|
||||||
int type; /* audit type */
|
int type; /* audit type */
|
||||||
} lsm[MAX_LSM_RULES];
|
} lsm[MAX_LSM_RULES];
|
||||||
char *fsname;
|
char *fsname;
|
||||||
|
char *fs_subtype;
|
||||||
struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
|
struct ima_rule_opt_list *keyrings; /* Measure keys added to these keyrings */
|
||||||
struct ima_rule_opt_list *label; /* Measure data grouped under this label */
|
struct ima_rule_opt_list *label; /* Measure data grouped under this label */
|
||||||
struct ima_template_desc *template;
|
struct ima_template_desc *template;
|
||||||
|
|
@ -241,7 +244,8 @@ static struct ima_rule_entry build_appraise_rules[] __ro_after_init = {
|
||||||
|
|
||||||
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
|
static struct ima_rule_entry secure_boot_rules[] __ro_after_init = {
|
||||||
{.action = APPRAISE, .func = MODULE_CHECK,
|
{.action = APPRAISE, .func = MODULE_CHECK,
|
||||||
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
|
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED | IMA_MODSIG_ALLOWED |
|
||||||
|
IMA_CHECK_BLACKLIST},
|
||||||
{.action = APPRAISE, .func = FIRMWARE_CHECK,
|
{.action = APPRAISE, .func = FIRMWARE_CHECK,
|
||||||
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
|
.flags = IMA_FUNC | IMA_DIGSIG_REQUIRED},
|
||||||
{.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
|
{.action = APPRAISE, .func = KEXEC_KERNEL_CHECK,
|
||||||
|
|
@ -397,6 +401,7 @@ static void ima_free_rule(struct ima_rule_entry *entry)
|
||||||
* the defined_templates list and cannot be freed here
|
* the defined_templates list and cannot be freed here
|
||||||
*/
|
*/
|
||||||
kfree(entry->fsname);
|
kfree(entry->fsname);
|
||||||
|
kfree(entry->fs_subtype);
|
||||||
ima_free_rule_opt_list(entry->keyrings);
|
ima_free_rule_opt_list(entry->keyrings);
|
||||||
ima_lsm_free_rule(entry);
|
ima_lsm_free_rule(entry);
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
|
|
@ -601,6 +606,12 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
|
||||||
if ((rule->flags & IMA_FSNAME)
|
if ((rule->flags & IMA_FSNAME)
|
||||||
&& strcmp(rule->fsname, inode->i_sb->s_type->name))
|
&& strcmp(rule->fsname, inode->i_sb->s_type->name))
|
||||||
return false;
|
return false;
|
||||||
|
if (rule->flags & IMA_FS_SUBTYPE) {
|
||||||
|
if (!inode->i_sb->s_subtype)
|
||||||
|
return false;
|
||||||
|
if (strcmp(rule->fs_subtype, inode->i_sb->s_subtype))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ((rule->flags & IMA_FSUUID) &&
|
if ((rule->flags & IMA_FSUUID) &&
|
||||||
!uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
|
!uuid_equal(&rule->fsuuid, &inode->i_sb->s_uuid))
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -674,7 +685,7 @@ retry:
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rc) {
|
if (rc <= 0) {
|
||||||
result = false;
|
result = false;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -1064,10 +1075,10 @@ void ima_update_policy(void)
|
||||||
enum policy_opt {
|
enum policy_opt {
|
||||||
Opt_measure, Opt_dont_measure,
|
Opt_measure, Opt_dont_measure,
|
||||||
Opt_appraise, Opt_dont_appraise,
|
Opt_appraise, Opt_dont_appraise,
|
||||||
Opt_audit, Opt_hash, Opt_dont_hash,
|
Opt_audit, Opt_dont_audit, Opt_hash, Opt_dont_hash,
|
||||||
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
Opt_obj_user, Opt_obj_role, Opt_obj_type,
|
||||||
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
Opt_subj_user, Opt_subj_role, Opt_subj_type,
|
||||||
Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, Opt_fsuuid,
|
Opt_func, Opt_mask, Opt_fsmagic, Opt_fsname, Opt_fs_subtype, Opt_fsuuid,
|
||||||
Opt_uid_eq, Opt_euid_eq, Opt_gid_eq, Opt_egid_eq,
|
Opt_uid_eq, Opt_euid_eq, Opt_gid_eq, Opt_egid_eq,
|
||||||
Opt_fowner_eq, Opt_fgroup_eq,
|
Opt_fowner_eq, Opt_fgroup_eq,
|
||||||
Opt_uid_gt, Opt_euid_gt, Opt_gid_gt, Opt_egid_gt,
|
Opt_uid_gt, Opt_euid_gt, Opt_gid_gt, Opt_egid_gt,
|
||||||
|
|
@ -1086,6 +1097,7 @@ static const match_table_t policy_tokens = {
|
||||||
{Opt_appraise, "appraise"},
|
{Opt_appraise, "appraise"},
|
||||||
{Opt_dont_appraise, "dont_appraise"},
|
{Opt_dont_appraise, "dont_appraise"},
|
||||||
{Opt_audit, "audit"},
|
{Opt_audit, "audit"},
|
||||||
|
{Opt_dont_audit, "dont_audit"},
|
||||||
{Opt_hash, "hash"},
|
{Opt_hash, "hash"},
|
||||||
{Opt_dont_hash, "dont_hash"},
|
{Opt_dont_hash, "dont_hash"},
|
||||||
{Opt_obj_user, "obj_user=%s"},
|
{Opt_obj_user, "obj_user=%s"},
|
||||||
|
|
@ -1098,6 +1110,7 @@ static const match_table_t policy_tokens = {
|
||||||
{Opt_mask, "mask=%s"},
|
{Opt_mask, "mask=%s"},
|
||||||
{Opt_fsmagic, "fsmagic=%s"},
|
{Opt_fsmagic, "fsmagic=%s"},
|
||||||
{Opt_fsname, "fsname=%s"},
|
{Opt_fsname, "fsname=%s"},
|
||||||
|
{Opt_fs_subtype, "fs_subtype=%s"},
|
||||||
{Opt_fsuuid, "fsuuid=%s"},
|
{Opt_fsuuid, "fsuuid=%s"},
|
||||||
{Opt_uid_eq, "uid=%s"},
|
{Opt_uid_eq, "uid=%s"},
|
||||||
{Opt_euid_eq, "euid=%s"},
|
{Opt_euid_eq, "euid=%s"},
|
||||||
|
|
@ -1282,7 +1295,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
|
||||||
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
|
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
|
||||||
IMA_UID | IMA_FOWNER | IMA_FSUUID |
|
IMA_UID | IMA_FOWNER | IMA_FSUUID |
|
||||||
IMA_INMASK | IMA_EUID | IMA_PCR |
|
IMA_INMASK | IMA_EUID | IMA_PCR |
|
||||||
IMA_FSNAME | IMA_GID | IMA_EGID |
|
IMA_FSNAME | IMA_FS_SUBTYPE |
|
||||||
|
IMA_GID | IMA_EGID |
|
||||||
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
|
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
|
||||||
IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS |
|
IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS |
|
||||||
IMA_CHECK_BLACKLIST | IMA_VERITY_REQUIRED))
|
IMA_CHECK_BLACKLIST | IMA_VERITY_REQUIRED))
|
||||||
|
|
@ -1295,7 +1309,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
|
||||||
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
|
if (entry->flags & ~(IMA_FUNC | IMA_MASK | IMA_FSMAGIC |
|
||||||
IMA_UID | IMA_FOWNER | IMA_FSUUID |
|
IMA_UID | IMA_FOWNER | IMA_FSUUID |
|
||||||
IMA_INMASK | IMA_EUID | IMA_PCR |
|
IMA_INMASK | IMA_EUID | IMA_PCR |
|
||||||
IMA_FSNAME | IMA_GID | IMA_EGID |
|
IMA_FSNAME | IMA_FS_SUBTYPE |
|
||||||
|
IMA_GID | IMA_EGID |
|
||||||
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
|
IMA_FGROUP | IMA_DIGSIG_REQUIRED |
|
||||||
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
|
IMA_PERMIT_DIRECTIO | IMA_MODSIG_ALLOWED |
|
||||||
IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
|
IMA_CHECK_BLACKLIST | IMA_VALIDATE_ALGOS))
|
||||||
|
|
@ -1308,7 +1323,8 @@ static bool ima_validate_rule(struct ima_rule_entry *entry)
|
||||||
|
|
||||||
if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID |
|
if (entry->flags & ~(IMA_FUNC | IMA_FSMAGIC | IMA_UID |
|
||||||
IMA_FOWNER | IMA_FSUUID | IMA_EUID |
|
IMA_FOWNER | IMA_FSUUID | IMA_EUID |
|
||||||
IMA_PCR | IMA_FSNAME | IMA_GID | IMA_EGID |
|
IMA_PCR | IMA_FSNAME | IMA_FS_SUBTYPE |
|
||||||
|
IMA_GID | IMA_EGID |
|
||||||
IMA_FGROUP))
|
IMA_FGROUP))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -1478,6 +1494,14 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
|
|
||||||
entry->action = AUDIT;
|
entry->action = AUDIT;
|
||||||
break;
|
break;
|
||||||
|
case Opt_dont_audit:
|
||||||
|
ima_log_string(ab, "action", "dont_audit");
|
||||||
|
|
||||||
|
if (entry->action != UNKNOWN)
|
||||||
|
result = -EINVAL;
|
||||||
|
|
||||||
|
entry->action = DONT_AUDIT;
|
||||||
|
break;
|
||||||
case Opt_hash:
|
case Opt_hash:
|
||||||
ima_log_string(ab, "action", "hash");
|
ima_log_string(ab, "action", "hash");
|
||||||
|
|
||||||
|
|
@ -1587,6 +1611,22 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
|
||||||
result = 0;
|
result = 0;
|
||||||
entry->flags |= IMA_FSNAME;
|
entry->flags |= IMA_FSNAME;
|
||||||
break;
|
break;
|
||||||
|
case Opt_fs_subtype:
|
||||||
|
ima_log_string(ab, "fs_subtype", args[0].from);
|
||||||
|
|
||||||
|
if (entry->fs_subtype) {
|
||||||
|
result = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->fs_subtype = kstrdup(args[0].from, GFP_KERNEL);
|
||||||
|
if (!entry->fs_subtype) {
|
||||||
|
result = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result = 0;
|
||||||
|
entry->flags |= IMA_FS_SUBTYPE;
|
||||||
|
break;
|
||||||
case Opt_keyrings:
|
case Opt_keyrings:
|
||||||
ima_log_string(ab, "keyrings", args[0].from);
|
ima_log_string(ab, "keyrings", args[0].from);
|
||||||
|
|
||||||
|
|
@ -2097,6 +2137,8 @@ int ima_policy_show(struct seq_file *m, void *v)
|
||||||
seq_puts(m, pt(Opt_dont_appraise));
|
seq_puts(m, pt(Opt_dont_appraise));
|
||||||
if (entry->action & AUDIT)
|
if (entry->action & AUDIT)
|
||||||
seq_puts(m, pt(Opt_audit));
|
seq_puts(m, pt(Opt_audit));
|
||||||
|
if (entry->action & DONT_AUDIT)
|
||||||
|
seq_puts(m, pt(Opt_dont_audit));
|
||||||
if (entry->action & HASH)
|
if (entry->action & HASH)
|
||||||
seq_puts(m, pt(Opt_hash));
|
seq_puts(m, pt(Opt_hash));
|
||||||
if (entry->action & DONT_HASH)
|
if (entry->action & DONT_HASH)
|
||||||
|
|
@ -2133,6 +2175,12 @@ int ima_policy_show(struct seq_file *m, void *v)
|
||||||
seq_puts(m, " ");
|
seq_puts(m, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry->flags & IMA_FS_SUBTYPE) {
|
||||||
|
snprintf(tbuf, sizeof(tbuf), "%s", entry->fs_subtype);
|
||||||
|
seq_printf(m, pt(Opt_fs_subtype), tbuf);
|
||||||
|
seq_puts(m, " ");
|
||||||
|
}
|
||||||
|
|
||||||
if (entry->flags & IMA_KEYRINGS) {
|
if (entry->flags & IMA_KEYRINGS) {
|
||||||
seq_puts(m, "keyrings=");
|
seq_puts(m, "keyrings=");
|
||||||
ima_show_rule_opt_list(m, entry->keyrings);
|
ima_show_rule_opt_list(m, entry->keyrings);
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
|
||||||
op = IPE_OP_FIRMWARE;
|
op = IPE_OP_FIRMWARE;
|
||||||
break;
|
break;
|
||||||
case READING_MODULE:
|
case READING_MODULE:
|
||||||
|
case READING_MODULE_COMPRESSED:
|
||||||
op = IPE_OP_KERNEL_MODULE;
|
op = IPE_OP_KERNEL_MODULE;
|
||||||
break;
|
break;
|
||||||
case READING_KEXEC_INITRAMFS:
|
case READING_KEXEC_INITRAMFS:
|
||||||
|
|
|
||||||
|
|
@ -4296,7 +4296,7 @@ static int selinux_kernel_read_file(struct file *file,
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
BUILD_BUG_ON_MSG(READING_MAX_ID > 7,
|
BUILD_BUG_ON_MSG(READING_MAX_ID > 8,
|
||||||
"New kernel_read_file_id introduced; update SELinux!");
|
"New kernel_read_file_id introduced; update SELinux!");
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
|
@ -4304,6 +4304,7 @@ static int selinux_kernel_read_file(struct file *file,
|
||||||
rc = selinux_kernel_load_from_file(file, SYSTEM__FIRMWARE_LOAD);
|
rc = selinux_kernel_load_from_file(file, SYSTEM__FIRMWARE_LOAD);
|
||||||
break;
|
break;
|
||||||
case READING_MODULE:
|
case READING_MODULE:
|
||||||
|
case READING_MODULE_COMPRESSED:
|
||||||
rc = selinux_kernel_load_from_file(file, SYSTEM__MODULE_LOAD);
|
rc = selinux_kernel_load_from_file(file, SYSTEM__MODULE_LOAD);
|
||||||
break;
|
break;
|
||||||
case READING_KEXEC_IMAGE:
|
case READING_KEXEC_IMAGE:
|
||||||
|
|
@ -4332,7 +4333,7 @@ static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
BUILD_BUG_ON_MSG(LOADING_MAX_ID > 7,
|
BUILD_BUG_ON_MSG(LOADING_MAX_ID > 8,
|
||||||
"New kernel_load_data_id introduced; update SELinux!");
|
"New kernel_load_data_id introduced; update SELinux!");
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue