[PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl

Abhinav Saxena via B4 Relay posted 2 patches 3 months, 2 weeks ago
[PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl
Posted by Abhinav Saxena via B4 Relay 3 months, 2 weeks ago
From: Abhinav Saxena <xandfury@gmail.com>

The TIOCSTI ioctl currently only checks the current process's
credentials, creating a TOCTOU vulnerability where an unprivileged
process can open a TTY fd and pass it to a privileged process via
SCM_RIGHTS.

Fix by requiring BOTH the file opener (file->f_cred) AND the current
process to have CAP_SYS_ADMIN. This prevents privilege escalation
while ensuring legitimate use cases continue to work.

Link: https://github.com/KSPP/linux/issues/156

Signed-off-by: Abhinav Saxena <xandfury@gmail.com>
---
 security/selinux/hooks.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 595ceb314aeb..a628551873ab 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3847,6 +3847,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
 					    CAP_OPT_NONE, true);
 		break;
 
+	case TIOCSTI:
+		if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN) ||
+		    !capable(CAP_SYS_ADMIN))
+			error = -EPERM;
+		break;
+
 	case FIOCLEX:
 	case FIONCLEX:
 		if (!selinux_policycap_ioctl_skip_cloexec())

-- 
2.43.0
Re: [PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl
Posted by Stephen Smalley 3 months, 2 weeks ago
On Sun, Jun 22, 2025 at 9:41 PM Abhinav Saxena via B4 Relay
<devnull+xandfury.gmail.com@kernel.org> wrote:
>
> From: Abhinav Saxena <xandfury@gmail.com>
>
> The TIOCSTI ioctl currently only checks the current process's
> credentials, creating a TOCTOU vulnerability where an unprivileged
> process can open a TTY fd and pass it to a privileged process via
> SCM_RIGHTS.
>
> Fix by requiring BOTH the file opener (file->f_cred) AND the current
> process to have CAP_SYS_ADMIN. This prevents privilege escalation
> while ensuring legitimate use cases continue to work.
>
> Link: https://github.com/KSPP/linux/issues/156
>
> Signed-off-by: Abhinav Saxena <xandfury@gmail.com>
> ---
>  security/selinux/hooks.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 595ceb314aeb..a628551873ab 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -3847,6 +3847,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
>                                             CAP_OPT_NONE, true);
>                 break;
>
> +       case TIOCSTI:
> +               if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN) ||
> +                   !capable(CAP_SYS_ADMIN))
> +                       error = -EPERM;
> +               break;
> +

So, aside from what I said previously, this also will break any
existing policies currently controlling TIOCSTI
via the selinux ioctl checking in the default case, so at the very
least, this would need to be gated by a new
SELinux policy capability for compatibility purposes. But I'm still
unconvinced that this is the right approach.

>         case FIOCLEX:
>         case FIONCLEX:
>                 if (!selinux_policycap_ioctl_skip_cloexec())
>
> --
> 2.43.0
>
>
Re: [PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl
Posted by Paul Moore 3 months, 2 weeks ago
On Mon, Jun 23, 2025 at 8:39 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
> On Sun, Jun 22, 2025 at 9:41 PM Abhinav Saxena via B4 Relay
> <devnull+xandfury.gmail.com@kernel.org> wrote:
> >
> > From: Abhinav Saxena <xandfury@gmail.com>
> >
> > The TIOCSTI ioctl currently only checks the current process's
> > credentials, creating a TOCTOU vulnerability where an unprivileged
> > process can open a TTY fd and pass it to a privileged process via
> > SCM_RIGHTS.
> >
> > Fix by requiring BOTH the file opener (file->f_cred) AND the current
> > process to have CAP_SYS_ADMIN. This prevents privilege escalation
> > while ensuring legitimate use cases continue to work.
> >
> > Link: https://github.com/KSPP/linux/issues/156
> >
> > Signed-off-by: Abhinav Saxena <xandfury@gmail.com>
> > ---
> >  security/selinux/hooks.c | 6 ++++++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 595ceb314aeb..a628551873ab 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -3847,6 +3847,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
> >                                             CAP_OPT_NONE, true);
> >                 break;
> >
> > +       case TIOCSTI:
> > +               if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN) ||
> > +                   !capable(CAP_SYS_ADMIN))
> > +                       error = -EPERM;
> > +               break;
> > +
>
> So, aside from what I said previously, this also will break any
> existing policies currently controlling TIOCSTI
> via the selinux ioctl checking in the default case, so at the very
> least, this would need to be gated by a new
> SELinux policy capability for compatibility purposes. But I'm still
> unconvinced that this is the right approach.

