Tcl Source Code

View Ticket
Login
Ticket UUID: 0ac9d06895f000b3c83fcb6b14940acc79f11122
Title: Don't call getsockname(2) in Tcl_MakeFileChannel(3) unless absolutely necessary
Type: RFE Version: 8.6.*
Submitter: stu Created on: 2018-06-07 06:25:47
Subsystem: 25. Channel System Assigned To: nobody
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2018-06-13 16:20:03
Resolution: Accepted Closed By: stu
    Closed on: 2018-06-13 16:20:03
Description:

Tcl_MakeFileChannel(3) checks if the given fd is a tty or a socket before assuming it's a file.
If there are pledge(2)es in effect that are restricting the usage of network functions then Tcl_MakeFileChannel will segfault when it tries to use getsockname(2) to check if the fd is a socket.
An important time when this happens is when tclsh is fed a script on stdin: tclsh will immediately segfault.
By using fstat(2) to first check if the fd is a socket, a call to getsockname might be avoided.
This may have security implications.

Attached is a patch against 8.6.8.
The patch has the nice side effect of putting all the socket bits in one place.

Here is a test program:

#include <unistd.h>
#define TCLSH "/usr/local/bin/tclsh"
int main (int argc, char *argv[]) {
        char *a[] = { TCLSH, NULL };
        char *e[] = { NULL };

#ifdef DNS
        pledge(NULL, "stdio rpath getpw dns");
#else
# ifdef INET
        pledge(NULL, "stdio rpath getpw inet");
# else
        pledge(NULL, "stdio rpath getpw");
# endif
#endif

        execve(TCLSH, a, e);
        return 0;
}
Build with no -D's:
$ cc -o tpl tpl.c
$ echo 'puts moo' | ./tpl
Abort trap (core dumped) 
Build with either -DINET or -DDNS:
$ cc -o tpl tpl.c -DINET
$ echo 'puts moo' | ./tpl
moo

User Comments: stu added on 2018-06-13 16:20:03:

[a23a536a48e68141]


stu added on 2018-06-13 16:18:24:
Closed by [a23a536a48].

Attachments: