public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* RFC: system-wide default tunables
@ 2023-10-04 20:55 DJ Delorie
  2023-10-06 14:44 ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-04 20:55 UTC (permalink / raw)
  To: libc-alpha


Before I start on actual coding, I'm sharing my thoughts on this
project to gain consensus...

Problem: tunables are set by an environment variable, and may be
limited by security settings, containerization, etc.  Plus users may
not assume that the env var is pre-set, and just overwrite it.

Solution: Add a way to specify system-wide defaults for tunables.

Ideas:

* Specify some file or files in /etc that contain tunables settings.
  Follow the ld.so.conf patterns, allow subdirectories, etc.

* Store tunables info in /etc/ld.so.cache in a new slot at the end,
  with a new enum for the chunk.  This way older glibc will just
  ignore it.  Parsing and storing will be done via ldconfig.

* Values in ld.so.cache will be parsed but not range checked; that's
  dependent on what the glibc app expects.

* read those, do range checking, and call callbacks at runtime

* To speed processing, encode a hash for each tunable name, both in
  glibc's table (which is built at glibc build time) and in
  /etc/ld.so.cache.  Comparing the hash typically fails but avoids a
  string compare.  Matching hashes are followed by a string compare to
  verify.  The hash need not be crypographically secure.

* I'm not going to try to add some "syntax" to specify if a tunable is
  overridable or not; this is a simple default-only change.

* Tunables set by these defaults will not be disabled for setuid
  programs; it's assumed they're a "trusted source".


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-04 20:55 RFC: system-wide default tunables DJ Delorie
@ 2023-10-06 14:44 ` Adhemerval Zanella Netto
  2023-10-06 17:12   ` Adhemerval Zanella Netto
  2023-10-06 18:29   ` DJ Delorie
  0 siblings, 2 replies; 20+ messages in thread
From: Adhemerval Zanella Netto @ 2023-10-06 14:44 UTC (permalink / raw)
  To: DJ Delorie, libc-alpha



On 04/10/23 17:55, DJ Delorie wrote:
> 
> Before I start on actual coding, I'm sharing my thoughts on this
> project to gain consensus...
> 
> Problem: tunables are set by an environment variable, and may be
> limited by security settings, containerization, etc.  Plus users may
> not assume that the env var is pre-set, and just overwrite it.
> 
> Solution: Add a way to specify system-wide defaults for tunables.
> 

The idea sounds ok, but adding on ld.so.cache means it would not work 
for static.  I don't think this is really an issue, static PIE is really
tricky because self-relocation happens after tunable (because tunables 
itself might change ifunc selection); and trying to add support for 
static PIE would require a lot of messy refactoring (all ld.so.cache 
loading would need to be annotated hidden, no external function calling,
even mem* ones; etc.).

> Ideas:
> 
> * Specify some file or files in /etc that contain tunables settings.
>   Follow the ld.so.conf patterns, allow subdirectories, etc.
> 
> * Store tunables info in /etc/ld.so.cache in a new slot at the end,
>   with a new enum for the chunk.  This way older glibc will just
>   ignore it.  Parsing and storing will be done via ldconfig.

It means that we will have to always load the ld.so.cache, not only when
we will actually have to load an ET_DYN .  It should be ok, but runtimes
that usually only link against libc.so (like rust) will have additional
overhead on startup.

We also have DF_1_NODEFLIB to inhibit loader cache search, should we add
another flag to inhibit the global tunables?  It does not make sense to
set per-library, but it still might be useful to set on ET_EXEC.

So I am not fully sure adding the global tunable setting on ld.so.cache is
the correct approach.  However, adding on an external file will add
another open/mmap/close on each program; plus the extra mmap.

> 
> * Values in ld.so.cache will be parsed but not range checked; that's
>   dependent on what the glibc app expects.

Importing the range information on tunable definition is straightforward, 
so I think we should add the range check on ldconfig ld.so.cache setup.
There is no error checking on env var tunable, invalid values are just
ignored without any user feedback.  Since we will do pre-processing,
I think it would be valuable to at least show any possible invalid range,
specially because this is a administration setting.

> 
> * read those, do range checking, and call callbacks at runtime
> 
> * To speed processing, encode a hash for each tunable name, both in
>   glibc's table (which is built at glibc build time) and in
>   /etc/ld.so.cache.  Comparing the hash typically fails but avoids a
>   string compare.  Matching hashes are followed by a string compare to
>   verify.  The hash need not be crypographically secure.

Do we really need this optimization?  Internally, the tunables are already
accessed through a enum, which is essentially a index on tunable_list.
Why can you we use the same enums value on the cache definition keys? 

The string mapping could be accomplished by adding a string list, with
the tunable value being the offset.

> 
> * I'm not going to try to add some "syntax" to specify if a tunable is
>   overridable or not; this is a simple default-only change.

How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
tunable?  Should we ignore the envvar or merge the results? Which one takes 
precedence (I take the system-wide)? Should we add a way to override system-wide 
value (similar to DF_1_NODEFLIB) as a runtime options (either another envvar or 
a extra field in GLIBC_TUNABLE)?

> 
> * Tunables set by these defaults will not be disabled for setuid
>   programs; it's assumed they're a "trusted source".

This seems reasonable, and with this rationale should we add an option
to allow some tunable to be disabled or overriden? I take this is an extra
complexity that we should not pursuit. 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 14:44 ` Adhemerval Zanella Netto
@ 2023-10-06 17:12   ` Adhemerval Zanella Netto
  2023-10-06 18:29   ` DJ Delorie
  1 sibling, 0 replies; 20+ messages in thread
From: Adhemerval Zanella Netto @ 2023-10-06 17:12 UTC (permalink / raw)
  To: DJ Delorie, libc-alpha



