diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 907faa398157..57b35199edea 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -398,7 +398,7 @@ LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) #ifdef CONFIG_AUDIT LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr, - void **lsmrule, int lsmid) + void **lsmrule, int lsmid, gfp_t gfp) LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule) LSM_HOOK(int, 0, audit_rule_match, struct lsmblob *blob, u32 field, u32 op, void *lsmrule, int lsmid) diff --git a/include/linux/security.h b/include/linux/security.h index 7deda575e27b..f1cf484c42fa 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2074,7 +2074,8 @@ static inline int security_key_getsecurity(struct key *key, char **_buffer) #ifdef CONFIG_AUDIT #ifdef CONFIG_SECURITY -int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule); +int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, + gfp_t gfp); int security_audit_rule_known(struct audit_krule *krule); int security_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *lsmrule); @@ -2083,7 +2084,7 @@ void security_audit_rule_free(void *lsmrule); #else static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr, - void **lsmrule) + void **lsmrule, gfp_t gfp) { return 0; } @@ -2107,7 +2108,7 @@ static inline void security_audit_rule_free(void *lsmrule) #if defined(CONFIG_IMA_LSM_RULES) && defined(CONFIG_SECURITY) int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, - int lsmid); + int lsmid, gfp_t gfp); int ima_filter_rule_match(struct lsmblob *blob, u32 field, u32 op, void *lsmrule, int lsmid); void ima_filter_rule_free(void *lsmrule, int lsmid); @@ -2115,7 +2116,7 @@ void ima_filter_rule_free(void *lsmrule, int lsmid); #else static inline int ima_filter_rule_init(u32 field, u32 op, char *rulestr, - void **lsmrule, int lsmid) + void **lsmrule, int lsmid, gfp_t gfp) { return 0; } diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 24cb8259e5b1..12d364e47468 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -529,7 +529,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, entry->rule.buflen += f_val; f->lsm_str = str; err = security_audit_rule_init(f->type, f->op, str, - (void **)&f->lsm_rule); + (void **)&f->lsm_rule, + GFP_KERNEL); /* Keep currently invalid fields around in case they * become valid after a policy reload. */ if (err == -EINVAL) { @@ -799,7 +800,7 @@ static inline int audit_dupe_lsm_field(struct audit_field *df, /* our own (refreshed) copy of lsm_rule */ ret = security_audit_rule_init(df->type, df->op, df->lsm_str, - (void **)&df->lsm_rule); + (void **)&df->lsm_rule, GFP_KERNEL); /* Keep currently invalid fields around in case they * become valid after a policy reload. */ if (ret == -EINVAL) { diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index f9f611333a12..9ecc1bc941f8 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -222,7 +222,7 @@ void aa_audit_rule_free(void *vrule, int lsmid) } int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, - int lsmid) + int lsmid, gfp_t gfp) { struct aa_audit_rule *rule; @@ -237,14 +237,14 @@ int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, return -EINVAL; } - rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL); + rule = kzalloc(sizeof(struct aa_audit_rule), gfp); if (!rule) return -ENOMEM; /* Currently rules are treated as coming from the root ns */ rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr, - GFP_KERNEL, true, false); + gfp, true, false); if (IS_ERR(rule->label)) { int err = PTR_ERR(rule->label); aa_audit_rule_free(rule, LSM_ID_APPARMOR); diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h index 3b40128b37b4..2fb888090a97 100644 --- a/security/apparmor/include/audit.h +++ b/security/apparmor/include/audit.h @@ -254,7 +254,7 @@ static inline int complain_error(int error) void aa_audit_rule_free(void *vrule, int lsmid); int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, - int lsmid); + int lsmid, gfp_t gfp); int aa_audit_rule_known(struct audit_krule *rule); int aa_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *vrule, int lsmid); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 8edf7a0ef9f6..71de4cb5bbaa 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -423,7 +423,8 @@ static void ima_free_rule(struct ima_rule_entry *entry) kfree(entry); } -static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) +static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry, + gfp_t gfp) { struct ima_rule_entry *nentry; int i; @@ -432,7 +433,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) * Immutable elements are copied over as pointers and data; only * lsm rules can change */ - nentry = kmemdup(entry, sizeof(*nentry), GFP_KERNEL); + nentry = kmemdup(entry, sizeof(*nentry), gfp); if (!nentry) return NULL; @@ -448,7 +449,8 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry) ima_filter_rule_init(nentry->lsm[i].type, Audit_equal, nentry->lsm[i].args_p, &nentry->lsm[i].rule, - entry->lsm[i].lsm_id); + entry->lsm[i].lsm_id, + gfp); if (!nentry->lsm[i].rule) pr_warn("rule for LSM \'%s\' is undefined\n", nentry->lsm[i].args_p); @@ -461,7 +463,7 @@ static int ima_lsm_update_rule(struct ima_rule_entry *entry) int i; struct ima_rule_entry *nentry; - nentry = ima_lsm_copy_rule(entry); + nentry = ima_lsm_copy_rule(entry, GFP_KERNEL); if (!nentry) return -ENOMEM; @@ -690,7 +692,7 @@ retry: } if (rc == -ESTALE && !rule_reinitialized) { - lsm_rule = ima_lsm_copy_rule(rule); + lsm_rule = ima_lsm_copy_rule(rule, GFP_ATOMIC); if (lsm_rule) { rule_reinitialized = true; goto retry; @@ -1169,7 +1171,8 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry, result = ima_filter_rule_init(entry->lsm[lsm_rule].type, Audit_equal, entry->lsm[lsm_rule].args_p, &entry->lsm[lsm_rule].rule, - entry->lsm[lsm_rule].lsm_id); + entry->lsm[lsm_rule].lsm_id, + GFP_KERNEL); if (!entry->lsm[lsm_rule].rule) { pr_warn("rule for LSM \'%s\' is undefined\n", entry->lsm[lsm_rule].args_p); diff --git a/security/security.c b/security/security.c index ec754a919803..8f82791920dd 100644 --- a/security/security.c +++ b/security/security.c @@ -5545,16 +5545,18 @@ int security_key_getsecurity(struct key *key, char **buffer) * @op: rule operator * @rulestr: rule context * @lsmrule: receive buffer for audit rule struct + * @gfp: GFP flag used for kmalloc * * Allocate and initialize an LSM audit rule structure. * * Return: Return 0 if @lsmrule has been successfully set, -EINVAL in case of * an invalid rule. */ -int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) +int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, + gfp_t gfp) { return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule, - LSM_ID_UNDEF); + LSM_ID_UNDEF, gfp); } /** @@ -5609,10 +5611,10 @@ int security_audit_rule_match(struct lsmblob *blob, u32 field, u32 op, void *lsm * the audit subsystem. */ int ima_filter_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule, - int lsmid) + int lsmid, gfp_t gfp) { return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule, - lsmid); + lsmid, gfp); } void ima_filter_rule_free(void *lsmrule, int lsmid) diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h index ecd6be8619a5..2fceeb59b0d7 100644 --- a/security/selinux/include/audit.h +++ b/security/selinux/include/audit.h @@ -22,13 +22,14 @@ * @rulestr: the text "target" of the rule * @rule: pointer to the new rule structure returned via this * @lsmid: the relevant LSM + * @gfp: GFP flag used for kmalloc * * Returns 0 if successful, -errno if not. On success, the rule structure * will be allocated internally. The caller must free this structure with * selinux_audit_rule_free() after use. */ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule, - int lsmid); + int lsmid, gfp_t gfp); /** * selinux_audit_rule_free - free an selinux audit rule structure. diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 4e8f8c21e1f0..d0267596f2ab 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -3511,7 +3511,7 @@ void selinux_audit_rule_free(void *vrule, int lsmid) } int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, - int lsmid) + int lsmid, gfp_t gfp) { struct selinux_state *state = &selinux_state; struct selinux_policy *policy; @@ -3554,7 +3554,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, return -EINVAL; } - tmprule = kzalloc(sizeof(struct selinux_audit_rule), GFP_KERNEL); + tmprule = kzalloc(sizeof(struct selinux_audit_rule), gfp); if (!tmprule) return -ENOMEM; context_init(&tmprule->au_ctxt); diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d2072efcb030..b33abdaf4b61 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4728,12 +4728,13 @@ static int smack_post_notification(const struct cred *w_cred, * @rulestr: smack label to be audited * @vrule: pointer to save our own audit rule representation * @lsmid: the relevant LSM + * @gfp: type of the memory for the allocation * * Prepare to audit cases where (@field @op @rulestr) is true. * The label to be audited is created if necessay. */ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule, - int lsmid) + int lsmid, gfp_t gfp) { struct smack_known *skp; char **rule = (char **)vrule;