diff options
author | Stefan Berger <stefanb@linux.ibm.com> | 2024-03-22 17:03:12 +0300 |
---|---|---|
committer | Mimi Zohar <zohar@linux.ibm.com> | 2024-04-08 14:55:47 +0300 |
commit | be84f32bb2c981ca670922e047cdde1488b233de (patch) | |
tree | a3c135a23ab2e801c0f2ab977e0a77d2122cdb13 /security/integrity/ima/ima_template_lib.c | |
parent | fec50db7033ea478773b159e0e2efb135270e3b7 (diff) | |
download | linux-be84f32bb2c981ca670922e047cdde1488b233de.tar.xz |
ima: Fix use-after-free on a dentry's dname.name
->d_name.name can change on rename and the earlier value can be freed;
there are conditions sufficient to stabilize it (->d_lock on dentry,
->d_lock on its parent, ->i_rwsem exclusive on the parent's inode,
rename_lock), but none of those are met at any of the sites. Take a stable
snapshot of the name instead.
Link: https://lore.kernel.org/all/20240202182732.GE2087318@ZenIV/
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
Diffstat (limited to 'security/integrity/ima/ima_template_lib.c')
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 6cd0add524cd..3b2cb8f1002e 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -483,7 +483,10 @@ static int ima_eventname_init_common(struct ima_event_data *event_data, bool size_limit) { const char *cur_filename = NULL; + struct name_snapshot filename; u32 cur_filename_len = 0; + bool snapshot = false; + int ret; BUG_ON(event_data->filename == NULL && event_data->file == NULL); @@ -496,7 +499,10 @@ static int ima_eventname_init_common(struct ima_event_data *event_data, } if (event_data->file) { - cur_filename = event_data->file->f_path.dentry->d_name.name; + take_dentry_name_snapshot(&filename, + event_data->file->f_path.dentry); + snapshot = true; + cur_filename = filename.name.name; cur_filename_len = strlen(cur_filename); } else /* @@ -505,8 +511,13 @@ static int ima_eventname_init_common(struct ima_event_data *event_data, */ cur_filename_len = IMA_EVENT_NAME_LEN_MAX; out: - return ima_write_template_field_data(cur_filename, cur_filename_len, - DATA_FMT_STRING, field_data); + ret = ima_write_template_field_data(cur_filename, cur_filename_len, + DATA_FMT_STRING, field_data); + + if (snapshot) + release_dentry_name_snapshot(&filename); + + return ret; } /* |