Provide GLIBC_PRIVATE symbols no longer used by the current library version to increase backwards compatibility during glibc updates. This will help to avoid some of the issues that surface while a glibc update is performed with concurrent application updates, and it also allows old nscd to trigger cache invalidation in a running nscd daemon. While at this, also add interfaces for supporting old nss_dns modules. This patch is not needed upstream because upstream does not provide backwards compatibility for GLIBC_PRIVATE symbols. diff --git a/inet/herrno.c b/inet/herrno.c index 0cd84445190728b3..4d26e9b254181422 100644 --- a/inet/herrno.c +++ b/inet/herrno.c @@ -28,3 +28,9 @@ __thread int __h_errno; extern __thread int __libc_h_errno __attribute__ ((alias ("__h_errno"))) attribute_hidden; #define h_errno __libc_h_errno + +#ifdef SHARED +/* Provide an alias for use by the old libpthread.so.0 during + updates. */ +asm (".symver __h_errno, h_errno@GLIBC_PRIVATE"); +#endif diff --git a/resolv/res_libc.c b/resolv/res_libc.c index 9f2d3c3bd442bb38..5ab02c79c72eb1ac 100644 --- a/resolv/res_libc.c +++ b/resolv/res_libc.c @@ -41,6 +41,7 @@ #include #include #include +#include int res_init (void) @@ -80,7 +81,34 @@ res_init (void) return __res_vinit (&_res, 1); } - + +#ifdef SHARED + +/* An old nscd binary may bind to __res_maybe_init during a glibc + update. Emulate it using the new functions. Ignore PREINIT + because almost all existing __res_maybe_init callers used zero + PREINIT, and the difference for RESP == &_res is very minor (a + potential override of application configuration). */ +attribute_compat_text_section +int +__res_maybe_init (res_state resp, int preinit) +{ + if (resp == &_res) + { + /* This performs an implicit initialization of _res. */ + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + return -1; + __resolv_context_put (ctx); + return 0; + } + else + return __res_vinit (resp, 0); +} +asm (".symver __res_maybe_init, __res_maybe_init@GLIBC_PRIVATE"); + +#endif /* SHARED */ + /* This needs to be after the use of _res in res_init, above. */ #undef _res diff --git a/resolv/res_query.c b/resolv/res_query.c index ebbe5a6a4ed86abe..24fefb561e7f1f5e 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -705,6 +705,96 @@ hostalias (const char *name) (__resolv_context_get (), name, abuf, sizeof (abuf)); } +#ifdef SHARED +/* Compatibiliaty functions to support old nss_dns modules. */ + +typedef int (*compat_query_function) (struct resolv_context *, + const char *name, + int class, int type, + u_char *answer, + int anslen, + u_char **answerp, + u_char **answerp2, + int *nanswerp2, + int *resplen2, + int *answerp2_malloced); + +attribute_compat_text_section +static int +wrap_compat_call (compat_query_function qf, + res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen, /* size of answer buffer */ + u_char **answerp, /* if buffer needs to be enlarged */ + u_char **answerp2, + int *nanswerp2, + int *resplen2, + int *answerp2_malloced) +{ + if (statp == &_res) + { + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + __set_h_errno (NO_RECOVERY); + return -1; + } + int ret = qf (ctx, name, class, type, + answer, anslen, answerp, answerp2, + nanswerp2, resplen2, answerp2_malloced); + __resolv_context_put (ctx); + return ret; + } + else + { + __set_h_errno (NO_RECOVERY); + __set_errno (ENOTSUP); + return -1; + } +} + +attribute_compat_text_section +int +__libc_res_nquery(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen, /* size of answer buffer */ + u_char **answerp, /* if buffer needs to be enlarged */ + u_char **answerp2, + int *nanswerp2, + int *resplen2, + int *answerp2_malloced) +{ + return wrap_compat_call (__res_context_query, statp, name, class, type, + answer, anslen, answerp, answerp2, + nanswerp2, resplen2, answerp2_malloced); +} +asm (".symver __libc_res_nquery, __libc_res_nquery@GLIBC_PRIVATE"); + +attribute_compat_text_section +int +__libc_res_nsearch(res_state statp, + const char *name, /* domain name */ + int class, int type, /* class and type of query */ + u_char *answer, /* buffer to put answer */ + int anslen, /* size of answer */ + u_char **answerp, + u_char **answerp2, + int *nanswerp2, + int *resplen2, + int *answerp2_malloced) +{ + return wrap_compat_call (__res_context_search, statp, name, class, type, + answer, anslen, answerp, answerp2, + nanswerp2, resplen2, answerp2_malloced); +} +asm (".symver __libc_res_nsearch, __libc_res_nsearch@GLIBC_PRIVATE"); + +#endif /* SHARED */ + #if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2) # undef res_query # undef res_querydomain