Skip to content

Commit b7efb8a

Browse files
committed
sudo_ttyname_dev: On Linux try to use /proc/self/fd/{0,1,2} if possible.
If one of std{in,out,err} matches the specified device, try to resolve it to a path by using /proc/self/fd/{0,1,2}. This avoids searching all of /dev and works in a chroot where /proc is mounted but /dev/pts is not. GitHub issue #421.
1 parent 7e8f006 commit b7efb8a

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

lib/util/ttyname_dev.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,39 @@ char *
253253
sudo_ttyname_dev_v1(dev_t rdev, char *buf, size_t buflen)
254254
{
255255
const char *devsearch, *devsearch_end;
256-
char path[PATH_MAX], *ret;
256+
char path[PATH_MAX], *ret = NULL;
257257
const char *cp, *ep;
258258
size_t len;
259259
debug_decl(sudo_ttyname_dev, SUDO_DEBUG_UTIL);
260260

261+
#ifdef __linux__
262+
/*
263+
* First check std{in,out,err} and use /proc/self/fd/{0,1,2} if possible.
264+
*/
265+
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd++) {
266+
char fdpath[] = "/proc/self/fd/N";
267+
struct stat sb;
268+
269+
if (fstat(fd, &sb) == -1 || !S_ISCHR(sb.st_mode))
270+
continue;
271+
if (rdev != sb.st_rdev)
272+
continue;
273+
274+
fdpath[sizeof("/proc/self/fd/N") - 2] = '0' + fd;
275+
len = readlink(fdpath, buf, buflen);
276+
if (len != (size_t)-1) {
277+
if (len == buflen) {
278+
errno = ERANGE; /* buf too small */
279+
} else {
280+
/* readlink(2) does not NUL-terminate. */
281+
buf[len] = '\0';
282+
ret = buf;
283+
}
284+
goto done;
285+
}
286+
}
287+
#endif
288+
261289
/*
262290
* First, check /dev/console.
263291
*/

0 commit comments

Comments
 (0)