On 06/10/23 11:44, Adhemerval Zanella Netto wrote:
> 
> 
> On 04/10/23 17:55, DJ Delorie wrote:
>>
>> Before I start on actual coding, I'm sharing my thoughts on this
>> project to gain consensus...
>>
>> Problem: tunables are set by an environment variable, and may be
>> limited by security settings, containerization, etc.  Plus users may
>> not assume that the env var is pre-set, and just overwrite it.
>>
>> Solution: Add a way to specify system-wide defaults for tunables.
>>
> 
> The idea sounds ok, but adding on ld.so.cache means it would not work 
> for static.  I don't think this is really an issue, static PIE is really
> tricky because self-relocation happens after tunable (because tunables 
> itself might change ifunc selection); and trying to add support for 
> static PIE would require a lot of messy refactoring (all ld.so.cache 
> loading would need to be annotated hidden, no external function calling,
> even mem* ones; etc.).
> 
>> Ideas:
>>
>> * Specify some file or files in /etc that contain tunables settings.
>>   Follow the ld.so.conf patterns, allow subdirectories, etc.
>>
>> * Store tunables info in /etc/ld.so.cache in a new slot at the end,
>>   with a new enum for the chunk.  This way older glibc will just
>>   ignore it.  Parsing and storing will be done via ldconfig.
> 
> It means that we will have to always load the ld.so.cache, not only when
> we will actually have to load an ET_DYN .  It should be ok, but runtimes
> that usually only link against libc.so (like rust) will have additional
> overhead on startup.
> 
> We also have DF_1_NODEFLIB to inhibit loader cache search, should we add
> another flag to inhibit the global tunables?  It does not make sense to
> set per-library, but it still might be useful to set on ET_EXEC.
> 
> So I am not fully sure adding the global tunable setting on ld.so.cache is
> the correct approach.  However, adding on an external file will add
> another open/mmap/close on each program; plus the extra mmap.
> 
>>
>> * Values in ld.so.cache will be parsed but not range checked; that's
>>   dependent on what the glibc app expects.
> 
> Importing the range information on tunable definition is straightforward, 
> so I think we should add the range check on ldconfig ld.so.cache setup.
> There is no error checking on env var tunable, invalid values are just
> ignored without any user feedback.  Since we will do pre-processing,
> I think it would be valuable to at least show any possible invalid range,
> specially because this is a administration setting.
> 
>>
>> * read those, do range checking, and call callbacks at runtime
>>
>> * To speed processing, encode a hash for each tunable name, both in
>>   glibc's table (which is built at glibc build time) and in
>>   /etc/ld.so.cache.  Comparing the hash typically fails but avoids a
>>   string compare.  Matching hashes are followed by a string compare to
>>   verify.  The hash need not be crypographically secure.
> 
> Do we really need this optimization?  Internally, the tunables are already
> accessed through a enum, which is essentially a index on tunable_list.
> Why can you we use the same enums value on the cache definition keys? 
> 
> The string mapping could be accomplished by adding a string list, with
> the tunable value being the offset.
> 
>>
>> * I'm not going to try to add some "syntax" to specify if a tunable is
>>   overridable or not; this is a simple default-only change.
> 
> How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
> tunable?  Should we ignore the envvar or merge the results? Which one takes 
> precedence (I take the system-wide)? Should we add a way to override system-wide 
> value (similar to DF_1_NODEFLIB) as a runtime options (either another envvar or 
> a extra field in GLIBC_TUNABLE)?
> 
>>
>> * Tunables set by these defaults will not be disabled for setuid
>>   programs; it's assumed they're a "trusted source".
> 
> This seems reasonable, and with this rationale should we add an option
> to allow some tunable to be disabled or overriden? I take this is an extra
> complexity that we should not pursuit. 

Another possible feature that comes from the tunable discussion is whether 
make sense to add a per-process tunables.  The aarch64 MTE for instance is an
example, it is disabled by default because of performance implications; so
the admin might just enable it on some really security sensitive processes.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 14:44 ` Adhemerval Zanella Netto
  2023-10-06 17:12   ` Adhemerval Zanella Netto
@ 2023-10-06 18:29   ` DJ Delorie
  2023-10-06 19:14     ` Adhemerval Zanella Netto
  1 sibling, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-06 18:29 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha

Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
> The idea sounds ok, but adding on ld.so.cache means it would not work 
> for static.  I don't think this is really an issue, static PIE is really
> tricky because self-relocation happens after tunable (because tunables 
> itself might change ifunc selection); and trying to add support for 
> static PIE would require a lot of messy refactoring (all ld.so.cache 
> loading would need to be annotated hidden, no external function calling,
> even mem* ones; etc.).

The idea behind using this is that admins are used to running ldconfig
and managing ld.so.cache, so there would be nothing new to learn.  The
cache already has some hwcaps-related info in it, too, for selecting
suitable libraries.

>> Ideas:
>> 
>> * Specify some file or files in /etc that contain tunables settings.
>>   Follow the ld.so.conf patterns, allow subdirectories, etc.
>> 
>> * Store tunables info in /etc/ld.so.cache in a new slot at the end,
>>   with a new enum for the chunk.  This way older glibc will just
>>   ignore it.  Parsing and storing will be done via ldconfig.
>
> It means that we will have to always load the ld.so.cache, not only when
> we will actually have to load an ET_DYN .  It should be ok, but runtimes
> that usually only link against libc.so (like rust) will have additional
> overhead on startup.

We don't have to "load" it just map it and read the aux data at the end.
But, yeah.

