[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240527155541.3865428-2-sashal@kernel.org>
Date: Mon, 27 May 2024 11:54:53 -0400
From: Sasha Levin <sashal@...nel.org>
To: linux-kernel@...r.kernel.org,
stable@...r.kernel.org
Cc: Stefan Berger <stefanb@...ux.ibm.com>,
Al Viro <viro@...iv.linux.org.uk>,
Mimi Zohar <zohar@...ux.ibm.com>,
Sasha Levin <sashal@...nel.org>,
roberto.sassu@...wei.com,
dmitry.kasatkin@...il.com,
paul@...l-moore.com,
jmorris@...ei.org,
serge@...lyn.com,
linux-integrity@...r.kernel.org,
linux-security-module@...r.kernel.org
Subject: [PATCH AUTOSEL 6.6 02/16] ima: Fix use-after-free on a dentry's dname.name
From: Stefan Berger <stefanb@...ux.ibm.com>
[ Upstream commit be84f32bb2c981ca670922e047cdde1488b233de ]
->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@...iv.linux.org.uk>
Signed-off-by: Stefan Berger <stefanb@...ux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@...ux.ibm.com>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
security/integrity/ima/ima_api.c | 16 ++++++++++++----
security/integrity/ima/ima_template_lib.c | 17 ++++++++++++++---
2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 597ea0c4d72f7..44b8161746fec 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -244,8 +244,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
const char *audit_cause = "failed";
struct inode *inode = file_inode(file);
struct inode *real_inode = d_real_inode(file_dentry(file));
- const char *filename = file->f_path.dentry->d_name.name;
struct ima_max_digest_data hash;
+ struct name_snapshot filename;
struct kstat stat;
int result = 0;
int length;
@@ -316,9 +316,13 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
if (file->f_flags & O_DIRECT)
audit_cause = "failed(directio)";
+ take_dentry_name_snapshot(&filename, file->f_path.dentry);
+
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
- filename, "collect_data", audit_cause,
- result, 0);
+ filename.name.name, "collect_data",
+ audit_cause, result, 0);
+
+ release_dentry_name_snapshot(&filename);
}
return result;
}
@@ -431,6 +435,7 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
*/
const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
{
+ struct name_snapshot filename;
char *pathname = NULL;
*pathbuf = __getname();
@@ -444,7 +449,10 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
}
if (!pathname) {
- strscpy(namebuf, path->dentry->d_name.name, NAME_MAX);
+ take_dentry_name_snapshot(&filename, path->dentry);
+ strscpy(namebuf, filename.name.name, NAME_MAX);
+ release_dentry_name_snapshot(&filename);
+
pathname = namebuf;
}
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 6cd0add524cdc..3b2cb8f1002e6 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;
}
/*
--
2.43.0
Powered by blists - more mailing lists