diff options
author | Wenwen Wang <wang6495@umn.edu> | 2019-04-19 21:49:29 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2019-04-22 11:22:03 -0400 |
commit | 70c4cf17e445264453bc5323db3e50aa0ac9e81f (patch) | |
tree | d4ac7a73d1e877e885a1b9310654c21a55235c85 | |
parent | 7e8eda734d30de81d06a949c9bf9853c445ede4e (diff) |
audit: fix a memory leak bug
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>
-rw-r--r-- | kernel/auditfilter.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 2c3c2f349b23..1bc6410413e6 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) | |||
1114 | int err = 0; | 1114 | int err = 0; |
1115 | struct audit_entry *entry; | 1115 | struct audit_entry *entry; |
1116 | 1116 | ||
1117 | entry = audit_data_to_entry(data, datasz); | ||
1118 | if (IS_ERR(entry)) | ||
1119 | return PTR_ERR(entry); | ||
1120 | |||
1121 | switch (type) { | 1117 | switch (type) { |
1122 | case AUDIT_ADD_RULE: | 1118 | case AUDIT_ADD_RULE: |
1119 | entry = audit_data_to_entry(data, datasz); | ||
1120 | if (IS_ERR(entry)) | ||
1121 | return PTR_ERR(entry); | ||
1123 | err = audit_add_rule(entry); | 1122 | err = audit_add_rule(entry); |
1124 | audit_log_rule_change("add_rule", &entry->rule, !err); | 1123 | audit_log_rule_change("add_rule", &entry->rule, !err); |
1125 | break; | 1124 | break; |
1126 | case AUDIT_DEL_RULE: | 1125 | case AUDIT_DEL_RULE: |
1126 | entry = audit_data_to_entry(data, datasz); | ||
1127 | if (IS_ERR(entry)) | ||
1128 | return PTR_ERR(entry); | ||
1127 | err = audit_del_rule(entry); | 1129 | err = audit_del_rule(entry); |
1128 | audit_log_rule_change("remove_rule", &entry->rule, !err); | 1130 | audit_log_rule_change("remove_rule", &entry->rule, !err); |
1129 | break; | 1131 | break; |
1130 | default: | 1132 | default: |
1131 | err = -EINVAL; | ||
1132 | WARN_ON(1); | 1133 | WARN_ON(1); |
1134 | return -EINVAL; | ||
1133 | } | 1135 | } |
1134 | 1136 | ||
1135 | if (err || type == AUDIT_DEL_RULE) { | 1137 | if (err || type == AUDIT_DEL_RULE) { |