> We also have DF_1_NODEFLIB to inhibit loader cache search, should we add
> another flag to inhibit the global tunables?  It does not make sense to
> set per-library, but it still might be useful to set on ET_EXEC.

If there were a system-wide tunable that caused improper action, it
wouldn't be a "tunable" it would be a "stoppable".  If a single program
was incompatible with system-wide tunables, it would need the environmen
variable set to tune them for the specific program.

> So I am not fully sure adding the global tunable setting on ld.so.cache is
> the correct approach.  However, adding on an external file will add
> another open/mmap/close on each program; plus the extra mmap.

Yup.  And worst case, those apps that don't get the tunable...  act like
they do now, with no system-wide tunables.

If the settings were mandatory, I'd worry more.

>> * Values in ld.so.cache will be parsed but not range checked; that's
>>   dependent on what the glibc app expects.
>
> Importing the range information on tunable definition is straightforward, 

Unless it differs between applications.  Or if the cache were generated
with one version of glibc and the application runs with a different
version.

> so I think we should add the range check on ldconfig ld.so.cache setup.
> There is no error checking on env var tunable, invalid values are just
> ignored without any user feedback.  Since we will do pre-processing,
> I think it would be valuable to at least show any possible invalid range,
> specially because this is a administration setting.

I see no problem with validating at cache time, but I don't want to skip
range checking at run time.  Doing so leads to security bugs.

>> * read those, do range checking, and call callbacks at runtime
>> 
>> * To speed processing, encode a hash for each tunable name, both in
>>   glibc's table (which is built at glibc build time) and in
>>   /etc/ld.so.cache.  Comparing the hash typically fails but avoids a
>>   string compare.  Matching hashes are followed by a string compare to
>>   verify.  The hash need not be crypographically secure.

> Do we really need this optimization?  Internally, the tunables are already
> accessed through a enum,

That enum might change from version to version.  We're already seeing
enum-related issues with RHEL upgrades.

>> * I'm not going to try to add some "syntax" to specify if a tunable is
>>   overridable or not; this is a simple default-only change.
>
> How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
> tunable?

The variable overrides the cache.

>> * Tunables set by these defaults will not be disabled for setuid
>>   programs; it's assumed they're a "trusted source".
>
> This seems reasonable, and with this rationale should we add an option
> to allow some tunable to be disabled or overriden? I take this is an extra
> complexity that we should not pursuit. 

Agreed; we want a simple system.

> Another possible feature that comes from the tunable discussion is
> whether make sense to add a per-process tunables.

Er, isn't that the environment variable?


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 18:29   ` DJ Delorie
@ 2023-10-06 19:14     ` Adhemerval Zanella Netto
  2023-10-06 20:25       ` DJ Delorie
  2023-10-06 22:04       ` DJ Delorie
  0 siblings, 2 replies; 20+ messages in thread
From: Adhemerval Zanella Netto @ 2023-10-06 19:14 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha



On 06/10/23 15:29, DJ Delorie wrote:
> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
>> The idea sounds ok, but adding on ld.so.cache means it would not work 
>> for static.  I don't think this is really an issue, static PIE is really
>> tricky because self-relocation happens after tunable (because tunables 
>> itself might change ifunc selection); and trying to add support for 
>> static PIE would require a lot of messy refactoring (all ld.so.cache 
>> loading would need to be annotated hidden, no external function calling,
>> even mem* ones; etc.).
> 
> The idea behind using this is that admins are used to running ldconfig
> and managing ld.so.cache, so there would be nothing new to learn.  The
> cache already has some hwcaps-related info in it, too, for selecting
> suitable libraries.

The hwcap-related are still used for library selection, the original
intention of the ld.so.cache.  What I am afraid is ld.so.cache start to
being an umbrella for different and unrelated settings.

> 
>>> Ideas:
>>>
>>> * Specify some file or files in /etc that contain tunables settings.
>>>   Follow the ld.so.conf patterns, allow subdirectories, etc.
>>>
>>> * Store tunables info in /etc/ld.so.cache in a new slot at the end,
>>>   with a new enum for the chunk.  This way older glibc will just
>>>   ignore it.  Parsing and storing will be done via ldconfig.
>>
>> It means that we will have to always load the ld.so.cache, not only when
>> we will actually have to load an ET_DYN .  It should be ok, but runtimes
>> that usually only link against libc.so (like rust) will have additional
>> overhead on startup.
> 
> We don't have to "load" it just map it and read the aux data at the end.
> But, yeah.

By 'load' I man mmap the ld.so.cache, which still adds extra commit charge.

> 
>> We also have DF_1_NODEFLIB to inhibit loader cache search, should we add
>> another flag to inhibit the global tunables?  It does not make sense to
>> set per-library, but it still might be useful to set on ET_EXEC.
> 
> If there were a system-wide tunable that caused improper action, it
> wouldn't be a "tunable" it would be a "stoppable".  If a single program
> was incompatible with system-wide tunables, it would need the environmen
> variable set to tune them for the specific program.

It is not improper action that I worried, but security and performance
implications.  For instance, the malloc tunables change performance depending
of the workload; a system-wide tunable might not the best option for all
programs.

The DF_ is just a shortcut to avoid the need to know which tunables are
set system-wide (assuming that the environment variables has precedence
over the system-wide). But I am assuming that system-wide has preference
over user-defined, which does not seems the case for your proposal.

> 
>> So I am not fully sure adding the global tunable setting on ld.so.cache is
>> the correct approach.  However, adding on an external file will add
>> another open/mmap/close on each program; plus the extra mmap.
> 
> Yup.  And worst case, those apps that don't get the tunable...  act like
> they do now, with no system-wide tunables.
> 
> If the settings were mandatory, I'd worry more.

I think what is not clear is if the idea is to mimic the 'security_level'
of tunable (which I intend to remove), in a way that we might have tunable
that might overridden and/or disabled by the process (through the envvar).

> 
>>> * Values in ld.so.cache will be parsed but not range checked; that's
>>>   dependent on what the glibc app expects.
>>
>> Importing the range information on tunable definition is straightforward, 
> 
> Unless it differs between applications.  Or if the cache were generated
> with one version of glibc and the application runs with a different
> version.

But in this case, and invalid/unknown value should be ignored if the program
is using a different glibc version.  Setting an invalid/unknown tunable still
make little sense to me, it means that it will always be ignored by some target 
if you are running different glibc with different tunable setting support.
And I don't see why we should not make it explicit for the administrator. 

Maybe the best way is to make the range/key check as default and add an
option to force to set invalid values.


> 
>> so I think we should add the range check on ldconfig ld.so.cache setup.
>> There is no error checking on env var tunable, invalid values are just
>> ignored without any user feedback.  Since we will do pre-processing,
>> I think it would be valuable to at least show any possible invalid range,
>> specially because this is a administration setting.
> 
> I see no problem with validating at cache time, but I don't want to skip
> range checking at run time.  Doing so leads to security bugs.

I agree, and I was not suggesting otherwise.

> 
>>> * read those, do range checking, and call callbacks at runtime
>>>
>>> * To speed processing, encode a hash for each tunable name, both in
>>>   glibc's table (which is built at glibc build time) and in
>>>   /etc/ld.so.cache.  Comparing the hash typically fails but avoids a
>>>   string compare.  Matching hashes are followed by a string compare to
>>>   verify.  The hash need not be crypographically secure.
> 
>> Do we really need this optimization?  Internally, the tunables are already
>> accessed through a enum,
> 
> That enum might change from version to version.  We're already seeing
> enum-related issues with RHEL upgrades.

Yes, Carlos has brought the awk sorting problem.  I think this is fixable
(maybe porting the tunables generation to python, run the sysdeps search
in a predictable way, set enum value based on tunable ordering) and we can
add test to check if tunable enum changes over releases.

I still think this is simpler than data structure your are proposing, and 
with less performance issues.  But I don't have a strong preference.

> 
>>> * I'm not going to try to add some "syntax" to specify if a tunable is
>>>   overridable or not; this is a simple default-only change.
>>
>> How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
>> tunable?
> 
> The variable overrides the cache.

Right.  Do we allow security opt-in option as well? I am asking because
in this case, it is expected that the system-wide should not be overridden.

> 
>>> * Tunables set by these defaults will not be disabled for setuid
>>>   programs; it's assumed they're a "trusted source".
>>
>> This seems reasonable, and with this rationale should we add an option
>> to allow some tunable to be disabled or overriden? I take this is an extra
>> complexity that we should not pursuit. 
> 
> Agreed; we want a simple system.
> 
>> Another possible feature that comes from the tunable discussion is
>> whether make sense to add a per-process tunables.
> 
> Er, isn't that the environment variable?
> 

It is a easier way to configure per-process tunable, it avoid messing with FS 
that either are mounted RO or do not allow adding wrappers to setup GLIBC_TUNABLES.

Also, my idea is to just remove the tunable setting for setuid/setguid; so 
per-process is a way to setup specific rules for security sensitive processes
(assuming that we will support non-overriden security tunables).

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 19:14     ` Adhemerval Zanella Netto
@ 2023-10-06 20:25       ` DJ Delorie
  2023-10-17 14:10         ` Adhemerval Zanella Netto
  2023-10-06 22:04       ` DJ Delorie
  1 sibling, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-06 20:25 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha

Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
> The hwcap-related are still used for library selection, the original
> intention of the ld.so.cache.  What I am afraid is ld.so.cache start to
> being an umbrella for different and unrelated settings.

