NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: FreeRADIUS instability



On 9/29/21 14:21, Pawel S. Veselov wrote:
As you saw the libc address lookup routines leave the fd open, and if
something as part of a "make sure all fd's > 2 are closed at startup"
type functionality went and closed it, that would cause a problem.
The kqueue fd is used to monitor /etc/resolv.conf for any changes that
would require (or might require) it to be re-read (which is a useful
thing to do for long running daemons) - so it needs to remain open
for the life of the process.
I think my other email provides a reasonable explanation of what
is going on. It seems to me that the sequence of getaddrinfo() -
fork() - getaddrinfo() will always cause issues since kqueue FD is not
inherited after fork(), but the libc address lookup routines keep the
descriptor around.

I've put together a quick test, it behaves a bit different, but shows
the problem all the same. I expected resolv to close the fd in the same
fashion, but it doesn't IMHO because kevent() fails. The situation is
then only fatal when the child opened kqueue, and not any other socket.

ktrace shows:

(parent opens resolv kqueue)
 22888      1 gf       CALL  kqueue1(0x400000)
 22888      1 gf       RET   kqueue1 3
(fork)
 22888      1 gf       CALL  fork
 22888      1 gf       RET   fork 16605/0x40dd
(child opens an FD)
 16605      1 gf       CALL  open(0x400db2,0,0)
 16605      1 gf       NAMI  "/etc/hosts"
 16605      1 gf       RET   open 3
(resolv in child tries to use FD 3)
16605 1 gf CALL __kevent50(3,0,0,0x7f7fff7d5620,1,0x7cb75cd787b0)
 16605      1 gf       RET   __kevent50 -1 errno 9 Bad file descriptor



[root@almaz ~]$ cat gf.c
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>

int main(int argc, char ** argv) {

        struct addrinfo * res;

        getaddrinfo("www.netbsd.org", NULL, NULL, &res);

        pid_t pid = fork();
        if (pid < 0) {
                perror("fork");
                return 1;
        }

        if (!pid) {
                // child
                int fd = open("/etc/hosts", O_RDONLY);
                getaddrinfo("www.netbsd.com", NULL, NULL, &res);
                char buf[101];
                int rc;
                while (1) {
                        rc = read(fd, buf, 100);
                        if (rc < 0) { perror("read"); }
                        if (rc <= 0) { break; }
                        buf[rc] = 0;
                        fprintf(stdout, "%s", buf);
                }
                fprintf(stdout, "\n");
                return !rc ? 0 : 1;
        } else {
                int s;
                while (1) {
                        waitpid(pid, &s, 0);
                        if (!WIFEXITED(s)) {
                                fprintf(stdout, "not ready\n");
                                continue;
                        }
                        return WEXITSTATUS(s);
                        break;
                }
        }

}



Home | Main Index | Thread Index | Old Index