Re: wall(1) unveil for non-root users

2019-05-16 Thread Theo de Raadt
Philip Guenther  wrote:

> On Wed, May 15, 2019 at 10:54 PM Theo de Raadt  wrote:
> 
>  Martijn van Duren  wrote:
> 
>  > I don't see much point in the check.
>  > 
>  > If we don't have write permissions open(2) will fail.
>  > If we open it based on S_IWOTH permissions than checking for S_IWGRP
>  > without considering who is in that group seems really absurd to me.
>  > 
>  > So I'd be OK with patch 1
> 
>  There are 3 write permission checks which could permit the open,
>  but then it checks the specific one.
> 
>  I believe this is similar to comsat / biff, which in those programs
>  are used to indicate "I am ok with messages to my tty".
> 
>  That is an old behaviour, but I bet that is the history of this S_IWGRP 
> check.
> 
> Yep.  mesg(1) manipulates your tty's group-write bit so that wall(1), 
> talk(1), and write(1) can check it.

Amusing, write(1) has a very similar TOCTOU.

These are not serious, but if they were fixes there are opportunities for 
unveil and pledge to
maybe prevent other bad behaviour in the future..



Re: wall(1) unveil for non-root users

2019-05-16 Thread Philip Guenther
On Wed, May 15, 2019 at 10:54 PM Theo de Raadt  wrote:

> Martijn van Duren  wrote:
>
> > I don't see much point in the check.
> >
> > If we don't have write permissions open(2) will fail.
> > If we open it based on S_IWOTH permissions than checking for S_IWGRP
> > without considering who is in that group seems really absurd to me.
> >
> > So I'd be OK with patch 1
>
> There are 3 write permission checks which could permit the open,
> but then it checks the specific one.
>
> I believe this is similar to comsat / biff, which in those programs
> are used to indicate "I am ok with messages to my tty".
>
> That is an old behaviour, but I bet that is the history of this S_IWGRP
> check.
>

Yep.  mesg(1) manipulates your tty's group-write bit so that wall(1),
talk(1), and write(1) can check it.

Philip Guenther


Re: wall(1) unveil for non-root users

2019-05-16 Thread Martijn van Duren
On 5/16/19 7:53 AM, Theo de Raadt wrote:
> Martijn van Duren  wrote:
> 
>> I don't see much point in the check.
>>
>> If we don't have write permissions open(2) will fail.
>> If we open it based on S_IWOTH permissions than checking for S_IWGRP
>> without considering who is in that group seems really absurd to me.
>>
>> So I'd be OK with patch 1
> 
> There are 3 write permission checks which could permit the open,
> but then it checks the specific one.
> 
> I believe this is similar to comsat / biff, which in those programs
> are used to indicate "I am ok with messages to my tty".
> 
> That is an old behaviour, but I bet that is the history of this S_IWGRP check.
> 
Sounds valid. Personally I think it's a rather obscure feature that can 
go as far as I'm concerned, but if people want it I'm OK with either 
diff.

martijn@



Re: wall(1) unveil for non-root users

2019-05-15 Thread Theo de Raadt
Martijn van Duren  wrote:

> I don't see much point in the check.
> 
> If we don't have write permissions open(2) will fail.
> If we open it based on S_IWOTH permissions than checking for S_IWGRP
> without considering who is in that group seems really absurd to me.
> 
> So I'd be OK with patch 1

There are 3 write permission checks which could permit the open,
but then it checks the specific one.

I believe this is similar to comsat / biff, which in those programs
are used to indicate "I am ok with messages to my tty".

That is an old behaviour, but I bet that is the history of this S_IWGRP check.



Re: wall(1) unveil for non-root users

2019-05-15 Thread Martijn van Duren
I don't see much point in the check.

If we don't have write permissions open(2) will fail.
If we open it based on S_IWOTH permissions than checking for S_IWGRP
without considering who is in that group seems really absurd to me.

So I'd be OK with patch 1

martijn@

