Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Follow (mostly) POSIX rules for environment variables #17188

Merged
merged 3 commits into from
Oct 14, 2020

Conversation

keszybz
Copy link
Member

@keszybz keszybz commented Sep 28, 2020

No description provided.

@poettering
Copy link
Member

Humpf, why? This sounds very wrong. Bash functions should stay in bash, I really don't grok why we would accept them as exported env vars?

@keszybz
Copy link
Member Author

keszybz commented Sep 28, 2020

Humpf, why? This sounds very wrong. Bash functions should stay in bash, I really don't grok why we would accept them as exported env vars?

I'd look at it the other way around: why should we use bash rules for user variables names for anything else? Actually bash itself depends on the fact that it can export variables with names outside of this set to keep the user envvars and some other things that needs to be exported separate. Other shells have different sets of rules of what they allow as variables (I only checked zsh, but I'd expect e.g. fish to be creative in this regard). But it doesn't matter: we shouldn't limit the environment block to shell syntax.

Copy link
Member

@poettering poettering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must say I am not a fan of this. uploading bash functions as env vars into systemd sounds like a really bad idea. I am not sure we should be a transport for something like that.

The two linked usecases seem borked to me. the first one i don#t grok at all... and the second one is strange: it appears they want to patch around in bash' environment to switch between alternatives of implementations of some tools? first of all, this switching doesn't appear to be something you want to do for bash only, if you really want to do that at all... other shells and services spawned by systemd --user probably should be covered too...

So, if they only care about bash: they can import these bash functions into their bash invocations by making them in ~/.bashrc, which would magically make them appear in all instances of bash without uploading them into anything...

if they care about user services, it appears they should use the environment generator stuff instead.

Which makes me wonder why they would need this PR?

if (!e)
return false;

if (n <= 0)
return false;

if (e[0] >= '0' && e[0] <= '9')
return false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

urks. this is a security problem... Why this? did anyone ask for this?

Please, let's sanitize data. This is expressly mentioned in POSIX to be problematic and noone asked so far to allow this, so why change this?

DIGITS LETTERS \
"_"

