|
|
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 <resolv.h> |
|
|
#include <libc-lock.h> |
|
|
#include <resolv-internal.h> |
|
|
+#include <resolv_context.h> |
|
|
|
|
|
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
|
|
|
|