[v6.6,3/5] eventfs: Save ownership and mode

Message ID 20231105160139.660634360@goodmis.org
State New
Headers
Series tracing: Backport of eventfs fixes for v6.6 |

Commit Message

Steven Rostedt Nov. 5, 2023, 3:56 p.m. UTC
  From: "Steven Rostedt (Google)" <rostedt@goodmis.org>

commit 28e12c09f5aa081b2d13d1340e3610070b6c624d upstream

Now that inodes and dentries are created on the fly, they are also
reclaimed on memory pressure. Since the ownership and file mode are saved
in the inode, if they are freed, any changes to the ownership and mode
will be lost.

To counter this, if the user changes the permissions or ownership, save
them, and when creating the inodes again, restore those changes.

Link: https://lkml.kernel.org/r/20231101172649.691841445@goodmis.org

Cc: stable@vger.kernel.org
Cc: Ajay Kaher <akaher@vmware.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Fixes: 63940449555e7 ("eventfs: Implement eventfs lookup, read, open functions")
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
 fs/tracefs/event_inode.c | 107 +++++++++++++++++++++++++++++++++------
 1 file changed, 91 insertions(+), 16 deletions(-)
  

Comments

Milian Wolff Nov. 12, 2023, 10:41 a.m. UTC | #1
Hey all,

this patch seems to have introduced a kernel bug causing
a NULL pointer dereference when one runs:

    sudo chown -R root:tracing /sys/kernel/debug/tracing/

See the archlinux bug report I created initially for some more information:
https://bugs.archlinux.org/task/80230

With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
the above `chmod` command works. With a normal 6.6.1 build, or re-applying
the patch again, the command fails and `dmesg` shows:

