|
|
f48767 |
diff --git a/src/ttyname.c b/src/ttyname.c
|
|
|
0e1944 |
index ff2cacc..013be95 100644
|
|
|
f48767 |
--- a/src/ttyname.c
|
|
|
f48767 |
+++ b/src/ttyname.c
|
|
|
0e1944 |
@@ -477,26 +477,38 @@ done:
|
|
|
f48767 |
char *
|
|
|
0e1944 |
get_process_ttyname(char *name, size_t namelen)
|
|
|
f48767 |
{
|
|
|
0e1944 |
- char path[PATH_MAX], *line = NULL;
|
|
|
f48767 |
+ const char path[] = "/proc/self/stat";
|
|
|
f48767 |
+ char *cp, buf[1024];
|
|
|
0e1944 |
char *ret = NULL;
|
|
|
0e1944 |
- size_t linesize = 0;
|
|
|
0e1944 |
int serrno = errno;
|
|
|
0e1944 |
- ssize_t len;
|
|
|
0e1944 |
- FILE *fp;
|
|
|
f48767 |
+ ssize_t nread;
|
|
|
f48767 |
+ int fd;
|
|
|
f48767 |
debug_decl(get_process_ttyname, SUDO_DEBUG_UTIL)
|
|
|
f48767 |
|
|
|
f48767 |
- /* Try to determine the tty from tty_nr in /proc/pid/stat. */
|
|
|
0e1944 |
- snprintf(path, sizeof(path), "/proc/%u/stat", (unsigned int)getpid());
|
|
|
0e1944 |
- if ((fp = fopen(path, "r")) != NULL) {
|
|
|
f48767 |
- len = getline(&line, &linesize, fp);
|
|
|
f48767 |
- fclose(fp);
|
|
|
f48767 |
- if (len != -1) {
|
|
|
f48767 |
+ /*
|
|
|
f48767 |
+ * Try to determine the tty from tty_nr in /proc/self/stat.
|
|
|
f48767 |
+ * Ignore /proc/self/stat if it contains embedded NUL bytes.
|
|
|
f48767 |
+ */
|
|
|
f48767 |
+ if ((fd = open(path, O_RDONLY | O_NOFOLLOW)) != -1) {
|
|
|
f48767 |
+ cp = buf;
|
|
|
f48767 |
+ while ((nread = read(fd, cp, buf + sizeof(buf) - cp)) != 0) {
|
|
|
f48767 |
+ if (nread == -1) {
|
|
|
f48767 |
+ if (errno == EAGAIN || errno == EINTR)
|
|
|
f48767 |
+ continue;
|
|
|
f48767 |
+ break;
|
|
|
f48767 |
+ }
|
|
|
f48767 |
+ cp += nread;
|
|
|
f48767 |
+ if (cp >= buf + sizeof(buf))
|
|
|
f48767 |
+ break;
|
|
|
f48767 |
+ }
|
|
|
f48767 |
+ if (nread == 0 && memchr(buf, '\0', cp - buf) == NULL) {
|
|
|
f48767 |
/*
|
|
|
f48767 |
* Field 7 is the tty dev (0 if no tty).
|
|
|
f48767 |
- * Since the process name at field 2 "(comm)" may include spaces,
|
|
|
f48767 |
- * start at the last ')' found.
|
|
|
f48767 |
+ * Since the process name at field 2 "(comm)" may include
|
|
|
f48767 |
+ * whitespace (including newlines), start at the last ')' found.
|
|
|
f48767 |
*/
|
|
|
f48767 |
- char *cp = strrchr(line, ')');
|
|
|
f48767 |
+ *cp = '\0';
|
|
|
f48767 |
+ cp = strrchr(buf, ')');
|
|
|
0e1944 |
if (cp != NULL) {
|
|
|
0e1944 |
char *ep = cp;
|
|
|
0e1944 |
const char *errstr;
|
|
|
0e1944 |
@@ -527,7 +539,8 @@ get_process_ttyname(char *name, size_t namelen)
|
|
|
0e1944 |
errno = ENOENT;
|
|
|
f48767 |
|
|
|
0e1944 |
done:
|
|
|
0e1944 |
- free(line);
|
|
|
f48767 |
+ if (fd != -1)
|
|
|
f48767 |
+ close(fd);
|
|
|
0e1944 |
if (ret == NULL)
|
|
|
0e1944 |
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
|
|
0e1944 |
"unable to resolve tty via %s", path);
|