| From 7593cfb16c000c5f4d68c552267ad6a5f67ce74b Mon Sep 17 00:00:00 2001 |
| From: Wenwen Wang <wang6495@umn.edu> |
| Date: Fri, 19 Apr 2019 20:49:29 -0500 |
| Subject: audit: fix a memory leak bug |
| |
| [ Upstream commit 70c4cf17e445264453bc5323db3e50aa0ac9e81f ] |
| |
| In audit_rule_change(), audit_data_to_entry() is firstly invoked to |
| translate the payload data to the kernel's rule representation. In |
| audit_data_to_entry(), depending on the audit field type, an audit tree may |
| be created in audit_make_tree(), which eventually invokes kmalloc() to |
| allocate the tree. Since this tree is a temporary tree, it will be then |
| freed in the following execution, e.g., audit_add_rule() if the message |
| type is AUDIT_ADD_RULE or audit_del_rule() if the message type is |
| AUDIT_DEL_RULE. However, if the message type is neither AUDIT_ADD_RULE nor |
| AUDIT_DEL_RULE, i.e., the default case of the switch statement, this |
| temporary tree is not freed. |
| |
| To fix this issue, only allocate the tree when the type is AUDIT_ADD_RULE |
| or AUDIT_DEL_RULE. |
| |
| Signed-off-by: Wenwen Wang <wang6495@umn.edu> |
| Reviewed-by: Richard Guy Briggs <rgb@redhat.com> |
| Signed-off-by: Paul Moore <paul@paul-moore.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/auditfilter.c | 12 +++++++----- |
| 1 file changed, 7 insertions(+), 5 deletions(-) |
| |
| diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c |
| index 63f8b3f26fab4..3ac71c4fda49a 100644 |
| --- a/kernel/auditfilter.c |
| +++ b/kernel/auditfilter.c |
| @@ -1114,22 +1114,24 @@ int audit_rule_change(int type, int seq, void *data, size_t datasz) |
| int err = 0; |
| struct audit_entry *entry; |
| |
| - entry = audit_data_to_entry(data, datasz); |
| - if (IS_ERR(entry)) |
| - return PTR_ERR(entry); |
| - |
| switch (type) { |
| case AUDIT_ADD_RULE: |
| + entry = audit_data_to_entry(data, datasz); |
| + if (IS_ERR(entry)) |
| + return PTR_ERR(entry); |
| err = audit_add_rule(entry); |
| audit_log_rule_change("add_rule", &entry->rule, !err); |
| break; |
| case AUDIT_DEL_RULE: |
| + entry = audit_data_to_entry(data, datasz); |
| + if (IS_ERR(entry)) |
| + return PTR_ERR(entry); |
| err = audit_del_rule(entry); |
| audit_log_rule_change("remove_rule", &entry->rule, !err); |
| break; |
| default: |
| - err = -EINVAL; |
| WARN_ON(1); |
| + return -EINVAL; |
| } |
| |
| if (err || type == AUDIT_DEL_RULE) { |
| -- |
| 2.20.1 |
| |