```
[ 60.723813] BUG: kernel NULL pointer dereference, address: 0000000000000058
[ 60.723817] #PF: supervisor read access in kernel mode
[ 60.723819] #PF: error_code(0x0000) - not-present page
[ 60.723820] PGD 0 P4D 0
[ 60.723821] Oops: 0000 [#1] PREEMPT SMP NOPTI
[ 60.723823] CPU: 5 PID: 2830 Comm: chown Tainted: P OE 6.6.1-arch1-1 #1 be166a630cd909acf8820643140e9106c6ea80e6
[ 60.723825] Hardware name: LENOVO 20Y30018GE/20Y30018GE, BIOS N40ET42W (1.24 ) 07/26/2023
[ 60.723826] RIP: 0010:eventfs_set_attr+0x28/0xd0
[ 60.723830] Code: 90 90 f3 0f 1e fa 0f 1f 44 00 00 41 55 41 54 49 89 d4 55 48 89 fd 48 c7 c7 a0 b7 b2 b2 53 48 89 f3 e8 8c 16 8c 00 4c 8b 6b 78 <41> f6 45 58 01 0f 85 87 00 00 00 48 89 de 4c 89 e2 48 89 ef e8 4f
[ 60.723830] RSP: 0018:ffffc90007fdbd38 EFLAGS: 00010246
[ 60.723832] RAX: 0000000000000000 RBX: ffff88810047e180 RCX: 8000000000000000
[ 60.723832] RDX: ffff888174b6ce00 RSI: ffff88810047e180 RDI: ffffffffb2b2b7a0
[ 60.723833] RBP: ffffffffb2b20620 R08: 0000000000000000 R09: ffffffffb2a4a488
[ 60.723834] R10: 00000000654f505f R11: 0000000018432441 R12: ffffc90007fdbe00
[ 60.723835] R13: 0000000000000000 R14: ffff88810047e180 R15: ffff8881004c02a8
[ 60.723835] FS: 00007f4ac6f4c740(0000) GS:ffff88901f540000(0000) knlGS:0000000000000000
[ 60.723836] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 60.723837] CR2: 0000000000000058 CR3: 000000021ad48001 CR4: 0000000000f70ee0
[ 60.723838] PKRU: 55555554
[ 60.723839] Call Trace:
[ 60.723840] <TASK>
[ 60.723842] ? __die+0x23/0x70
[ 60.723845] ? page_fault_oops+0x171/0x4e0
[ 60.723847] ? generic_permission+0x39/0x220
[ 60.723850] ? exc_page_fault+0x7f/0x180
[ 60.723853] ? asm_exc_page_fault+0x26/0x30
[ 60.723857] ? eventfs_set_attr+0x28/0xd0
[ 60.723858] ? eventfs_set_attr+0x24/0xd0
[ 60.723859] notify_change+0x1f2/0x4b0
[ 60.723862] ? chown_common+0x222/0x230
[ 60.723863] chown_common+0x222/0x230
[ 60.723865] do_fchownat+0xa3/0x100
[ 60.723866] __x64_sys_fchownat+0x1f/0x30
[ 60.723867] do_syscall_64+0x5d/0x90
[ 60.723869] ? syscall_exit_to_user_mode+0x2b/0x40
[ 60.723871] ? do_syscall_64+0x6c/0x90
[ 60.723872] ? do_syscall_64+0x6c/0x90
[ 60.723874] ? do_syscall_64+0x6c/0x90
[ 60.723875] entry_SYSCALL_64_after_hwframe+0x6e/0xd8
[ 60.723877] RIP: 0033:0x7f4ac704e2ce
[ 60.723904] Code: 48 8b 0d 65 8a 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 49 89 ca b8 04 01 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 32 8a 0d 00 f7 d8 64 89 01 48
[ 60.723905] RSP: 002b:00007ffed0b735b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000104
[ 60.723906] RAX: ffffffffffffffda RBX: 00005625366cfd80 RCX: 00007f4ac704e2ce
[ 60.723907] RDX: 0000000000000000 RSI: 00005625366cfe10 RDI: 0000000000000004
[ 60.723908] RBP: 0000000000000001 R08: 0000000000000100 R09: 0000000000000007
[ 60.723908] R10: 00000000000003e9 R11: 0000000000000246 R12: 00005625366cb9c0
[ 60.723909] R13: 00005625366cfd10 R14: 00005625366cfe10 R15: 0000000000000000
[ 60.723910] </TASK>
[ 60.723910] Modules linked in: snd_seq_dummy snd_hrtimer snd_seq snd_seq_device rfcomm ccm cmac algif_hash algif_skcipher af_alg bnep nvidia_drm(POE) nvidia_modeset(POE) snd_ctl_led snd_soc_skl_hda_dsp snd_soc_intel_hda_dsp_common snd_soc_hdac_hdmi snd_sof_probes nvidia_uvm(POE) snd_hda_codec_realtek snd_hda_codec_generic snd_soc_dmic intel_tcc_cooling snd_sof_pci_intel_tgl x86_pkg_temp_thermal intel_powerclamp snd_sof_intel_hda_common soundwire_intel coretemp snd_sof_intel_hda_mlink nvidia(POE) soundwire_cadence snd_sof_intel_hda kvm_intel snd_sof_pci snd_sof_xtensa_dsp snd_sof kvm snd_sof_utils snd_soc_hdac_hda vfat snd_hda_ext_core fat snd_soc_acpi_intel_match irqbypass snd_soc_acpi iwlmvm crct10dif_pclmul joydev soundwire_generic_allocation mousedev soundwire_bus crc32_pclmul snd_hda_codec_hdmi snd_soc_core polyval_clmulni polyval_generic snd_compress gf128mul mac80211 ac97_bus ghash_clmulni_intel snd_pcm_dmaengine sha512_ssse3 btusb aesni_intel btrtl uvcvideo snd_hda_intel crypto_simd btintel videobuf2_vmalloc
[ 60.723940] snd_intel_dspcfg cryptd libarc4 btbcm uvc snd_intel_sdw_acpi btmtk videobuf2_memops iTCO_wdt hid_multitouch snd_hda_codec intel_pmc_bxt videobuf2_v4l2 mei_hdcp mei_wdt mei_pxp rapl ee1004 iTCO_vendor_support intel_rapl_msr snd_hda_core bluetooth processor_thermal_device_pci_legacy videodev processor_thermal_device iwlwifi processor_thermal_rfim spi_nor videobuf2_common snd_hwdep intel_cstate think_lmi processor_thermal_mbox intel_uncore psmouse pcspkr cfg80211 mc ecdh_generic mtd firmware_attributes_class wmi_bmof mei_me ucsi_acpi processor_thermal_rapl snd_pcm i2c_i801 intel_lpss_pci typec_ucsi intel_rapl_common i2c_smbus intel_lpss thunderbolt i2c_hid_acpi mei snd_timer typec intel_soc_dts_iosf idma64 i2c_hid int3403_thermal roles int340x_thermal_zone int3400_thermal acpi_tad acpi_pad acpi_thermal_rel mac_hid i2c_dev crypto_user fuse acpi_call(OE) dm_mod loop ip_tables x_tables ext4 crc32c_generic crc16 mbcache jbd2 i915 thinkpad_acpi rtsx_pci_sdmmc ledtrig_audio i2c_algo_bit mmc_core serio_raw
[ 60.723972] platform_profile drm_buddy ttm snd atkbd nvme intel_gtt libps2 vivaldi_fmap soundcore drm_display_helper nvme_core xhci_pci crc32c_intel spi_intel_pci rfkill rtsx_pci spi_intel xhci_pci_renesas cec nvme_common video i8042 serio wmi
[ 60.723982] CR2: 0000000000000058
[ 60.723983] ---[ end trace 0000000000000000 ]---
[ 60.723984] RIP: 0010:eventfs_set_attr+0x28/0xd0
[ 60.723985] Code: 90 90 f3 0f 1e fa 0f 1f 44 00 00 41 55 41 54 49 89 d4 55 48 89 fd 48 c7 c7 a0 b7 b2 b2 53 48 89 f3 e8 8c 16 8c 00 4c 8b 6b 78 <41> f6 45 58 01 0f 85 87 00 00 00 48 89 de 4c 89 e2 48 89 ef e8 4f
[ 60.723986] RSP: 0018:ffffc90007fdbd38 EFLAGS: 00010246
[ 60.723987] RAX: 0000000000000000 RBX: ffff88810047e180 RCX: 8000000000000000
[ 60.723987] RDX: ffff888174b6ce00 RSI: ffff88810047e180 RDI: ffffffffb2b2b7a0
[ 60.723988] RBP: ffffffffb2b20620 R08: 0000000000000000 R09: ffffffffb2a4a488
[ 60.723989] R10: 00000000654f505f R11: 0000000018432441 R12: ffffc90007fdbe00
[ 60.723989] R13: 0000000000000000 R14: ffff88810047e180 R15: ffff8881004c02a8
[ 60.723990] FS: 00007f4ac6f4c740(0000) GS:ffff88901f540000(0000) knlGS:0000000000000000
[ 60.723991] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 60.723991] CR2: 0000000000000058 CR3: 000000021ad48001 CR4: 0000000000f70ee0
[ 60.723992] PKRU: 55555554
[ 60.723992] note: chown[2830] exited with irqs disabled
```

