From: Christian Brauner <brauner@kernel.org>
To: James Bottomley <James.Bottomley@hansenpartnership.com>
Cc: "Ard Biesheuvel" <ardb@kernel.org>,
"Al Viro" <viro@zeniv.linux.org.uk>,
"Ryan Lee" <ryan.lee@canonical.com>,
"Malte Schröder" <malte.schroeder@tnxip.de>,
linux-security-module@vger.kernel.org,
apparmor <apparmor@lists.ubuntu.com>,
linux-efi@vger.kernel.org,
"John Johansen" <john.johansen@canonical.com>,
"jk@ozlabs.org" <jk@ozlabs.org>,
linux-fsdevel@vger.kernel.org
Subject: Re: apparmor NULL pointer dereference on resume [efivarfs]
Date: Tue, 11 Mar 2025 17:19:01 +0100 [thread overview]
Message-ID: <20250311-gelage-abgraben-b5de5b6ba126@brauner> (raw)
In-Reply-To: <20250311-trunk-farben-fe36bebe233a@brauner>
On Tue, Mar 11, 2025 at 04:55:16PM +0100, Christian Brauner wrote:
> On Tue, Mar 11, 2025 at 09:01:36AM -0400, James Bottomley wrote:
> > On Tue, 2025-03-11 at 09:45 +0100, Christian Brauner wrote:
> > > On Tue, Mar 11, 2025 at 08:16:34AM +0100, Ard Biesheuvel wrote:
> > > > (cc Al Viro)
> > > >
> > > > On Mon, 10 Mar 2025 at 22:49, James Bottomley
> > > > <James.Bottomley@hansenpartnership.com> wrote:
> > [...]
> > > > > The problem comes down to the superblock functions not being able
> > > > > to get the struct vfsmount for the superblock (because it isn't
> > > > > even allocated until after they've all been called). The
> > > > > assumption I was operating under was that provided I added
> > > > > O_NOATIME to prevent the parent directory being updated, passing
> > > > > in a NULL mnt for the purposes of iterating the directory dentry
> > > > > was safe. What apparmour is trying to do is look up the idmap
> > > > > for the mount point to do one of its checks.
> > > > >
> > > > > There are two ways of fixing this that I can think of. One would
> > > > > be exporting a function that lets me dig the vfsmount out of
> > > > > s_mounts and use that (it's well hidden in the internals of
> > > > > fs/mount.h, so I suspect this might not be very acceptable) or to
> > > > > get mnt_idmap to return
> > >
> > > Nope, please don't.
> > >
> > > > > &nop_mnt_idmap if the passed in mnt is NULL. I'd lean towards
> > > > > the latter, but I'm cc'ing fsdevel to see what others think.
> > >
> > > A struct path with mount NULL and dentry != NULL is guaranteed to bit
> > > us in the ass in other places. That's the bug.
> > >
> > > > >
> > > >
> > > >
> > > > Al spotted the same issue based on a syzbot report [0]
> > > >
> > > > [0] https://lore.kernel.org/all/20250310235831.GL2023217@ZenIV/
> > >
> > > efivars as written only has a single global superblock and it doesn't
> > > support idmapped mounts and I don't see why it ever would.
> >
> > So that's not quite true: efivarfs currently supports uid and gid
> > mapping as mount options, which certainly looks like they were designed
> > to allow a second mount in a user directory. I've no idea what the
> > actual use case for this is, but if I go for a single superblock, any
> > reconfigure with new uid/gid would become globally effective (change
> > every current mount) because they're stored in the superblock
> > information.
> >
> > So what is the use case for this uid/gid parameter? If no-one can
> > remember and no-one actually uses it, perhaps the whole config path can
> > be simplified by getting rid of the options? Even if there is a use
> > case, if it's single mount only then we can still go with a global
> > superblock.
>
> So efivarfs uses get_tree_single(). That means that only a single
> superblock of the filesystem type efivarfs can ever exist on the system.
>
> If efivars is mounted multiple times it will be the exact same
> superblock that's used. IOW, mounting efivars multiple times is akin to
> a bind-mount. It would be a bit ugly but it could be done by making sure
> that any uid/gid changes are reflected. But see below.
>
> >
> > > But since efivars does only ever have a single global superblock, one
> > > possibility is to an internal superblock that always exits and is
> > > resurfaced whenever userspace mounts efivarfs. That's essentially the
> > > devtmpfs model.
> > >
> > > Then you can stash:
> > >
> > > static struct vfsmount *efivarfs_mnt;
> > >
> > > globally and use that in efivarfs_pm_notify() to fill in struct path.
> >
> > I didn't see devtmpfs when looking for examples, since it's hiding
> > outside of the fs/ directory. However, it does seem to be a bit legacy
> > nasty as an example to copy. However, I get the basics: we'd
> > instantiate the mnt and superblock on init (stashing mnt in the sfi so
> > the notifier gets it). Then we can do the variable population on
> > reconfigure, just in case an EFI system doesn't want to mount efivarfs
> > to save memory.
> >
> > I can code that up if I can get an answer to the uid/gid parameter
> > question above.
>
> I have some questions. efivarfs registers efivarfs_pm_notify even before
> a superblock exists in efivarfs_init_fs_context(). That's called during
> fd_context = fsopen("efivarfs") before a superblock even exists:
>
> (1) Is it guaranteed that efivarfs_pm_notify() is only called once a
> superblock exists?
>
> (2) Is it guaranteed that efivarfs_pm_notify() is only called when and
> while a mount for the superblock exists?
>
> If the question to either one of those is "no" then the global
> vfsmount hack will not help.
>
> >From reading efivarfs_pm_notify() it looks like the answer to (1) is
> "yes" because you're dereferencing sfi->sb->s_root in
> efivarfs_pm_notify().
>
> But I'm not at all certain that (2) isn't a "no" and that
> efivarfs_pm_notify() can be called before a mount exists. IOW, once
> fsconfig(FSCONFIG_CMD_CREATE) is called the notifier seems ready and
> registered but userspace isn't forced to call fsmount(fd_fs) at all.
>
> They could just not to do it for whatever reason but the notifier should
> already be able to run.
>
> Another question is whether the superblock can be freed while
> efivarfs_pm_notify() is running? I think that can't happen because
> blocking_notifier_chain_unregister(&efivar_ops_nh, &sfi->nb) will block
> in efivarfs_kill_sb() until all outstanding calls to
> efivarfs_pm_notify() are finished?
>
> If (2) isn't guranteed then efivarfs_pm_notify() needs to be rewritten
> without relying on files because there's no guarantee that a mount
> exists at all.
Btw, sorry but I'm going to be able to (guarantee) to respond Wed - Fri
because I'm on kid-watch-duty.
next prev parent reply other threads:[~2025-03-11 16:19 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-05 19:04 apparmor NULL pointer dereference on resume Malte Schröder
2025-03-05 19:22 ` Ryan Lee
2025-03-05 21:47 ` Malte Schröder
2025-03-10 19:57 ` Ryan Lee
2025-03-10 21:49 ` apparmor NULL pointer dereference on resume [efivarfs] James Bottomley
2025-03-11 7:16 ` Ard Biesheuvel
2025-03-11 8:45 ` Christian Brauner
2025-03-11 13:01 ` James Bottomley
2025-03-11 15:55 ` Christian Brauner
2025-03-11 16:19 ` Christian Brauner [this message]
2025-03-11 16:20 ` James Bottomley
2025-03-11 17:15 ` Al Viro
2025-03-11 17:46 ` James Bottomley
2025-03-14 14:59 ` [RFC 1/1] fix NULL mnt [was Re: apparmor NULL pointer dereference on resume [efivarfs]] James Bottomley
2025-03-15 10:04 ` Christian Brauner
2025-03-15 18:41 ` James Bottomley
2025-03-16 6:46 ` Christian Brauner
2025-03-16 14:26 ` James Bottomley
2025-03-16 19:19 ` Ard Biesheuvel
2025-03-17 8:56 ` Christian Brauner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250311-gelage-abgraben-b5de5b6ba126@brauner \
--to=brauner@kernel.org \
--cc=James.Bottomley@hansenpartnership.com \
--cc=apparmor@lists.ubuntu.com \
--cc=ardb@kernel.org \
--cc=jk@ozlabs.org \
--cc=john.johansen@canonical.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=malte.schroeder@tnxip.de \
--cc=ryan.lee@canonical.com \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox