mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
rtld: Account static TLS surplus for audit modules
The new static TLS surplus size computation is surplus_tls = 192 * (nns-1) + 144 * nns + 512 where nns is controlled via the rtld.nns tunable. This commit accounts audit modules too so nns = rtld.nns + audit modules. rtld.nns should only include the namespaces required by the application, namespaces for audit modules are accounted on top of that so audit modules don't use up the static TLS that is reserved for the application. This allows loading many audit modules without tuning rtld.nns or using up static TLS, and it fixes FAIL: elf/tst-auditmany Note that DL_NNS is currently a hard upper limit for nns, and if rtld.nns + audit modules go over the limit that's a fatal error. By default rtld.nns is 4 which allows 12 audit modules. Counting the audit modules is based on existing audit string parsing code, we cannot use GLRO(dl_naudit) before the modules are actually loaded.
This commit is contained in:
parent
0c7b002fac
commit
17796419b5
@ -126,8 +126,8 @@ __libc_setup_tls (void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the size of the static TLS surplus. */
|
/* Calculate the size of the static TLS surplus, with 0 auditors. */
|
||||||
_dl_tls_static_surplus_init ();
|
_dl_tls_static_surplus_init (0);
|
||||||
|
|
||||||
/* We have to set up the TCB block which also (possibly) contains
|
/* We have to set up the TCB block which also (possibly) contains
|
||||||
'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
|
'errno'. Therefore we avoid 'malloc' which might touch 'errno'.
|
||||||
|
15
elf/dl-tls.c
15
elf/dl-tls.c
@ -49,7 +49,10 @@
|
|||||||
that affects the size of the static TLS and by default it's small enough
|
that affects the size of the static TLS and by default it's small enough
|
||||||
not to cause problems with existing applications. The limit is not
|
not to cause problems with existing applications. The limit is not
|
||||||
enforced or checked: it is the user's responsibility to increase rtld.nns
|
enforced or checked: it is the user's responsibility to increase rtld.nns
|
||||||
if more dlmopen namespaces are used. */
|
if more dlmopen namespaces are used.
|
||||||
|
|
||||||
|
Audit modules use their own namespaces, they are not included in rtld.nns,
|
||||||
|
but come on top when computing the number of namespaces. */
|
||||||
|
|
||||||
/* Size of initial-exec TLS in libc.so. */
|
/* Size of initial-exec TLS in libc.so. */
|
||||||
#define LIBC_IE_TLS 192
|
#define LIBC_IE_TLS 192
|
||||||
@ -60,8 +63,11 @@
|
|||||||
/* Size of additional surplus TLS, placeholder for TLS optimizations. */
|
/* Size of additional surplus TLS, placeholder for TLS optimizations. */
|
||||||
#define OPT_SURPLUS_TLS 512
|
#define OPT_SURPLUS_TLS 512
|
||||||
|
|
||||||
|
/* Calculate the size of the static TLS surplus, when the given
|
||||||
|
number of audit modules are loaded. Must be called after the
|
||||||
|
number of audit modules is known and before static TLS allocation. */
|
||||||
void
|
void
|
||||||
_dl_tls_static_surplus_init (void)
|
_dl_tls_static_surplus_init (size_t naudit)
|
||||||
{
|
{
|
||||||
size_t nns;
|
size_t nns;
|
||||||
|
|
||||||
@ -73,6 +79,11 @@ _dl_tls_static_surplus_init (void)
|
|||||||
#endif
|
#endif
|
||||||
if (nns > DL_NNS)
|
if (nns > DL_NNS)
|
||||||
nns = DL_NNS;
|
nns = DL_NNS;
|
||||||
|
if (DL_NNS - nns < naudit)
|
||||||
|
_dl_fatal_printf ("Failed loading %lu audit modules, %lu are supported.\n",
|
||||||
|
(unsigned long) naudit, (unsigned long) (DL_NNS - nns));
|
||||||
|
nns += naudit;
|
||||||
|
|
||||||
GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS
|
GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS
|
||||||
+ nns * OTHER_IE_TLS
|
+ nns * OTHER_IE_TLS
|
||||||
+ OPT_SURPLUS_TLS);
|
+ OPT_SURPLUS_TLS);
|
||||||
|
31
elf/rtld.c
31
elf/rtld.c
@ -299,6 +299,23 @@ audit_list_next (struct audit_list *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Count audit modules before they are loaded so GLRO(dl_naudit)
|
||||||
|
is not yet usable. */
|
||||||
|
static size_t
|
||||||
|
audit_list_count (struct audit_list *list)
|
||||||
|
{
|
||||||
|
/* Restore the audit_list iterator state at the end. */
|
||||||
|
const char *saved_tail = list->current_tail;
|
||||||
|
size_t naudit = 0;
|
||||||
|
|
||||||
|
assert (list->current_index == 0);
|
||||||
|
while (audit_list_next (list) != NULL)
|
||||||
|
naudit++;
|
||||||
|
list->current_tail = saved_tail;
|
||||||
|
list->current_index = 0;
|
||||||
|
return naudit;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef HAVE_INLINED_SYSCALLS
|
#ifndef HAVE_INLINED_SYSCALLS
|
||||||
/* Set nonzero during loading and initialization of executable and
|
/* Set nonzero during loading and initialization of executable and
|
||||||
libraries, cleared before the executable's entry point runs. This
|
libraries, cleared before the executable's entry point runs. This
|
||||||
@ -738,7 +755,7 @@ match_version (const char *string, struct link_map *map)
|
|||||||
static bool tls_init_tp_called;
|
static bool tls_init_tp_called;
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
init_tls (void)
|
init_tls (size_t naudit)
|
||||||
{
|
{
|
||||||
/* Number of elements in the static TLS block. */
|
/* Number of elements in the static TLS block. */
|
||||||
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
|
GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
|
||||||
@ -781,7 +798,7 @@ init_tls (void)
|
|||||||
assert (i == GL(dl_tls_max_dtv_idx));
|
assert (i == GL(dl_tls_max_dtv_idx));
|
||||||
|
|
||||||
/* Calculate the size of the static TLS surplus. */
|
/* Calculate the size of the static TLS surplus. */
|
||||||
_dl_tls_static_surplus_init ();
|
_dl_tls_static_surplus_init (naudit);
|
||||||
|
|
||||||
/* Compute the TLS offsets for the various blocks. */
|
/* Compute the TLS offsets for the various blocks. */
|
||||||
_dl_determine_tlsoffset ();
|
_dl_determine_tlsoffset ();
|
||||||
@ -1674,9 +1691,11 @@ of this helper program; chances are you did not intend to run this program.\n\
|
|||||||
bool need_security_init = true;
|
bool need_security_init = true;
|
||||||
if (audit_list.length > 0)
|
if (audit_list.length > 0)
|
||||||
{
|
{
|
||||||
|
size_t naudit = audit_list_count (&audit_list);
|
||||||
|
|
||||||
/* Since we start using the auditing DSOs right away we need to
|
/* Since we start using the auditing DSOs right away we need to
|
||||||
initialize the data structures now. */
|
initialize the data structures now. */
|
||||||
tcbp = init_tls ();
|
tcbp = init_tls (naudit);
|
||||||
|
|
||||||
/* Initialize security features. We need to do it this early
|
/* Initialize security features. We need to do it this early
|
||||||
since otherwise the constructors of the audit libraries will
|
since otherwise the constructors of the audit libraries will
|
||||||
@ -1686,6 +1705,10 @@ of this helper program; chances are you did not intend to run this program.\n\
|
|||||||
need_security_init = false;
|
need_security_init = false;
|
||||||
|
|
||||||
load_audit_modules (main_map, &audit_list);
|
load_audit_modules (main_map, &audit_list);
|
||||||
|
|
||||||
|
/* The count based on audit strings may overestimate the number
|
||||||
|
of audit modules that got loaded, but not underestimate. */
|
||||||
|
assert (GLRO(dl_naudit) <= naudit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keep track of the currently loaded modules to count how many
|
/* Keep track of the currently loaded modules to count how many
|
||||||
@ -1929,7 +1952,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|
|||||||
multiple threads (from a non-TLS-using libpthread). */
|
multiple threads (from a non-TLS-using libpthread). */
|
||||||
bool was_tls_init_tp_called = tls_init_tp_called;
|
bool was_tls_init_tp_called = tls_init_tp_called;
|
||||||
if (tcbp == NULL)
|
if (tcbp == NULL)
|
||||||
tcbp = init_tls ();
|
tcbp = init_tls (0);
|
||||||
|
|
||||||
if (__glibc_likely (need_security_init))
|
if (__glibc_likely (need_security_init))
|
||||||
/* Initialize security features. But only if we have not done it
|
/* Initialize security features. But only if we have not done it
|
||||||
|
@ -242,9 +242,12 @@ Sets the number of supported dynamic link namespaces (see @code{dlmopen}).
|
|||||||
Currently this limit can be set between 1 and 16 inclusive, the default is 4.
|
Currently this limit can be set between 1 and 16 inclusive, the default is 4.
|
||||||
Each link namespace consumes some memory in all thread, and thus raising the
|
Each link namespace consumes some memory in all thread, and thus raising the
|
||||||
limit will increase the amount of memory each thread uses. Raising the limit
|
limit will increase the amount of memory each thread uses. Raising the limit
|
||||||
is useful when your application uses more than 4 dynamic linker audit modules
|
is useful when your application uses more than 4 dynamic link namespaces as
|
||||||
e.g. @env{LD_AUDIT}, or will use more than 4 dynamic link namespaces as created
|
created by @code{dlmopen} with an lmid argument of @code{LM_ID_NEWLM}.
|
||||||
by @code{dlmopen} with an lmid argument of @code{LM_ID_NEWLM}.
|
Dynamic linker audit modules are loaded in their own dynamic link namespaces,
|
||||||
|
but they are not accounted for in @code{glibc.rtld.nns}. They implicitly
|
||||||
|
increase the per-thread memory usage as necessary, so this tunable does
|
||||||
|
not need to be changed to allow many audit modules e.g. via @env{LD_AUDIT}.
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
@node Elision Tunables
|
@node Elision Tunables
|
||||||
|
@ -1106,8 +1106,9 @@ extern size_t _dl_count_modids (void) attribute_hidden;
|
|||||||
/* Calculate offset of the TLS blocks in the static TLS block. */
|
/* Calculate offset of the TLS blocks in the static TLS block. */
|
||||||
extern void _dl_determine_tlsoffset (void) attribute_hidden;
|
extern void _dl_determine_tlsoffset (void) attribute_hidden;
|
||||||
|
|
||||||
/* Calculate the size of the static TLS surplus. */
|
/* Calculate the size of the static TLS surplus, when the given
|
||||||
void _dl_tls_static_surplus_init (void) attribute_hidden;
|
number of audit modules are loaded. */
|
||||||
|
void _dl_tls_static_surplus_init (size_t naudit) attribute_hidden;
|
||||||
|
|
||||||
#ifndef SHARED
|
#ifndef SHARED
|
||||||
/* Set up the TCB for statically linked applications. This is called
|
/* Set up the TCB for statically linked applications. This is called
|
||||||
|
Loading…
Reference in New Issue
Block a user