Skip to content

Commit 88674ba

Browse files
committedMay 31, 2017
A command name may also contain newline characters so read
/proc/self/stat until EOF. It is not legal for /proc/self/stat to contain embedded NUL bytes so treat the file as corrupt if we see any. With help from Qualys. This is not exploitable due to the /dev traversal changes in sudo 1.8.20p1 (thanks Solar!). --HG-- branch : 1.8
1 parent 63a88fd commit 88674ba

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed
 

‎src/ttyname.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -452,25 +452,37 @@ char *
452452
get_process_ttyname(char *name, size_t namelen)
453453
{
454454
const char path[] = "/proc/self/stat";
455-
char *line = NULL;
455+
char *cp, buf[1024];
456456
char *ret = NULL;
457-
size_t linesize = 0;
458457
int serrno = errno;
459-
ssize_t len;
460-
FILE *fp;
458+
ssize_t nread;
459+
int fd;
461460
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
462461

463-
/* Try to determine the tty from tty_nr in /proc/self/stat. */
464-
if ((fp = fopen(path, "r")) != NULL) {
465-
len = getline(&line, &linesize, fp);
466-
fclose(fp);
467-
if (len != -1) {
462+
/*
463+
* Try to determine the tty from tty_nr in /proc/self/stat.
464+
* Ignore /proc/self/stat if it contains embedded NUL bytes.
465+
*/
466+
if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) {
467+
cp = buf;
468+
while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) {
469+
if (nread == -1) {
470+
if (errno == EAGAIN || errno == EINTR)
471+
continue;
472+
break;
473+
}
474+
cp += nread;
475+
if (cp >= buf + sizeof(buf))
476+
break;
477+
}
478+
if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) {
468479
/*
469480
* Field 7 is the tty dev (0 if no tty).
470-
* Since the process name at field 2 "(comm)" may include spaces,
471-
* start at the last ')' found.
481+
* Since the process name at field 2 "(comm)" may include
482+
* whitespace (including newlines), start at the last ')' found.
472483
*/
473-
char *cp = strrchr(line, ')');
484+
*cp = '\0';
485+
cp = strrchr(buf, ')');
474486
if (cp != NULL) {
475487
char *ep = cp;
476488
const char *errstr;
@@ -501,7 +513,8 @@ get_process_ttyname(char *name, size_t namelen)
501513
errno = ENOENT;
502514

503515
done:
504-
free(line);
516+
if (fd != -1)
517+
close(fd);
505518
if (ret == NULL)
506519
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
507520
"unable to resolve tty via %s", path);

0 commit comments

Comments
 (0)
Please sign in to comment.