The alternative is to add an /etc/tunables.cache which would correspond
to /etc/tunables.conf and/or /etc/tunables.conf.d/*

On most systems (no files) that would add one unsuccessful stat() call.

> It is not improper action that I worried, but security and performance
> implications.  For instance, the malloc tunables change performance depending
> of the workload; a system-wide tunable might not the best option for all
> programs.

Yup.  That would be a bad choice, but not an *invalid* choice.  The more
likely use of these tunables would be to alter the hwcaps logic to
better match the hardware, or to enforce a "common minimum" hardware
level for migratable programs.  Or something else I can't imagine just
yet ;-)

> But I am assuming that system-wide has preference
> over user-defined, which does not seems the case for your proposal.

Since these are tunables and not, say, security settings, it seemed to
make sense that a system-wide setting would be "new default" relative to
the environment variable.  An environment variable can be set for a
specific program; a system-wide setting cannot.

> I think what is not clear is if the idea is to mimic the 'security_level'
> of tunable (which I intend to remove), in a way that we might have tunable
> that might overridden and/or disabled by the process (through the envvar).

I thought of that - being able to have flags for tunables that control
those overrides et al - but decided against it.  These are tunables, not
security settings, and are more "advisory" than "mandatory", and I
couldn't think of a legitimate reason to stop a program from having a
program-specific tuning.

>>>> * Values in ld.so.cache will be parsed but not range checked; that's
>>>>   dependent on what the glibc app expects.
>>>
>>> Importing the range information on tunable definition is straightforward, 
>> 
>> Unless it differs between applications.  Or if the cache were generated
>> with one version of glibc and the application runs with a different
>> version.
>
> But in this case, and invalid/unknown value should be ignored if the program
> is using a different glibc version.

The case I was referring to would be if the *range* changed between
versions.  Same tunable name, different min/max.

I don't think it would matter much to test the wrong range, but the app
still needs to range check at runtime anyway.

> Setting an invalid/unknown tunable still make little sense to me, it
> means that it will always be ignored by some target if you are running
> different glibc with different tunable setting support.  And I don't
> see why we should not make it explicit for the administrator.
>
> Maybe the best way is to make the range/key check as default and add an
> option to force to set invalid values.

I'm OK with warnings.

On a system with multiple installed versions of glibc (no, don't ask me
how ;) there might not be one common set of checks that works.

>> That enum might change from version to version.  We're already seeing
>> enum-related issues with RHEL upgrades.
>
> Yes, Carlos has brought the awk sorting problem.  I think this is fixable
> (maybe porting the tunables generation to python, run the sysdeps search
> in a predictable way, set enum value based on tunable ordering) and we can
> add test to check if tunable enum changes over releases.
>
> I still think this is simpler than data structure your are proposing, and 
> with less performance issues.  But I don't have a strong preference.

If we store the enums, and *also* store the tunable name, we could use
the enum for lookup but also strcmp to validate that it's the correct
one.

>>>> * I'm not going to try to add some "syntax" to specify if a tunable is
>>>>   overridable or not; this is a simple default-only change.
>>>
>>> How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
>>> tunable?
>> 
>> The variable overrides the cache.
>
> Right.  Do we allow security opt-in option as well? I am asking because
> in this case, it is expected that the system-wide should not be overridden.

If a tunable needs to be ignored for security reasons, I would assume
the system-wide default would be left alone but the environment variable
would be ignored.  I do not expect a case where a system-wide tunable
should become "sticky" and block the environment variable in a
non-security context.

This assumes that a correct tunable setting is required for
secure/proper operation; if this is not the case, the program is at
fault ;-) because it's not just "tuning" at that point.

>> Er, isn't that the environment variable?
>> 
>
> It is a easier way to configure per-process tunable, it avoid messing with FS 
> that either are mounted RO or do not allow adding wrappers to setup GLIBC_TUNABLES.
>
> Also, my idea is to just remove the tunable setting for setuid/setguid; so 
> per-process is a way to setup specific rules for security sensitive processes
> (assuming that we will support non-overriden security tunables).

So /etc/tunables.conf would have something like this?

[/bin/bash]
glibc.malloc.max_arenas=1

This is the type of complexity I wanted to avoid.

We could, in theory, add an ELF section for embedding tunables into an
executable image, but that's outside my scope.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 19:14     ` Adhemerval Zanella Netto
  2023-10-06 20:25       ` DJ Delorie
@ 2023-10-06 22:04       ` DJ Delorie
  1 sibling, 0 replies; 20+ messages in thread
From: DJ Delorie @ 2023-10-06 22:04 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha

> The alternative is to add an /etc/tunables.cache which would correspond
> to /etc/tunables.conf and/or /etc/tunables.conf.d/*

This adds the question: if we have a separate cache file, do we need a
separate program to generate it?


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-06 20:25       ` DJ Delorie
@ 2023-10-17 14:10         ` Adhemerval Zanella Netto
  2023-10-17 14:17           ` Siddhesh Poyarekar
  2023-10-17 17:40           ` Zack Weinberg
  0 siblings, 2 replies; 20+ messages in thread
From: Adhemerval Zanella Netto @ 2023-10-17 14:10 UTC (permalink / raw)
  To: DJ Delorie; +Cc: libc-alpha



On 06/10/23 17:25, DJ Delorie wrote:
> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
>> The hwcap-related are still used for library selection, the original
>> intention of the ld.so.cache.  What I am afraid is ld.so.cache start to
>> being an umbrella for different and unrelated settings.
> 
> The alternative is to add an /etc/tunables.cache which would correspond
> to /etc/tunables.conf and/or /etc/tunables.conf.d/*
> 
> On most systems (no files) that would add one unsuccessful stat() call.

We can use 'access' to check for file existent first and then read the whole
file, as we do for /etc/ld.so.preload.  It should slight faster than stat.  

> 
>> It is not improper action that I worried, but security and performance
>> implications.  For instance, the malloc tunables change performance depending
>> of the workload; a system-wide tunable might not the best option for all
>> programs.
> 
> Yup.  That would be a bad choice, but not an *invalid* choice.  The more
> likely use of these tunables would be to alter the hwcaps logic to
> better match the hardware, or to enforce a "common minimum" hardware
> level for migratable programs.  Or something else I can't imagine just
> yet ;-)
> 
>> But I am assuming that system-wide has preference
>> over user-defined, which does not seems the case for your proposal.
> 
> Since these are tunables and not, say, security settings, it seemed to
> make sense that a system-wide setting would be "new default" relative to
> the environment variable.  An environment variable can be set for a
> specific program; a system-wide setting cannot.
> 
>> I think what is not clear is if the idea is to mimic the 'security_level'
>> of tunable (which I intend to remove), in a way that we might have tunable
>> that might overridden and/or disabled by the process (through the envvar).
> 
> I thought of that - being able to have flags for tunables that control
> those overrides et al - but decided against it.  These are tunables, not
> security settings, and are more "advisory" than "mandatory", and I
> couldn't think of a legitimate reason to stop a program from having a
> program-specific tuning.

But we already have opt-in security features with glibc.cpu.x86_ibt,
glibc.cpu.x86_shstk, and glibc.mem.tagging.  At least the x86 ones,
the default is set by an ELF property (assuming --enable-cet), but
memory tagging is complete opt-in.

That's why I think we either need to add some security context on
system-wide tunables; where the tunable can not be override by user;
or move the opt-in security tunable to a different mechanism.

> 
>>>>> * Values in ld.so.cache will be parsed but not range checked; that's
>>>>>   dependent on what the glibc app expects.
>>>>
>>>> Importing the range information on tunable definition is straightforward, 
>>>
>>> Unless it differs between applications.  Or if the cache were generated
>>> with one version of glibc and the application runs with a different
>>> version.
>>
>> But in this case, and invalid/unknown value should be ignored if the program
>> is using a different glibc version.
> 
> The case I was referring to would be if the *range* changed between
> versions.  Same tunable name, different min/max.
> 
> I don't think it would matter much to test the wrong range, but the app
> still needs to range check at runtime anyway.

Yes, I wasn't say otherwise.  The range check should always be done at
runtime as well.

> 
>> Setting an invalid/unknown tunable still make little sense to me, it
>> means that it will always be ignored by some target if you are running
>> different glibc with different tunable setting support.  And I don't
>> see why we should not make it explicit for the administrator.
>>
>> Maybe the best way is to make the range/key check as default and add an
>> option to force to set invalid values.
> 
> I'm OK with warnings.
> 
> On a system with multiple installed versions of glibc (no, don't ask me
> how ;) there might not be one common set of checks that works.
> 
>>> That enum might change from version to version.  We're already seeing
>>> enum-related issues with RHEL upgrades.
>>
>> Yes, Carlos has brought the awk sorting problem.  I think this is fixable
>> (maybe porting the tunables generation to python, run the sysdeps search
>> in a predictable way, set enum value based on tunable ordering) and we can
>> add test to check if tunable enum changes over releases.
>>
>> I still think this is simpler than data structure your are proposing, and 
>> with less performance issues.  But I don't have a strong preference.
> 
> If we store the enums, and *also* store the tunable name, we could use
> the enum for lookup but also strcmp to validate that it's the correct
> one.

Sounds reasonable.

> 
>>>>> * I'm not going to try to add some "syntax" to specify if a tunable is
>>>>>   overridable or not; this is a simple default-only change.
>>>>
>>>> How should we handle the envvar GLIBC_TUNABLEs in the presence of a system-wide
>>>> tunable?
>>>
>>> The variable overrides the cache.
>>
>> Right.  Do we allow security opt-in option as well? I am asking because
>> in this case, it is expected that the system-wide should not be overridden.
> 
> If a tunable needs to be ignored for security reasons, I would assume
> the system-wide default would be left alone but the environment variable
> would be ignored.  I do not expect a case where a system-wide tunable
> should become "sticky" and block the environment variable in a
> non-security context.

Yes, I would expect that once the administrator sets a opt-in security
features; it should not be able to be disable by user tunables.

> 
> This assumes that a correct tunable setting is required for
> secure/proper operation; if this is not the case, the program is at
> fault ;-) because it's not just "tuning" at that point.
> 
>>> Er, isn't that the environment variable?
>>>
>>
>> It is a easier way to configure per-process tunable, it avoid messing with FS 
>> that either are mounted RO or do not allow adding wrappers to setup GLIBC_TUNABLES.
>>
>> Also, my idea is to just remove the tunable setting for setuid/setguid; so 
>> per-process is a way to setup specific rules for security sensitive processes
>> (assuming that we will support non-overriden security tunables).
> 
> So /etc/tunables.conf would have something like this?
> 
> [/bin/bash]
> glibc.malloc.max_arenas=1
> 
> This is the type of complexity I wanted to avoid.
> 
> We could, in theory, add an ELF section for embedding tunables into an
> executable image, but that's outside my scope.
> 

This was only an idea, but I take this might be added only if we do have a
requirement for that.

>> The alternative is to add an /etc/tunables.cache which would correspond
>> to etc/tunables.conf and/or /etc/tunables.conf.d*
> 
> This adds the question: if we have a separate cache file, do we need a
> separate program to generate it?
> 

I think it would make sense, since ldconfig is really described as 'configure
dynamic linker run-time bindings'.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 14:10         ` Adhemerval Zanella Netto
@ 2023-10-17 14:17           ` Siddhesh Poyarekar
  2023-10-17 14:37             ` Siddhesh Poyarekar
                               ` (2 more replies)
  2023-10-17 17:40           ` Zack Weinberg
  1 sibling, 3 replies; 20+ messages in thread
From: Siddhesh Poyarekar @ 2023-10-17 14:17 UTC (permalink / raw)
  To: Adhemerval Zanella Netto, DJ Delorie; +Cc: libc-alpha

On 2023-10-17 10:10, Adhemerval Zanella Netto wrote:
> But we already have opt-in security features with glibc.cpu.x86_ibt,
> glibc.cpu.x86_shstk, and glibc.mem.tagging.  At least the x86 ones,
> the default is set by an ELF property (assuming --enable-cet), but
> memory tagging is complete opt-in.
> 
> That's why I think we either need to add some security context on
> system-wide tunables; where the tunable can not be override by user;
> or move the opt-in security tunable to a different mechanism.

Only stricter overrides to systemwide tunables should be allowed, e.g. 
going from enabled memory tagging to disabled memory tagging.  For 
numeric values such as mmap_threshold, we may need to figure out on a 
case by case basis what constitutes "stricter".

Thanks,
Sid

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 14:17           ` Siddhesh Poyarekar
@ 2023-10-17 14:37             ` Siddhesh Poyarekar
  2023-10-17 15:43             ` DJ Delorie
  2023-10-17 16:45             ` DJ Delorie
  2 siblings, 0 replies; 20+ messages in thread
From: Siddhesh Poyarekar @ 2023-10-17 14:37 UTC (permalink / raw)
  To: Adhemerval Zanella Netto, DJ Delorie; +Cc: libc-alpha

On 2023-10-17 10:17, Siddhesh Poyarekar wrote:
> On 2023-10-17 10:10, Adhemerval Zanella Netto wrote:
>> But we already have opt-in security features with glibc.cpu.x86_ibt,
>> glibc.cpu.x86_shstk, and glibc.mem.tagging.  At least the x86 ones,
>> the default is set by an ELF property (assuming --enable-cet), but
>> memory tagging is complete opt-in.
>>
>> That's why I think we either need to add some security context on
>> system-wide tunables; where the tunable can not be override by user;
>> or move the opt-in security tunable to a different mechanism.
> 
> Only stricter overrides to systemwide tunables should be allowed, e.g. 
> going from enabled memory tagging to disabled memory tagging.  
I realized that I abruptly ended that statement, thus completely 
reversing its meaning ;)  I meant that memory tagging, when enabled in 
systemwide tunables, should not be possible to override using the 
GLIBC_TUNABLES envvar.

Thanks,
Sid

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 14:17           ` Siddhesh Poyarekar
  2023-10-17 14:37             ` Siddhesh Poyarekar
@ 2023-10-17 15:43             ` DJ Delorie
  2023-10-17 15:58               ` Siddhesh Poyarekar
  2023-10-17 16:45             ` DJ Delorie
  2 siblings, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-17 15:43 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: adhemerval.zanella, libc-alpha

Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
> Only stricter overrides to systemwide tunables should be allowed, e.g. 
> going from enabled memory tagging to disabled memory tagging.  For 
> numeric values such as mmap_threshold, we may need to figure out on a 
> case by case basis what constitutes "stricter".

Encoding "stricter" in the cache file might be difficult.  If we were to
include enforcement, I'd opt for "can't override" vs "can't override
unless stricter".


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 15:43             ` DJ Delorie
@ 2023-10-17 15:58               ` Siddhesh Poyarekar
  0 siblings, 0 replies; 20+ messages in thread
From: Siddhesh Poyarekar @ 2023-10-17 15:58 UTC (permalink / raw)
  To: DJ Delorie; +Cc: adhemerval.zanella, libc-alpha

On 2023-10-17 11:43, DJ Delorie wrote:
> Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
>> Only stricter overrides to systemwide tunables should be allowed, e.g.
>> going from enabled memory tagging to disabled memory tagging.  For
>> numeric values such as mmap_threshold, we may need to figure out on a
>> case by case basis what constitutes "stricter".
> 
> Encoding "stricter" in the cache file might be difficult.  If we were to
> include enforcement, I'd opt for "can't override" vs "can't override
> unless stricter".
> 

That check would have to live in the code rather than in the cache file 
and would end up being per-tunable.  Maybe enhance the callback routine 
in tunable_initialize path to pass the systemwide default, allowing the 
subsystem where the tunable is initialized to decide whether the envvar 
override should stick or not.

Sid

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 14:17           ` Siddhesh Poyarekar
  2023-10-17 14:37             ` Siddhesh Poyarekar
  2023-10-17 15:43             ` DJ Delorie
@ 2023-10-17 16:45             ` DJ Delorie
  2023-10-17 16:55               ` Siddhesh Poyarekar
  2 siblings, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-17 16:45 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: adhemerval.zanella, libc-alpha

Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
> Only stricter overrides to systemwide tunables should be allowed,

This leads to the next question: how to express these constraints in the
tunables.conf file.  A the simplest, prefixing each tunable with '+',
'-', or '=' for example?  For stricter, looser, or can't change?  Else
we need to come up with some more flexible "flag parser".


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 16:45             ` DJ Delorie
@ 2023-10-17 16:55               ` Siddhesh Poyarekar
  2023-10-17 17:14                 ` DJ Delorie
  0 siblings, 1 reply; 20+ messages in thread
From: Siddhesh Poyarekar @ 2023-10-17 16:55 UTC (permalink / raw)
  To: DJ Delorie; +Cc: adhemerval.zanella, libc-alpha

On 2023-10-17 12:45, DJ Delorie wrote:
> Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
>> Only stricter overrides to systemwide tunables should be allowed,
> 
> This leads to the next question: how to express these constraints in the
> tunables.conf file.  A the simplest, prefixing each tunable with '+',
> '-', or '=' for example?  For stricter, looser, or can't change?  Else
> we need to come up with some more flexible "flag parser".
> 

Actually I wasn't thinking of any conf file related constraint markup, I 
was thinking of TUNABLE_CALLBACKs encoding constraints in whichever way 
they deem fit.  e.g. for ibt it could be:

void
TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
{
   if (!strcmp (valp->system_default, "always_on"))
     return;

   /* Otherwise read the value.  */
}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 16:55               ` Siddhesh Poyarekar
@ 2023-10-17 17:14                 ` DJ Delorie
  2023-10-18 14:20                   ` Siddhesh Poyarekar
  0 siblings, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-17 17:14 UTC (permalink / raw)
  To: Siddhesh Poyarekar; +Cc: adhemerval.zanella, libc-alpha

Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
> Actually I wasn't thinking of any conf file related constraint markup, I 
> was thinking of TUNABLE_CALLBACKs encoding constraints in whichever way 
> they deem fit.  e.g. for ibt it could be:
>
> void
> TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
> {
>    if (!strcmp (valp->system_default, "always_on"))
>      return;
>
>    /* Otherwise read the value.  */
> }

So the tunable definition *itself* decides whether the sysadmin wants to
override a user?

Or are you saying the tunable *value* describes the constraint?


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 14:10         ` Adhemerval Zanella Netto
  2023-10-17 14:17           ` Siddhesh Poyarekar
@ 2023-10-17 17:40           ` Zack Weinberg
  2023-10-17 17:47             ` DJ Delorie
  1 sibling, 1 reply; 20+ messages in thread
From: Zack Weinberg @ 2023-10-17 17:40 UTC (permalink / raw)
  To: Adhemerval Zanella, DJ Delorie; +Cc: GNU libc development

On Tue, Oct 17, 2023, at 10:10 AM, Adhemerval Zanella Netto wrote:
> On 06/10/23 17:25, DJ Delorie wrote:
>> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
>>> The hwcap-related are still used for library selection, the original
>>> intention of the ld.so.cache.  What I am afraid is ld.so.cache start to
>>> being an umbrella for different and unrelated settings.
>> 
>> The alternative is to add an /etc/tunables.cache which would correspond
>> to /etc/tunables.conf and/or /etc/tunables.conf.d/*
>> 
>> On most systems (no files) that would add one unsuccessful stat() call.
>
> We can use 'access' to check for file existent first and then read the whole
> file, as we do for /etc/ld.so.preload.  It should slight faster than stat.  

Even better to open() unconditionally and ignore ENOENT failures.

zw

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 17:40           ` Zack Weinberg
@ 2023-10-17 17:47             ` DJ Delorie
  2023-10-17 18:17               ` Zack Weinberg
  0 siblings, 1 reply; 20+ messages in thread