On 5/16/19 12:46 AM, Theo de Raadt wrote:
> Anton Borowka  wrote:
> 
>> wall(1) does not work correctly for non-root users at the moment because
>> ttymsg() needs read access for the tty devices, but only write access is
>> unveiled. Because it cannot access any devices nothing is printed.
>>
>> This patch adds read access for /dev. Don't know if it makes sense to
>> only unveil read access for non-root users.
> 
> Apparently it stat()'s the devices [thereby desiring "r"], before calling
> open O_WRONLY [which only needs "w"].
> 
> It is a TOCTOU.  Here are two proposals.
> 
> This one lets non-root write to any fd it can manage to open.
> 
> Index: ttymsg.c
> ===
> RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
> retrieving revision 1.17
> diff -u -p -u -r1.17 ttymsg.c
> --- ttymsg.c  5 Nov 2015 22:20:11 -   1.17
> +++ ttymsg.c  15 May 2019 22:39:44 -
> @@ -87,13 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
>   return (errbuf);
>   }
>  
> - if (getuid()) {
> - if (stat(device, ) < 0)
> - return (NULL);
> - if ((st.st_mode & S_IWGRP) == 0)
> - return (NULL);
> - }
> -
>   /*
>* open will fail on slip lines or exclusive-use lines
>* if not running as root; not an error.
> 
> This one is a bit more cautious, it checks if specifically g+w
> is allowed on the tty, that is more true to the original behaviour
> isn't it?
> 
> Index: ttymsg.c
> ===
> RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
> retrieving revision 1.17
> diff -u -p -u -r1.17 ttymsg.c
> --- ttymsg.c  5 Nov 2015 22:20:11 -   1.17
> +++ ttymsg.c  15 May 2019 22:42:58 -
> @@ -87,12 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
>   return (errbuf);
>   }
>  
> - if (getuid()) {
> - if (stat(device, ) < 0)
> - return (NULL);
> - if ((st.st_mode & S_IWGRP) == 0)
> - return (NULL);
> - }
>  
>   /*
>* open will fail on slip lines or exclusive-use lines
> @@ -104,6 +98,17 @@ ttymsg(iov, iovcnt, line, tmout)
>   (void) snprintf(errbuf, sizeof(errbuf),
>   "%s: %s", device, strerror(errno));
>   return (errbuf);
> + }
> +
> + if (getuid()) {
> + if (fstat(fd, ) < 0) {
> + close(fd);
> + return (NULL);
> + }
> + if ((st.st_mode & S_IWGRP) == 0) {
> + close(fd);
> + return (NULL);
> + }
>   }
>  
>   for (cnt = left = 0; cnt < iovcnt; ++cnt)
> 



Re: wall(1) unveil for non-root users

2019-05-15 Thread Anton Borowka
"Theo de Raadt"  writes:

> Anton Borowka  wrote:
>
>> wall(1) does not work correctly for non-root users at the moment because
>> ttymsg() needs read access for the tty devices, but only write access is
>> unveiled. Because it cannot access any devices nothing is printed.
>> 
>> This patch adds read access for /dev. Don't know if it makes sense to
>> only unveil read access for non-root users.
>
> Apparently it stat()'s the devices [thereby desiring "r"], before calling
> open O_WRONLY [which only needs "w"].
>
> It is a TOCTOU.  Here are two proposals.
>
> This one lets non-root write to any fd it can manage to open.
>
> Index: ttymsg.c
> ===
> RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
> retrieving revision 1.17
> diff -u -p -u -r1.17 ttymsg.c
> --- ttymsg.c  5 Nov 2015 22:20:11 -   1.17
> +++ ttymsg.c  15 May 2019 22:39:44 -
> @@ -87,13 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
>   return (errbuf);
>   }
>  
> - if (getuid()) {
> - if (stat(device, ) < 0)
> - return (NULL);
> - if ((st.st_mode & S_IWGRP) == 0)
> - return (NULL);
> - }
> -
>   /*
>* open will fail on slip lines or exclusive-use lines
>* if not running as root; not an error.
>
> This one is a bit more cautious, it checks if specifically g+w
> is allowed on the tty, that is more true to the original behaviour
> isn't it?
>
> Index: ttymsg.c
> ===
> RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
> retrieving revision 1.17
> diff -u -p -u -r1.17 ttymsg.c
> --- ttymsg.c  5 Nov 2015 22:20:11 -   1.17
> +++ ttymsg.c  15 May 2019 22:42:58 -
> @@ -87,12 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
>   return (errbuf);
>   }
>  
> - if (getuid()) {
> - if (stat(device, ) < 0)
> - return (NULL);
> - if ((st.st_mode & S_IWGRP) == 0)
> - return (NULL);
> - }
>  
>   /*
>* open will fail on slip lines or exclusive-use lines
> @@ -104,6 +98,17 @@ ttymsg(iov, iovcnt, line, tmout)
>   (void) snprintf(errbuf, sizeof(errbuf),
>   "%s: %s", device, strerror(errno));
>   return (errbuf);
> + }
> +
> + if (getuid()) {
> + if (fstat(fd, ) < 0) {
> + close(fd);
> + return (NULL);
> + }
> + if ((st.st_mode & S_IWGRP) == 0) {
> + close(fd);
> + return (NULL);
> + }
>   }
>  
>   for (cnt = left = 0; cnt < iovcnt; ++cnt)

While looking at the wall(1) code I also thought about the first diff,
but the comments above ttymesg() said something about it being used by
talkd(8). Apparently I misunderstood or the comment is outdated, but I
didn't look into it.

I don't know about the practical implications of the second diff. A user
can not read his own messages, because for example the tty is not group
writable (but writable by the user)?

As you said the second one is more conservative and keeps to the old
behaviour. I personally don't see anything wrong with the first diff,
but I'm not an expert. 


Best regards

Anton



Re: wall(1) unveil for non-root users

2019-05-15 Thread Theo de Raadt
Anton Borowka  wrote:

> wall(1) does not work correctly for non-root users at the moment because
> ttymsg() needs read access for the tty devices, but only write access is
> unveiled. Because it cannot access any devices nothing is printed.
> 
> This patch adds read access for /dev. Don't know if it makes sense to
> only unveil read access for non-root users.

Apparently it stat()'s the devices [thereby desiring "r"], before calling
open O_WRONLY [which only needs "w"].

It is a TOCTOU.  Here are two proposals.

This one lets non-root write to any fd it can manage to open.

Index: ttymsg.c
===
RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
retrieving revision 1.17
diff -u -p -u -r1.17 ttymsg.c
--- ttymsg.c5 Nov 2015 22:20:11 -   1.17
+++ ttymsg.c15 May 2019 22:39:44 -
@@ -87,13 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
return (errbuf);
}
 
-   if (getuid()) {
-   if (stat(device, ) < 0)
-   return (NULL);
-   if ((st.st_mode & S_IWGRP) == 0)
-   return (NULL);
-   }
-
/*
 * open will fail on slip lines or exclusive-use lines
 * if not running as root; not an error.

This one is a bit more cautious, it checks if specifically g+w
is allowed on the tty, that is more true to the original behaviour
isn't it?

Index: ttymsg.c
===
RCS file: /cvs/src/usr.bin/wall/ttymsg.c,v
retrieving revision 1.17
diff -u -p -u -r1.17 ttymsg.c
--- ttymsg.c5 Nov 2015 22:20:11 -   1.17
+++ ttymsg.c15 May 2019 22:42:58 -
@@ -87,12 +87,6 @@ ttymsg(iov, iovcnt, line, tmout)
return (errbuf);
}
 
-   if (getuid()) {
-   if (stat(device, ) < 0)
-   return (NULL);
-   if ((st.st_mode & S_IWGRP) == 0)
-   return (NULL);
-   }
 
/*
 * open will fail on slip lines or exclusive-use lines
@@ -104,6 +98,17 @@ ttymsg(iov, iovcnt, line, tmout)
(void) snprintf(errbuf, sizeof(errbuf),
"%s: %s", device, strerror(errno));
return (errbuf);
+   }
+
+   if (getuid()) {
+   if (fstat(fd, ) < 0) {
+   close(fd);
+   return (NULL);
+   }
+   if ((st.st_mode & S_IWGRP) == 0) {
+   close(fd);
+   return (NULL);
+   }
}
 
for (cnt = left = 0; cnt < iovcnt; ++cnt)



wall(1) unveil for non-root users

2019-05-15 Thread Anton Borowka
wall(1) does not work correctly for non-root users at the moment because
ttymsg() needs read access for the tty devices, but only write access is
unveiled. Because it cannot access any devices nothing is printed.

This patch adds read access for /dev. Don't know if it makes sense to
only unveil read access for non-root users.

Index: usr.bin/wall/wall.c
===
RCS file: /cvs/src/usr.bin/wall/wall.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 wall.c
--- usr.bin/wall/wall.c 28 Jan 2019 20:17:51 -  1.34
+++ usr.bin/wall/wall.c 15 May 2019 17:06:31 -
@@ -117,7 +117,7 @@ main(int argc, char **argv)
 
if (unveil(_PATH_UTMP, "r") == -1)
err(1, "unveil");
-   if (unveil(_PATH_DEV, "w") == -1)
+   if (unveil(_PATH_DEV, "rw") == -1)
err(1, "unveil");
if (unveil(_PATH_DEVDB, "r") == -1)
err(1, "unveil");