Thanks, if you need more information just let me know.

Cheers
  
Steven Rostedt Nov. 12, 2023, 12:14 p.m. UTC | #2
On Sun, 12 Nov 2023 11:41:58 +0100
Milian Wolff <milian.wolff@kdab.com> wrote:

> Hey all,
> 
> this patch seems to have introduced a kernel bug causing
> a NULL pointer dereference when one runs:
> 
>     sudo chown -R root:tracing /sys/kernel/debug/tracing/
> 
> See the archlinux bug report I created initially for some more information:
> https://bugs.archlinux.org/task/80230
> 
> With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
> the above `chmod` command works. With a normal 6.6.1 build, or re-applying
> the patch again, the command fails and `dmesg` shows:

Thanks for the report. I'll work on it on my way to Plumbers.

-- Steve
  
Steven Rostedt Nov. 12, 2023, 2:26 p.m. UTC | #3
On Sun, 12 Nov 2023 07:14:39 -0500
Steven Rostedt <rostedt@goodmis.org> wrote:
> > With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
> > the above `chmod` command works. With a normal 6.6.1 build, or re-applying
> > the patch again, the command fails and `dmesg` shows:  
> 
> Thanks for the report. I'll work on it on my way to Plumbers.

Can you test this patch?

Note, this code was rewritten for 6.7 so it probably doesn't affect
that tree, but I'm going to test to make sure, just in case.

