[PATCH v12 1/9] security: Introduce ENOFILEOPS return value for IOCTL hooks
Mickaël Salaün
mic at digikod.net
Tue Mar 26 14:28:08 UTC 2024
On Tue, Mar 26, 2024 at 02:09:47PM +0100, Günther Noack wrote:
> On Tue, Mar 26, 2024 at 12:58:42PM +0100, Arnd Bergmann wrote:
> > On Tue, Mar 26, 2024, at 11:10, Mickaël Salaün wrote:
> > > On Tue, Mar 26, 2024 at 10:33:23AM +0100, Arnd Bergmann wrote:
> > >> On Tue, Mar 26, 2024, at 09:32, Mickaël Salaün wrote:
> > >> >
> > >> > This is indeed a simpler solution but unfortunately this doesn't fit
> > >> > well with the requirements for an access control, especially when we
> > >> > need to log denied accesses. Indeed, with this approach, the LSM (or
> > >> > any other security mechanism) that returns ENOFILEOPS cannot know for
> > >> > sure if the related request will allowed or not, and then it cannot
> > >> > create reliable logs (unlike with EACCES or EPERM).
> > >>
> > >> Where does the requirement come from specifically, i.e.
> > >> who is the consumer of that log?
> > >
> > > The audit framework may be used by LSMs to log denials.
> > >
> > >>
> > >> Even if the log doesn't tell you directly whether the ioctl
> > >> was ultimately denied, I would think logging the ENOFILEOPS
> > >> along with the command number is enough to reconstruct what
> > >> actually happened from reading the log later.
> > >
> > > We could indeed log ENOFILEOPS but that could include a lot of allowed
> > > requests and we usually only want unlegitimate access requests to be
> > > logged. Recording all ENOFILEOPS would mean 1/ that logs would be
> > > flooded by legitimate requests and 2/ that user space log parsers would
> > > need to deduce if a request was allowed or not, which require to know
> > > the list of IOCTL commands implemented by fs/ioctl.c, which would defeat
> > > the goal of this specific patch.
> >
> > Right, makes sense. Unfortunately that means I don't see any
> > option that I think is actually better than what we have today,
> > but that forces the use of a custom whitelist or extra logic in
> > landlock.
> >
> > I didn't really mind having an extra hook for the callbacks
> > in addition to the top-level one, but that was already nacked.
>
> Thank you both for the review!
>
> I agree, this approach would break logging.
>
> As you both also said, I also think this leads us back to the approach
> where we hardcode the allow-list of permitted IOCTL commands in the
> file_ioctl hook.
>
> I think this approach has the following upsides:
>
> 1. Landlock's (future) audit logging will be able to log exactly
> which IOCTL commands were denied.
> 2. The allow-list of permitted IOCTL commands can be reasoned about
> locally and does not accidentally change as a side-effect of a
> change to the implementation of fs/ioctl.c.
>
> A risk that we have is:
>
> 3. We might miss changes to fs/ioctl.c which we might want to
> reflect in Landlock.
>
>
> To think about 2 and 3 in more concrete terms, I categorized the
> scenarios in which IOCTL cmd implementations can get added to or
> removed from the do_vfs_ioctl() layer:
>
> Case A: New cmd added to do_vfs_ioctl layer
>
> We want to double check whether this cmd should be included in
> Landlock's allow list. (Because the command is new, there are no
> existing users of the IOCTL command, so we can't break anyone and
> we it probably does not require to be made explicit in Landlock's
> ABI versioning scheme.)
>
> ==> We need to catch these changes early,
> and should do Landlock-side changes in sync.
>
> Case B: Existing cmd removed from do_vfs_ioctl layer
>
> (This case is unlikely, as it would be a backwards-incompatible
> change in the ioctl interface.)
>
> Case C: Existing cmd is moved from f_ops->..._ioctl() to do_vfs_ioctl()
>
> (For regular files, I think this has happened for the XFS
> "reflink" ioctls before, which became features in other COW file
> systems as well.)
>
> If such a change happens for device files (which are in scope for
> Landlock's IOCTL feature), we should catch these changes. We
> should consider whether the affected IOCTL command should be
> allow-listed. Strictly speaking, if we allow-list the cmd, which
> was previously not allow-listed, this would mean that Landlock's
> DEV_IOCTL feature would have different semantics than before
> (permitting an additional cmd), and it would potentially be a
> backwards-incompatible change that need to be made explicit in
> Landlock's ABI versioning.
>
> Case D: Existing cmd is moved from do_vfs_ioctl() to f_ops->..._ioctl()
>
> (This case seems also very unlikely to me because it decentralizes
> the reasoning about these IOCTL APIs which are currently centrally
> controlled and must stay backwards compatible.)
>
Excellent summary! You should put a link to this email in the commit
message and quickly explain why we ended up here.
>
>
> So -- a proposal:
>
> * Keep the original implementation of fs/ioctl.c
> * Implement Landlock's file_ioctl hook with a switch(cmd) where we list
> the permitted IOCTL commands from do_vfs_ioctl.
> * Make sure Landlock maintainers learn about changes to do_vfs_ioctl():
> * Put a warning on top of do_vfs_ioctl() to loop in Landlock
> maintainers
Yes please.
> * Set up automation to catch such changes?
>
>
> Open questions are:
>
> * Mickaël, do you think we should use a more device-file-specific
> subset of IOCTL commands again, or would you prefer to stick to the
> full list of all IOCTL commands implemented in do_vfs_ioctl()?
We should stick to the device-file-specific IOCTL commands [1] but we
should probably complete the switch-case with commented cases (in the
same order as in do_vfs_ioctl) to know which one were reviewed (as in
[1]). These helpers should now be static and in security/landlock/fs.c
[1] https://lore.kernel.org/r/20240219183539.2926165-1-mic@digikod.net
BTW, there are now two new IOCTL commands (FS_IOC_GETUUID and
FS_IOC_GETFSSYSFSPATH) masking device-specific IOCTL ones.
>
> * Regarding automation:
>
> We could additionally set up some automation to watch changes to
> do_vfs_ioctl(). Given the low rate of change in that corner, we
> might get away with extracting the relevant portion of the C file
> (awk '/^static int do_vfs_ioctl/, /^\}/' fs/ioctl.c) and watching
> for any changes. It is brittle, but the rate of changes is low, and
> reasoning about source code is difficult and error prone as well.
>
> In an ideal world this could maybe be part of the kernel test
> suites, but I still have not found the right place where this could
> be hooked in. Do you have any thoughts on this?
I think this change should be enough for now:
diff --git a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12222,6 +12222,7 @@ W: https://landlock.io
T: git https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git
F: Documentation/security/landlock.rst
F: Documentation/userspace-api/landlock.rst
+F: fs/ioctl.c
F: include/uapi/linux/landlock.h
F: samples/landlock/
F: security/landlock/
It should be OK considered the number of patches matching this file: a
subset of https://lore.kernel.org/all/?q=dfn%3Afs%2Fioctl.c
More information about the Linux-security-module-archive
mailing list