From: DJ Delorie @ 2023-10-17 17:47 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: adhemerval.zanella, libc-alpha

"Zack Weinberg" <zack@owlfolio.org> writes:
> Even better to open() unconditionally and ignore ENOENT failures.

From a security/performance perspective, which is better - open() and
read a line at a time, or mmap() and parse in place?

ldconfig reads a line at a time, but it also has a lot of glibc-specific
helper functions (like argp_parse() and getline()) that I assume have
been checked for security.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 17:47             ` DJ Delorie
@ 2023-10-17 18:17               ` Zack Weinberg
  2023-10-17 18:21                 ` DJ Delorie
  0 siblings, 1 reply; 20+ messages in thread
From: Zack Weinberg @ 2023-10-17 18:17 UTC (permalink / raw)
  To: DJ Delorie; +Cc: Adhemerval Zanella, GNU libc development

On Tue, Oct 17, 2023, at 1:47 PM, DJ Delorie wrote:
> "Zack Weinberg" <zack@owlfolio.org> writes:
>> Even better to open() unconditionally and ignore ENOENT failures.
>
> From a security/performance perspective, which is better - open() and
> read a line at a time, or mmap() and parse in place?

Huh? You cannot mmap without having opened first.

zw

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 18:17               ` Zack Weinberg
@ 2023-10-17 18:21                 ` DJ Delorie
  0 siblings, 0 replies; 20+ messages in thread
From: DJ Delorie @ 2023-10-17 18:21 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: adhemerval.zanella, libc-alpha

"Zack Weinberg" <zack@owlfolio.org> writes:
>> From a security/performance perspective, which is better - open() and
>> read a line at a time, or mmap() and parse in place?
>
> Huh? You cannot mmap without having opened first.

true, but the question remains...


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: RFC: system-wide default tunables
  2023-10-17 17:14                 ` DJ Delorie
@ 2023-10-18 14:20                   ` Siddhesh Poyarekar
  0 siblings, 0 replies; 20+ messages in thread
From: Siddhesh Poyarekar @ 2023-10-18 14:20 UTC (permalink / raw)
  To: DJ Delorie; +Cc: adhemerval.zanella, libc-alpha

On 2023-10-17 13:14, DJ Delorie wrote:
> Siddhesh Poyarekar <siddhesh@gotplt.org> writes:
>> Actually I wasn't thinking of any conf file related constraint markup, I
>> was thinking of TUNABLE_CALLBACKs encoding constraints in whichever way
>> they deem fit.  e.g. for ibt it could be:
>>
>> void
>> TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp)
>> {
>>     if (!strcmp (valp->system_default, "always_on"))
>>       return;
>>
>>     /* Otherwise read the value.  */
>> }
> 
> So the tunable definition *itself* decides whether the sysadmin wants to
> override a user?

Sort of; the tunable definition decides how much control a systemwide 
tunable (consequently the sysadmin) has, on the capability of a user to 
override it.

So for security tunables it could be a latch value (like above) that a 
user may not be able to override.  For numeric value tunables it could 
be a range that a user is not allowed to surpass.  For string tunables, 
it could be a list of values the user is allowed to set; the first valid 
value in the list could be the default.

Thanks,
Sid

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2023-10-18 14:20 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-10-04 20:55 RFC: system-wide default tunables DJ Delorie
2023-10-06 14:44 ` Adhemerval Zanella Netto
2023-10-06 17:12   ` Adhemerval Zanella Netto
2023-10-06 18:29   ` DJ Delorie
2023-10-06 19:14     ` Adhemerval Zanella Netto
2023-10-06 20:25       ` DJ Delorie
2023-10-17 14:10         ` Adhemerval Zanella Netto
2023-10-17 14:17           ` Siddhesh Poyarekar
2023-10-17 14:37             ` Siddhesh Poyarekar
2023-10-17 15:43             ` DJ Delorie
2023-10-17 15:58               ` Siddhesh Poyarekar
2023-10-17 16:45             ` DJ Delorie
2023-10-17 16:55               ` Siddhesh Poyarekar
2023-10-17 17:14                 ` DJ Delorie
2023-10-18 14:20                   ` Siddhesh Poyarekar
2023-10-17 17:40           ` Zack Weinberg
2023-10-17 17:47             ` DJ Delorie
2023-10-17 18:17               ` Zack Weinberg
2023-10-17 18:21                 ` DJ Delorie
2023-10-06 22:04       ` DJ Delorie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).