Also, this shows I need to add a selftest to cover this case.

Thanks,

-- Steve

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index 5fcfb634fec2..efbdc47c74dc 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -113,14 +113,14 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
 
 	mutex_lock(&eventfs_mutex);
 	ef = dentry->d_fsdata;
-	if (ef->is_freed) {
+	if (ef && ef->is_freed) {
 		/* Do not allow changes if the event is about to be removed. */
 		mutex_unlock(&eventfs_mutex);
 		return -ENODEV;
 	}
 
 	ret = simple_setattr(idmap, dentry, iattr);
-	if (!ret)
+	if (!ret && ef)
 		update_attr(ef, iattr);
 	mutex_unlock(&eventfs_mutex);
 	return ret;
  
Linux regression tracking (Thorsten Leemhuis) Nov. 14, 2023, 1:38 p.m. UTC | #4
[TLDR: I'm adding this report to the list of tracked Linux kernel
regressions; the text you find below is based on a few templates
paragraphs you might have encountered already in similar form.
See link in footer if these mails annoy you.]

On 12.11.23 11:41, Milian Wolff wrote:
> 
> this patch seems to have introduced a kernel bug causing
> a NULL pointer dereference when one runs:
> 
>     sudo chown -R root:tracing /sys/kernel/debug/tracing/
> 
> See the archlinux bug report I created initially for some more information:
> https://bugs.archlinux.org/task/80230
> 
> With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
> the above `chmod` command works. With a normal 6.6.1 build, or re-applying
> the patch again, the command fails and `dmesg` shows:

Steven is already working on this, but to ensure the issue doesn't fall
through the cracks unnoticed, I'm adding it to regzbot, the Linux kernel
regression tracking bot (and from the context I assume it happens in
mainline as well)

#regzbot ^introduced 28e12c09f5aa081b2
#regzbot title eventfs: NULL pointer dereference regression when running
`chmod -R root:tracing /sys/kernel/debug/tracing`
#regzbot ignore-activity

This isn't a regression? This issue or a fix for it are already
discussed somewhere else? It was fixed already? You want to clarify when
the regression started to happen? Or point out I got the title or
something else totally wrong? Then just reply and tell me -- ideally
while also telling regzbot about it, as explained by the page listed in
the footer of this mail.

Developers: When fixing the issue, remember to add 'Link:' tags pointing
to the report (the parent of this mail). See page linked in footer for
details.

Ciao, Thorsten (wearing his 'the Linux kernel's regression tracker' hat)
--
Everything you wanna know about Linux kernel regression tracking:
https://linux-regtracking.leemhuis.info/about/#tldr
That page also explains what to do if mails like this annoy you.
  
Steven Rostedt Nov. 14, 2023, 1:55 p.m. UTC | #5
On Tue, 14 Nov 2023 14:38:57 +0100
"Linux regression tracking #adding (Thorsten Leemhuis)" <regressions@leemhuis.info> wrote:

> [TLDR: I'm adding this report to the list of tracked Linux kernel
> regressions; the text you find below is based on a few templates
> paragraphs you might have encountered already in similar form.
> See link in footer if these mails annoy you.]
> 
> On 12.11.23 11:41, Milian Wolff wrote:
> > 
> > this patch seems to have introduced a kernel bug causing
> > a NULL pointer dereference when one runs:
> > 
> >     sudo chown -R root:tracing /sys/kernel/debug/tracing/
> > 
> > See the archlinux bug report I created initially for some more information:
> > https://bugs.archlinux.org/task/80230
> > 
> > With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
> > the above `chmod` command works. With a normal 6.6.1 build, or re-applying
> > the patch again, the command fails and `dmesg` shows:  
> 
> Steven is already working on this, but to ensure the issue doesn't fall
> through the cracks unnoticed, I'm adding it to regzbot, the Linux kernel
> regression tracking bot (and from the context I assume it happens in
> mainline as well)

Note, the code in question was rewritten in 6.7 and the bug does not
exist there. It only exists in 6.6 and I already sent Greg the patch,
and he told me that it's in his queue.

It's only a regression in 6.6 and not in mainline.

-- Steve
  
Linux regression tracking (Thorsten Leemhuis) Nov. 14, 2023, 3:06 p.m. UTC | #6
On 14.11.23 14:55, Steven Rostedt wrote:
> On Tue, 14 Nov 2023 14:38:57 +0100
> "Linux regression tracking #adding (Thorsten Leemhuis)" <regressions@leemhuis.info> wrote:
> 
>> [TLDR: I'm adding this report to the list of tracked Linux kernel
>> regressions; the text you find below is based on a few templates
>> paragraphs you might have encountered already in similar form.
>> See link in footer if these mails annoy you.]
>>
>> On 12.11.23 11:41, Milian Wolff wrote:
>>>
>>> this patch seems to have introduced a kernel bug causing
>>> a NULL pointer dereference when one runs:
>>>
>>>     sudo chown -R root:tracing /sys/kernel/debug/tracing/
>>>
>>> See the archlinux bug report I created initially for some more information:
>>> https://bugs.archlinux.org/task/80230
>>>
>>> With 6.6.1 and 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b reverted,
>>> the above `chmod` command works. With a normal 6.6.1 build, or re-applying
>>> the patch again, the command fails and `dmesg` shows:  
>>
>> Steven is already working on this, but to ensure the issue doesn't fall
>> through the cracks unnoticed, I'm adding it to regzbot, the Linux kernel
>> regression tracking bot (and from the context I assume it happens in
>> mainline as well)
> 
> Note, the code in question was rewritten in 6.7 and the bug does not
> exist there. It only exists in 6.6 and I already sent Greg the patch,
> and he told me that it's in his queue.
> 
> It's only a regression in 6.6 and not in mainline.

Ahh, sorry fot getting this wrong and thx for letting me know.

#regzbot introduced 9aaee3eebc91dd9ccebf6b6bc8a5f59d04ef718b
#regzbot fix: eventfs: Check for NULL ef in eventfs_set_attr()

Ciao, Thorsten

P.S.: Enjoy LPC, hope to be there again next year.
  

Patch

diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
index a64d8fa39e54..6a3f7502310c 100644
--- a/fs/tracefs/event_inode.c
+++ b/fs/tracefs/event_inode.c
@@ -40,6 +40,8 @@  struct eventfs_inode {
  * @data:	something that the caller will want to get to later on
  * @is_freed:	Flag set if the eventfs is on its way to be freed
  * @mode:	the permission that the file or directory should have
+ * @uid:	saved uid if changed
+ * @gid:	saved gid if changed
  */
 struct eventfs_file {
 	const char			*name;
@@ -61,11 +63,22 @@  struct eventfs_file {
 	void				*data;
 	unsigned int			is_freed:1;
 	unsigned int			mode:31;
+	kuid_t				uid;
+	kgid_t				gid;
 };
 
 static DEFINE_MUTEX(eventfs_mutex);
 DEFINE_STATIC_SRCU(eventfs_srcu);
 
+/* Mode is unsigned short, use the upper bits for flags */
+enum {
+	EVENTFS_SAVE_MODE	= BIT(16),
+	EVENTFS_SAVE_UID	= BIT(17),
+	EVENTFS_SAVE_GID	= BIT(18),
+};
+
+#define EVENTFS_MODE_MASK	(EVENTFS_SAVE_MODE - 1)
+
 static struct dentry *eventfs_root_lookup(struct inode *dir,
 					  struct dentry *dentry,
 					  unsigned int flags);
@@ -73,8 +86,54 @@  static int dcache_dir_open_wrapper(struct inode *inode, struct file *file);
 static int dcache_readdir_wrapper(struct file *file, struct dir_context *ctx);
 static int eventfs_release(struct inode *inode, struct file *file);
 
+static void update_attr(struct eventfs_file *ef, struct iattr *iattr)
+{
+	unsigned int ia_valid = iattr->ia_valid;
+
+	if (ia_valid & ATTR_MODE) {
+		ef->mode = (ef->mode & ~EVENTFS_MODE_MASK) |
+			(iattr->ia_mode & EVENTFS_MODE_MASK) |
+			EVENTFS_SAVE_MODE;
+	}
+	if (ia_valid & ATTR_UID) {
+		ef->mode |= EVENTFS_SAVE_UID;
+		ef->uid = iattr->ia_uid;
+	}
+	if (ia_valid & ATTR_GID) {
+		ef->mode |= EVENTFS_SAVE_GID;
+		ef->gid = iattr->ia_gid;
+	}
+}
+
+static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
+			     struct iattr *iattr)
+{
+	struct eventfs_file *ef;
+	int ret;
+
+	mutex_lock(&eventfs_mutex);
+	ef = dentry->d_fsdata;
+	/* The LSB is set when the eventfs_inode is being freed */
+	if (((unsigned long)ef & 1UL) || ef->is_freed) {
+		/* Do not allow changes if the event is about to be removed. */
+		mutex_unlock(&eventfs_mutex);
+		return -ENODEV;
+	}
+
+	ret = simple_setattr(idmap, dentry, iattr);
+	if (!ret)
+		update_attr(ef, iattr);
+	mutex_unlock(&eventfs_mutex);
+	return ret;
+}
+
 static const struct inode_operations eventfs_root_dir_inode_operations = {
 	.lookup		= eventfs_root_lookup,
+	.setattr	= eventfs_set_attr,
+};
+
+static const struct inode_operations eventfs_file_inode_operations = {
+	.setattr	= eventfs_set_attr,
 };
 
 static const struct file_operations eventfs_file_operations = {
@@ -85,10 +144,20 @@  static const struct file_operations eventfs_file_operations = {
 	.release	= eventfs_release,
 };
 
+static void update_inode_attr(struct inode *inode, struct eventfs_file *ef)
+{
+	inode->i_mode = ef->mode & EVENTFS_MODE_MASK;
+
+	if (ef->mode & EVENTFS_SAVE_UID)
+		inode->i_uid = ef->uid;
+
+	if (ef->mode & EVENTFS_SAVE_GID)
+		inode->i_gid = ef->gid;
+}
+
 /**
  * create_file - create a file in the tracefs filesystem
- * @name: the name of the file to create.
- * @mode: the permission that the file should have.
+ * @ef: the eventfs_file
  * @parent: parent dentry for this file.
  * @data: something that the caller will want to get to later on.
  * @fop: struct file_operations that should be used for this file.
@@ -104,7 +173,7 @@  static const struct file_operations eventfs_file_operations = {
  * If tracefs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
  */
-static struct dentry *create_file(const char *name, umode_t mode,
+static struct dentry *create_file(struct eventfs_file *ef,
 				  struct dentry *parent, void *data,
 				  const struct file_operations *fop)
 {
@@ -112,13 +181,13 @@  static struct dentry *create_file(const char *name, umode_t mode,
 	struct dentry *dentry;
 	struct inode *inode;
 
-	if (!(mode & S_IFMT))
-		mode |= S_IFREG;
+	if (!(ef->mode & S_IFMT))
+		ef->mode |= S_IFREG;
 
-	if (WARN_ON_ONCE(!S_ISREG(mode)))
+	if (WARN_ON_ONCE(!S_ISREG(ef->mode)))
 		return NULL;
 
-	dentry = eventfs_start_creating(name, parent);
+	dentry = eventfs_start_creating(ef->name, parent);
 
 	if (IS_ERR(dentry))
 		return dentry;
@@ -127,7 +196,10 @@  static struct dentry *create_file(const char *name, umode_t mode,
 	if (unlikely(!inode))
 		return eventfs_failed_creating(dentry);
 
-	inode->i_mode = mode;
+	/* If the user updated the directory's attributes, use them */
+	update_inode_attr(inode, ef);
+
+	inode->i_op = &eventfs_file_inode_operations;
 	inode->i_fop = fop;
 	inode->i_private = data;
 
@@ -140,7 +212,7 @@  static struct dentry *create_file(const char *name, umode_t mode,
 
 /**
  * create_dir - create a dir in the tracefs filesystem
- * @name: the name of the file to create.
+ * @ei: the eventfs_inode that represents the directory to create
  * @parent: parent dentry for this file.
  * @data: something that the caller will want to get to later on.
  *
@@ -155,13 +227,14 @@  static struct dentry *create_file(const char *name, umode_t mode,
  * If tracefs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
  */
-static struct dentry *create_dir(const char *name, struct dentry *parent, void *data)
+static struct dentry *create_dir(struct eventfs_file *ef,
+				 struct dentry *parent, void *data)
 {
 	struct tracefs_inode *ti;
 	struct dentry *dentry;
 	struct inode *inode;
 
-	dentry = eventfs_start_creating(name, parent);
+	dentry = eventfs_start_creating(ef->name, parent);
 	if (IS_ERR(dentry))
 		return dentry;
 
@@ -169,7 +242,8 @@  static struct dentry *create_dir(const char *name, struct dentry *parent, void *
 	if (unlikely(!inode))
 		return eventfs_failed_creating(dentry);
 
-	inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
+	update_inode_attr(inode, ef);
+
 	inode->i_op = &eventfs_root_dir_inode_operations;
 	inode->i_fop = &eventfs_file_operations;
 	inode->i_private = data;
@@ -306,10 +380,9 @@  create_dentry(struct eventfs_file *ef, struct dentry *parent, bool lookup)
 		inode_lock(parent->d_inode);
 
 	if (ef->ei)
-		dentry = create_dir(ef->name, parent, ef->data);
+		dentry = create_dir(ef, parent, ef->data);
 	else
-		dentry = create_file(ef->name, ef->mode, parent,
-				     ef->data, ef->fop);
+		dentry = create_file(ef, parent, ef->data, ef->fop);
 
 	if (!lookup)
 		inode_unlock(parent->d_inode);
@@ -475,6 +548,7 @@  static int dcache_dir_open_wrapper(struct inode *inode, struct file *file)
 		if (d) {
 			struct dentry **tmp;
 
+
 			tmp = krealloc(dentries, sizeof(d) * (cnt + 2), GFP_KERNEL);
 			if (!tmp)
 				break;
@@ -549,13 +623,14 @@  static struct eventfs_file *eventfs_prepare_ef(const char *name, umode_t mode,
 			return ERR_PTR(-ENOMEM);
 		}
 		INIT_LIST_HEAD(&ef->ei->e_top_files);
+		ef->mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
 	} else {
 		ef->ei = NULL;
+		ef->mode = mode;
 	}
 
 	ef->iop = iop;
 	ef->fop = fop;
-	ef->mode = mode;
 	ef->data = data;
 	return ef;
 }