From 2c2578a0600e14b28846874c3019c830176f3fe6 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Sat, 30 Dec 2023 23:59:43 +0000 Subject: (cherry-pick) Don't call getsockname(2) in Tcl_MakeFileChannel(3) unless absolutely necessary. Closes RFE [0ac9d06895]. Permits better constraining of Tcl/tclsh via OpenBSD's pledge(2) or similar mechanisms. Minor rewrite --- unix/tclUnixChan.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c index fe36972..f83a213 100644 --- a/unix/tclUnixChan.c +++ b/unix/tclUnixChan.c @@ -1531,30 +1531,34 @@ Tcl_MakeFileChannel( char channelName[16 + TCL_INTEGER_SPACE]; int fd = PTR2INT(handle); const Tcl_ChannelType *channelTypePtr; - struct sockaddr sockaddr; - socklen_t sockaddrLen = sizeof(sockaddr); + struct stat buf; if (mode == 0) { return NULL; } - sockaddr.sa_family = AF_UNSPEC; - #ifdef SUPPORTS_TTY if (isatty(fd)) { channelTypePtr = &ttyChannelType; snprintf(channelName, sizeof(channelName), "serial%d", fd); + goto final; } else #endif /* SUPPORTS_TTY */ - if ((getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0) - && (sockaddrLen > 0) - && (sockaddr.sa_family == AF_INET || sockaddr.sa_family == AF_INET6)) { - return TclpMakeTcpClientChannelMode(INT2PTR(fd), mode); - } else { - channelTypePtr = &fileChannelType; - snprintf(channelName, sizeof(channelName), "file%d", fd); + if (fstat(fd, &buf) == 0 && S_ISSOCK(buf.st_mode)) { + struct sockaddr sockaddr; + socklen_t sockaddrLen = sizeof(sockaddr); + + sockaddr.sa_family = AF_UNSPEC; + if ((getsockname(fd, (struct sockaddr *)&sockaddr, &sockaddrLen) == 0) + && (sockaddrLen > 0) + && (sockaddr.sa_family == AF_INET + || sockaddr.sa_family == AF_INET6)) { + return (Tcl_Channel)TclpMakeTcpClientChannelMode(INT2PTR(fd), mode); + } } - + channelTypePtr = &fileChannelType; + snprintf(channelName, sizeof(channelName), "file%d", fd); +final: fsPtr = (FileState *)ckalloc(sizeof(FileState)); fsPtr->fd = fd; fsPtr->validMask = mode | TCL_EXCEPTION; -- cgit v0.12