Source-Changes-HG archive

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

[src/netbsd-9]: src/lib/libc/resolv Pull up following revision(s) (requested ...



details:   https://anonhg.NetBSD.org/src/rev/b11c4293f408
branches:  netbsd-9
changeset: 1002387:b11c4293f408
user:      martin <martin%NetBSD.org@localhost>
date:      Tue Oct 05 11:06:58 2021 +0000

description:
Pull up following revision(s) (requested by christos in ticket #1356):

        lib/libc/resolv/res_init.c: revision 1.32
        lib/libc/resolv/res_private.h: revision 1.4

kqueue(2) file descriptors are not inherited across fork(2). A
process that that calls getaddrinfo(3) will end up cacheing the
kqueue(2) file descriptor in its res_state structure. If that
process fork(2)s and calls getaddrinfo(3) again might end up closing
that cached file descriptor which can end up pointing to a different
file object than the kqueue(2) original one. To fix this, associate
the kqueue(2) file descriptor with the process id that created it,
and don't close(2) it if it is being closed from a different process.

An alternative fix would be to attach the resolver to a fork(2) hook
to cleanup the res_state, but handling it internally in the resolver
is less intrusive. This was discovered by Dima Veselov when using
the FreeRADIUS package.

diffstat:

 lib/libc/resolv/res_init.c    |  42 ++++++++++++++++++++++++++++--------------
 lib/libc/resolv/res_private.h |   3 ++-
 2 files changed, 30 insertions(+), 15 deletions(-)

diffs (109 lines):

diff -r 093d6471dade -r b11c4293f408 lib/libc/resolv/res_init.c
--- a/lib/libc/resolv/res_init.c        Tue Oct 05 11:02:18 2021 +0000
+++ b/lib/libc/resolv/res_init.c        Tue Oct 05 11:06:58 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: res_init.c,v 1.31 2017/04/19 22:21:07 christos Exp $   */
+/*     $NetBSD: res_init.c,v 1.31.14.1 2021/10/05 11:06:58 martin Exp $        */
 
 /*
  * Copyright (c) 1985, 1989, 1993
@@ -72,7 +72,7 @@
 static const char sccsid[] = "@(#)res_init.c   8.1 (Berkeley) 6/7/93";
 static const char rcsid[] = "Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp";
 #else
-__RCSID("$NetBSD: res_init.c,v 1.31 2017/04/19 22:21:07 christos Exp $");
+__RCSID("$NetBSD: res_init.c,v 1.31.14.1 2021/10/05 11:06:58 martin Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -190,6 +190,21 @@
        return (__res_vinit(statp, 0));
 }
 
+static int
+__res_kqinit(res_state statp)
+{
+       struct kevent kc;
+       struct __res_state_ext *ext = statp->_u._ext.ext;
+
+       ext->kq = kqueue1(O_CLOEXEC);
+       ext->kqpid = getpid();
+       EV_SET(&kc, ext->resfd, EVFILT_VNODE,
+           EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_DELETE|NOTE_WRITE| NOTE_EXTEND|
+           NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0);
+       (void)kevent(ext->kq, &kc, 1, NULL, 0, &ts);
+       return ext->kq;
+}
+
 /*% This function has to be reachable by res_data.c but not publically. */
 int
 __res_vinit(res_state statp, int preinit) {
@@ -346,7 +361,6 @@
        nserv = 0;
        if ((fp = fopen(__res_conf_name, "re")) != NULL) {
            struct stat st;
-           struct kevent kc;
 
            /* read the config file */
            while (fgets(buf, (int)sizeof(buf), fp) != NULL) {
@@ -500,11 +514,7 @@
            if (fstat(statp->_u._ext.ext->resfd, &st) != -1)
                    __res_conf_time = statp->_u._ext.ext->res_conf_time =
                        st.st_mtimespec;
-           statp->_u._ext.ext->kq = kqueue1(O_CLOEXEC);
-           EV_SET(&kc, statp->_u._ext.ext->resfd, EVFILT_VNODE,
-               EV_ADD|EV_ENABLE|EV_CLEAR, NOTE_DELETE|NOTE_WRITE| NOTE_EXTEND|
-               NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE, 0, 0);
-           (void)kevent(statp->_u._ext.ext->kq, &kc, 1, NULL, 0, &ts);
+           __res_kqinit(statp);
        } else {
            statp->_u._ext.ext->kq = -1;
            statp->_u._ext.ext->resfd = -1;
@@ -573,6 +583,9 @@
                struct kevent ke;
                if (statp->_u._ext.ext->kq == -1)
                        goto out;
+               if (statp->_u._ext.ext->kqpid != getpid() &&
+                   __res_kqinit(statp) == -1)
+                       goto out;
 
                switch (kevent(statp->_u._ext.ext->kq, NULL, 0, &ke, 1, &ts)) {
                case 0:
@@ -812,13 +825,14 @@
 void
 res_ndestroy(res_state statp)
 {
+       struct __res_state_ext *ext = statp->_u._ext.ext;
        res_nclose(statp);
-       if (statp->_u._ext.ext != NULL) {
-               if (statp->_u._ext.ext->kq != -1)
-                       (void)close(statp->_u._ext.ext->kq);
-               if (statp->_u._ext.ext->resfd != -1)
-                       (void)close(statp->_u._ext.ext->resfd);
-               free(statp->_u._ext.ext);
+       if (ext != NULL) {
+               if (ext->kq != -1 && ext->kqpid == getpid())
+                       (void)close(ext->kq);
+               if (ext->resfd != -1)
+                       (void)close(ext->resfd);
+               free(ext);
                statp->_u._ext.ext = NULL;
        }
        if (statp->_rnd != NULL) {
diff -r 093d6471dade -r b11c4293f408 lib/libc/resolv/res_private.h
--- a/lib/libc/resolv/res_private.h     Tue Oct 05 11:02:18 2021 +0000
+++ b/lib/libc/resolv/res_private.h     Tue Oct 05 11:06:58 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: res_private.h,v 1.3 2009/10/24 17:24:01 christos Exp $ */
+/*     $NetBSD: res_private.h,v 1.3.48.1 2021/10/05 11:06:58 martin Exp $      */
 
 #ifndef res_private_h
 #define res_private_h
@@ -16,6 +16,7 @@
        char nsuffix2[64];
        struct timespec res_conf_time;
        int kq, resfd;
+       pid_t kqpid;
 };
 
 extern int res_ourserver_p(const res_state, const struct sockaddr *);



Home | Main Index | Thread Index | Old Index