I want to add my voice to the other comments that adding these
capability checks to the SELinux code and not the main TIOCSTI kernel
code is not an approach we want to support.  Beyond that, as others
have already pointed out, I think some additional inspection and
testing is needed to ensure that the additional capability checks do
not break existing, valid use cases.

-- 
paul-moore.com
Re: [PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl
Posted by Günther Noack 3 months, 2 weeks ago
On Mon, Jun 23, 2025 at 11:15:39AM -0400, Paul Moore wrote:
> On Mon, Jun 23, 2025 at 8:39 AM Stephen Smalley
> <stephen.smalley.work@gmail.com> wrote:
> > On Sun, Jun 22, 2025 at 9:41 PM Abhinav Saxena via B4 Relay
> > <devnull+xandfury.gmail.com@kernel.org> wrote:
> > > --- a/security/selinux/hooks.c
> > > +++ b/security/selinux/hooks.c
> > > @@ -3847,6 +3847,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
> > >                                             CAP_OPT_NONE, true);
> > >                 break;
> > >
> > > +       case TIOCSTI:
> > > +               if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN) ||
> > > +                   !capable(CAP_SYS_ADMIN))
> > > +                       error = -EPERM;
> > > +               break;
> > > +
> >
> > So, aside from what I said previously, this also will break any
> > existing policies currently controlling TIOCSTI
> > via the selinux ioctl checking in the default case, so at the very
> > least, this would need to be gated by a new
> > SELinux policy capability for compatibility purposes. But I'm still
> > unconvinced that this is the right approach.
> 
> I want to add my voice to the other comments that adding these
> capability checks to the SELinux code and not the main TIOCSTI kernel
> code is not an approach we want to support.  Beyond that, as others
> have already pointed out, I think some additional inspection and
> testing is needed to ensure that the additional capability checks do
> not break existing, valid use cases.

+1 from me as well.

If the perceived problem is in core TTY logic, but the proposed fix is
in SELinux, it only addresses a fraction of the install base, as not
all machines use SELinux.

Also, it's not clear to me why the perceived problem of FD-passsing
with SCM_RIGHTS is a problem at all.  If a CAP_SYS_ADMIN process
accepts FDs over SCM_RIGHTS, it is the responsibility of that process
not to do unjustified privileged operations with these FDs, on behalf
of other, less privileged, processes.

In the more classic attack scenarios (as described in a series of CVEs
[1]) the process who had the FD first is normally the more privileged
one, for for those ones, the existing CAP_SYS_ADMIN check seems fine.

—Günther

[1] https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=TIOCSTI

-- 
Re: [PATCH 2/2] selinux: add capability checks for TIOCSTI ioctl
Posted by Greg KH 3 months, 2 weeks ago
On Sun, Jun 22, 2025 at 07:41:08PM -0600, Abhinav Saxena via B4 Relay wrote:
> From: Abhinav Saxena <xandfury@gmail.com>
> 
> The TIOCSTI ioctl currently only checks the current process's
> credentials, creating a TOCTOU vulnerability where an unprivileged
> process can open a TTY fd and pass it to a privileged process via
> SCM_RIGHTS.

If a priviliged process has a fd, what is the problem with it using this
ioctl in the firstplace?

> 
> Fix by requiring BOTH the file opener (file->f_cred) AND the current
> process to have CAP_SYS_ADMIN. This prevents privilege escalation
> while ensuring legitimate use cases continue to work.
> 
> Link: https://github.com/KSPP/linux/issues/156
> 
> Signed-off-by: Abhinav Saxena <xandfury@gmail.com>
> ---
>  security/selinux/hooks.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 595ceb314aeb..a628551873ab 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -3847,6 +3847,12 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
>  					    CAP_OPT_NONE, true);
>  		break;
>  
> +	case TIOCSTI:
> +		if (!file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN) ||
> +		    !capable(CAP_SYS_ADMIN))
> +			error = -EPERM;
> +		break;

Are you sure this type of policy should be in the selinux core code?
Wouldn't you need a "rule" for selinux to follow (or not follow) for
this type of thing and not just a blanket change to the logic?

Also, have you looked at what userspace tools actually use this ioctl to
see if this change would break anything?

thanks,

greg k-h