Subject: bin/28474: usr.bin/write (& wall) can't handle ptyfs system
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <gcw@primenet.com.au>
List: netbsd-bugs
Date: 11/30/2004 04:00:00
>Number: 28474
>Category: bin
>Synopsis: write does some weird checking and can't handle ptyfs
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Nov 30 04:00:00 +0000 2004
>Originator: Geoff C. Wing
>Release: NetBSD 2.99.10 (2004-11-30)
>Organization:
>Environment:
System: NetBSD g.primenet.com.au 2.99.10 NetBSD 2.99.10 (G) #0: Tue Nov 30 14:06:40 EST 2004 gcw@g.primenet.com.au:/usr/netbsd/src/sys/arch/i386/compile/G i386
Architecture: i386
Machine: i386
>Description:
write does a security check to make sure people can't escape the /dev
directory by checking for dot & slash before using the tty string.
However, the tty string is appended to _PATH_DEV (which starts with
a slash) so checking for dot is sufficient to prevent "../" bypassing
and if you need to stop people from using subdirectories in /dev
because they can write or mount there then security's out the window
anyway.
write also strips out all parts of a tty up to the last slash to find
the tty name. Then gives error messages as though it had "/dev/"
prepended. If we think we have "/dev/" there and not "/foo/" then
we should act as if we do. Thus when we see "/dev/pty/2" we parse
it as "pty/2" instead of saying "2" and printing out "/dev/2".
This also affects wall
>How-To-Repeat:
use with ptyfs
>Fix:
--- usr.bin/write/term_chk.c.org 2004-10-28 14:25:02.000000000 +1000
+++ usr.bin/write/term_chk.c 2004-11-30 14:39:29.000000000 +1100
@@ -63,7 +63,7 @@
struct stat s;
int i, fd, serrno;
- if (strcspn(tty, "./") != strlen(tty)) {
+ if (strchr(tty, '.') != NULL) {
errno = EINVAL;
return -1;
}
@@ -111,7 +111,6 @@
int myttyfd;
int msgsok;
char *mytty;
- char *cp;
/* check that sender has write enabled */
if (isatty(fileno(stdin)))
@@ -126,8 +125,8 @@
errx(1, "Cannot find your tty");
if ((mytty = ttyname(myttyfd)) == NULL)
err(1, "Cannot find the name of your tty");
- if ((cp = strrchr(mytty, '/')) != NULL)
- mytty = cp + 1;
+ if (strncmp(mytty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
+ mytty += sizeof(_PATH_DEV) - 1;
if (term_chk(myuid, mytty, &msgsok, atime, 1, saved_egid) == -1)
err(1, "%s%s", _PATH_DEV, mytty);
if (!msgsok) {