FAILED: patch "[PATCH] ima: Fix use-after-free on a dentry's dname.name" failed to apply to 5.4-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x be84f32bb2c981ca6709
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2024061920-daycare-control-aa50@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From be84f32bb2c981ca670922e047cdde1488b233de Mon Sep 17 00:00:00 2001
From: Stefan Berger <[email protected]>
Date: Fri, 22 Mar 2024 10:03:12 -0400
Subject: [PATCH] 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.
security/integrity/ima/ima_api.c +12 -4
@@ -245,8 +245,8 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,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;
@@ -317,9 +317,13 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,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; }
@@ -432,6 +436,7 @@ void ima_audit_measurement(struct ima_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 ();
@@ -445,7 +450,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; }
security/integrity/ima/ima_template_lib.c +14 -3
@@ -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; }/*