static bool env_name_is_valid_n(const char *e, size_t n) {
const char *p;
static bool printable_portable_character(char c) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the function is a misnomer... the portable charset is larger...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestions? nonwhitespace_portable_character?

static void invalid_callback(const char *p, void *userdata) {
_cleanup_free_ char *t = cescape(p);

log_debug("Ignoring invalid environment assignment \"%s\".", strnull(t));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this really just be debug?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used debug because on my system there's quite a few variables which we refuse to export:
Ignoring invalid environment assignment "LESS_TERMCAP_mb=\033[01;31m".
Ignoring invalid environment assignment "LESS_TERMCAP_md=\033[01;31m".
Ignoring invalid environment assignment "LESS_TERMCAP_me=\033[0m".
Ignoring invalid environment assignment "LESS_TERMCAP_se=\033[0m".
Ignoring invalid environment assignment "LESS_TERMCAP_so=\033[01;44;33m".
Ignoring invalid environment assignment "LESS_TERMCAP_ue=\033[0m".
Ignoring invalid environment assignment "LESS_TERMCAP_us=\033[01;32m".
Logging at non-debug level about all of them would be annoying. So we should either relax our rules to allow the rvalues used here, or keep logging at debug level.

@keszybz
Copy link
Member Author

keszybz commented Sep 28, 2020

uploading bash functions as env vars into systemd sounds like a really bad idea. I am not sure we should be a transport for something like that.

So... I think the more general question is what function is the environment block in systemd is supposed to have. Is it supposed to be like os-release, a limited set of restricted variable names, it is supposed to be like a storage for bash variables, is it supposed to be like storage for arbitrary shell variables, or is it supposed to be a general storage for posix envvars? I really don't want to be in the game of specifying which shell is the most important and what types of variables should be allowed. After all, privileges are required to insert variables here, there is no trust boundary, and just allowing stuff that POSIX says is portable seems like the most rational choice.

urks. this is a security problem... Why this? did anyone ask for this?
This is expressly mentioned in POSIX to be problematic and noone asked so far to allow this, so why change this?

I think this is a misunderstanding. Why would a variable name with digits be relevant to security? Such variables are special in shell syntax, because of various magic variables with digits there. For that reason it'd also be awkward to require users to set or consume variables with leading digits, for example as a way to modify systemd behaviour. But once exported into the environment block, it seems to me the variable is as safe as any other. I'm not saying that using such variables is a particularly useful thing, but if a user wants to, let them knock themselves out.

…owed

There was some confusion about what POSIX says about variable names:

   names shall not contain the character '='. For values to be portable
   across systems conforming to POSIX.1-2008, the value shall be composed
   of characters from the portable character set (except NUL and as
   indicated below).

i.e. it allows almost all ASCII in variable names (without NUL and DEL and
'='). OTOH, it says that *utilities* use a smaller set of characters:

   Environment variable names used by the utilities in the Shell and
   Utilities volume of POSIX.1-2008 consist solely of uppercase letters,
   digits, and the <underscore> ( '_' ) from the characters defined in
   Portable Character Set and do not begin with a digit.

When enforcing variable names in environment blocks, we need to use this
first definition, so that we can propagate all valid variables.
I think having non-printable characters in variable names is too much, so
I took out the whitespace stuff from the first definition.

OTOH, when we use *shell syntax*, for example doing variable expansion,
it seems enough to support expansion of variables that the shell would allow.

Fixes systemd#14878,
https://bugzilla.redhat.com/show_bug.cgi?id=1754395,
https://bugzilla.redhat.com/show_bug.cgi?id=1879216.
When doing import-environment, we shouldn't fail if some assignment is invalid.
OTOH, if the invalid assignment is specified as a positional argument, we should
keep failing.

This would also fix https://bugzilla.redhat.com/show_bug.cgi?id=1754395, by
ignoring certain variables which are not important in that scenario. It seems
like the right thing to do in general.
@keszybz
Copy link
Member Author

keszybz commented Oct 12, 2020

Rebased.

@poettering
Copy link
Member

I still think Lmod or whatever package actually relies on this, and uploads bash code into the env block is really just broken. They shouldn't do that, and using systemd as a conduit for such terrible things is just sad.

That said, it probably is OK if we following POSIX naming rules on this, even though it's really a bad bad idea to pass potentially large pieces of bash-specific code around of this. It's conceptually a bad idea to pass literal, potentially large pieces of code around like this.

I really don#t grok why the offending package thinks its fun to dirty every process' env block with large code blobs like this as if they all where bash prorgams. They should just load that into bash (via .bashrc or .bash_profile), and not everything under the sun.

Summary: terrible usecase, but will merge this anyway.

@poettering poettering merged commit b0eb40c into systemd:master Oct 14, 2020
@kirelagin
Copy link

Does this mean that show-environment is unsafe again, because it is now possible to have a shell injection in variable names, since, e.g. a semicolon is allowed?

@keszybz keszybz deleted the envvars-posix branch October 15, 2020 06:25
@keszybz
Copy link
Member Author

keszybz commented Oct 15, 2020

Oh, I forgot about show-environment. Yeah, we need to escape or skip those. I'll make a follow-up PR.

keszybz added a commit to keszybz/systemd that referenced this pull request Oct 23, 2020
… are allowed"

This reverts commit b45c068.

I think the idea was generally sound, but didn't take into account the
limitations of show-environment and how it is used. People expect to be able to
eval systemctl show-environment output in bash, and no escaping syntax is
defined for environment *names* (we only do escaping for *values*). We could
skip such problematic variables in 'systemctl show-environment', and only allow
them to be inherited directly. But this would be confusing and ugly.

The original motivation for this change was that various import operations
would fail. a4ccce2 changed systemctl to filter
invalid variables in import-environment.
https://gitlab.gnome.org/GNOME/gnome-session/-/issues/71 does a similar change
in GNOME. So those problematic variables should not cause failures, but just
be silently ignored.

Finally, the environment block is becoming a dumping ground. In my gnome
session 'systemctl show-environment --user' includes stuff like PWD, FPATH
(from zsh), SHLVL=0 (no idea what that is). This is not directly related to
variable names (since all those are allowed under the stricter rules too), but
I think we should start pushing people away from running import-environment and
towards importing only select variables.

systemd#17188 (comment)
keszybz added a commit to keszybz/systemd that referenced this pull request Oct 23, 2020
… are allowed"

This reverts commit b45c068.

I think the idea was generally sound, but didn't take into account the
limitations of show-environment and how it is used. People expect to be able to
eval systemctl show-environment output in bash, and no escaping syntax is
defined for environment *names* (we only do escaping for *values*). We could
skip such problematic variables in 'systemctl show-environment', and only allow
them to be inherited directly. But this would be confusing and ugly.

The original motivation for this change was that various import operations
would fail. a4ccce2 changed systemctl to filter
invalid variables in import-environment.
https://gitlab.gnome.org/GNOME/gnome-session/-/issues/71 does a similar change
in GNOME. So those problematic variables should not cause failures, but just
be silently ignored.

Finally, the environment block is becoming a dumping ground. In my gnome
session 'systemctl show-environment --user' includes stuff like PWD, FPATH
(from zsh), SHLVL=0 (no idea what that is). This is not directly related to
variable names (since all those are allowed under the stricter rules too), but
I think we should start pushing people away from running import-environment and
towards importing only select variables.

systemd#17188 (comment)
lqb pushed a commit to lqb/systemd that referenced this pull request Oct 29, 2020
… are allowed"

This reverts commit b45c068.

I think the idea was generally sound, but didn't take into account the
limitations of show-environment and how it is used. People expect to be able to
eval systemctl show-environment output in bash, and no escaping syntax is
defined for environment *names* (we only do escaping for *values*). We could
skip such problematic variables in 'systemctl show-environment', and only allow
them to be inherited directly. But this would be confusing and ugly.

The original motivation for this change was that various import operations
would fail. a4ccce2 changed systemctl to filter
invalid variables in import-environment.
https://gitlab.gnome.org/GNOME/gnome-session/-/issues/71 does a similar change
in GNOME. So those problematic variables should not cause failures, but just
be silently ignored.

Finally, the environment block is becoming a dumping ground. In my gnome
session 'systemctl show-environment --user' includes stuff like PWD, FPATH
(from zsh), SHLVL=0 (no idea what that is). This is not directly related to
variable names (since all those are allowed under the stricter rules too), but
I think we should start pushing people away from running import-environment and
towards importing only select variables.

systemd#17188 (comment)
Yamakuzure pushed a commit to elogind/elogind that referenced this pull request Aug 10, 2021
… are allowed"

This reverts commit b45c068dd8fac7661a15e99e7cf699ff06010b13.

I think the idea was generally sound, but didn't take into account the
limitations of show-environment and how it is used. People expect to be able to
eval systemctl show-environment output in bash, and no escaping syntax is
defined for environment *names* (we only do escaping for *values*). We could
skip such problematic variables in 'systemctl show-environment', and only allow
them to be inherited directly. But this would be confusing and ugly.

The original motivation for this change was that various import operations
would fail. a4ccce22d9552dc74b6916cc5ec57f2a0b686b4f changed systemctl to filter
invalid variables in import-environment.
https://gitlab.gnome.org/GNOME/gnome-session/-/issues/71 does a similar change
in GNOME. So those problematic variables should not cause failures, but just
be silently ignored.

Finally, the environment block is becoming a dumping ground. In my gnome
session 'systemctl show-environment --user' includes stuff like PWD, FPATH
(from zsh), SHLVL=0 (no idea what that is). This is not directly related to
variable names (since all those are allowed under the stricter rules too), but
I think we should start pushing people away from running import-environment and
towards importing only select variables.

systemd/systemd#17188 (comment)
fbuihuu pushed a commit to openSUSE/systemd that referenced this pull request Jun 9, 2022
… are allowed"

This reverts commit b45c068.

I think the idea was generally sound, but didn't take into account the
limitations of show-environment and how it is used. People expect to be able to
eval systemctl show-environment output in bash, and no escaping syntax is
defined for environment *names* (we only do escaping for *values*). We could
skip such problematic variables in 'systemctl show-environment', and only allow
them to be inherited directly. But this would be confusing and ugly.

The original motivation for this change was that various import operations
would fail. a4ccce2 changed systemctl to filter
invalid variables in import-environment.
https://gitlab.gnome.org/GNOME/gnome-session/-/issues/71 does a similar change
in GNOME. So those problematic variables should not cause failures, but just
be silently ignored.

Finally, the environment block is becoming a dumping ground. In my gnome
session 'systemctl show-environment --user' includes stuff like PWD, FPATH
(from zsh), SHLVL=0 (no idea what that is). This is not directly related to
variable names (since all those are allowed under the stricter rules too), but
I think we should start pushing people away from running import-environment and
towards importing only select variables.

systemd/systemd#17188 (comment)
(cherry picked from commit ff46157)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

exporting bash functions as env vars are not compatible with systemctl's --import-environment operation
4 participants