[PATCH v9 1/8] landlock: Add IOCTL access right
Arnd Bergmann
arnd at arndb.de
Sat Feb 10 11:49:23 UTC 2024
On Sat, Feb 10, 2024, at 12:06, Günther Noack wrote:
> On Fri, Feb 09, 2024 at 06:06:05PM +0100, Günther Noack wrote:
>
> The IOCTL command in question is FIONREAD: fs/ioctl.c implements
> FIONREAD directly for S_ISREG files, but it does call the FIONREAD
> implementation in the VFS layer for other file types.
>
> The question we are asking ourselves is:
>
> * Can we let processes safely use FIONREAD for all files which get
> opened for the purpose of reading, or do we run the risk of
> accidentally exposing surprising IOCTL implementations which have
> completely different purposes?
>
> Is it safe to assume that the VFS layer FIONREAD implementations are
> actually implementing FIONREAD semantics?
>
> * I know there have been accidental collisions of IOCTL command
> numbers in the past -- Hypothetically, if this were to happen in one
> of the VFS implementations of FIONREAD, would that be considered a
> bug that would need to get fixed in that implementation?
Clearly it's impossible to be sure no driver has a conflict
on this particular ioctl, but the risk for one intentionally
overriding it should be fairly low.
There are a couple of possible issues I can think of:
- the numeric value of FIONREAD is different depending
on the architecture, with at least four different numbers
aliasing to it. This is probably harmless but makes it
harder to look for accidental conflicts.
- Aside from FIONREAD, it is sometimes called SIOCINQ
(for sockets) or TIOCINQ (for tty). These still go
through the same VFS entry point and as far as I can
tell always have the same semantics (writing 4 bytes
of data with the count of the remaining bytes in the
fd).
- There are probably a couple of drivers that do something
in their ioctl handler without actually looking at
the command number.
If you want to be really sure you get this right, you
could add a new callback to struct file_operations
that handles this for all drivers, something like
static int ioctl_fionread(struct file *filp, int __user *arg)
{
int n;
if (S_ISREG(inode->i_mode))
return put_user(i_size_read(inode) - filp->f_pos, arg);
if (!file->f_op->fionread)
return -ENOIOCTLCMD;
n = file->f_op->fionread(filp);
if (n < 0)
return n;
return put_user(n, arg);
}
With this, you can go through any driver implementing
FIONREAD/SIOCINQ/TIOCINQ and move the code from .ioctl
into .fionread. This probably results in cleaner code
overall, especially in drivers that have no other ioctl
commands besides this one.
Since sockets and ttys tend to have both SIOCINQ/TIOCINQ
and SIOCOUTQ/TIOCOUTQ (unlike regular files), it's
probably best to do both at the same time, or maybe
have a single callback pointer with an in/out flag.
Arnd
More information about the Linux-security-module-archive
mailing list