mirror of
https://github.com/systemd/systemd.git
synced 2025-03-21 02:50:18 +03:00
Merge pull request #18129 from keszybz/envvars
Allow control characters in environment variable values
This commit is contained in:
commit
a2804e3cd8
@ -1080,8 +1080,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
|
||||
<para><command>systemd</command> supports an environment block that is passed to processes the manager
|
||||
spawns. The names of the variables can contain ASCII letters, digits, and the underscore
|
||||
character. Variable names cannot be empty or start with a digit. In variable values, most characters
|
||||
are allowed, but non-printable characters are currently rejected. The total length of the environment
|
||||
block is limited to <constant>_SC_ARG_MAX</constant> value defined by
|
||||
are allowed, but the whole sequence must be valid UTF-8. (Note that control characters like newline
|
||||
(<constant>NL</constant>), tab (<constant>TAB</constant>), or the escape character
|
||||
(<constant>ESC</constant>), <emphasis>are</emphasis> valid ASCII and thus valid UTF-8). The total
|
||||
length of the environment block is limited to <constant>_SC_ARG_MAX</constant> value defined by
|
||||
<citerefentry project='man-pages'><refentrytitle>sysconf</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
|
@ -57,16 +57,13 @@ bool env_value_is_valid(const char *e) {
|
||||
if (!utf8_is_valid(e))
|
||||
return false;
|
||||
|
||||
/* bash allows tabs and newlines in environment variables, and so
|
||||
* should we */
|
||||
if (string_has_cc(e, "\t\n"))
|
||||
return false;
|
||||
/* Note that variable *values* may contain control characters, in particular NL, TAB, BS, DEL, ESC…
|
||||
* When printing those variables with show-environment, we'll escape them. Make sure to print
|
||||
* environment variables carefully! */
|
||||
|
||||
/* POSIX says the overall size of the environment block cannot
|
||||
* be > ARG_MAX, an individual assignment hence cannot be
|
||||
* either. Discounting the shortest possible variable name of
|
||||
* length 1, the equal sign and trailing NUL this hence leaves
|
||||
* ARG_MAX-3 as longest possible variable value. */
|
||||
/* POSIX says the overall size of the environment block cannot be > ARG_MAX, an individual assignment
|
||||
* hence cannot be either. Discounting the shortest possible variable name of length 1, the equal
|
||||
* sign and trailing NUL this hence leaves ARG_MAX-3 as longest possible variable value. */
|
||||
if (strlen(e) > sc_arg_max() - 3)
|
||||
return false;
|
||||
|
||||
@ -86,10 +83,8 @@ bool env_assignment_is_valid(const char *e) {
|
||||
if (!env_value_is_valid(eq + 1))
|
||||
return false;
|
||||
|
||||
/* POSIX says the overall size of the environment block cannot
|
||||
* be > ARG_MAX, hence the individual variable assignments
|
||||
* cannot be either, but let's leave room for one trailing NUL
|
||||
* byte. */
|
||||
/* POSIX says the overall size of the environment block cannot be > ARG_MAX, hence the individual
|
||||
* variable assignments cannot be either, but let's leave room for one trailing NUL byte. */
|
||||
if (strlen(e) > sc_arg_max() - 1)
|
||||
return false;
|
||||
|
||||
|
@ -127,6 +127,12 @@ int import_environment(int argc, char *argv[], void *userdata) {
|
||||
|
||||
strv_env_clean_with_callback(copy, invalid_callback, NULL);
|
||||
|
||||
char **e;
|
||||
STRV_FOREACH(e, copy)
|
||||
if (string_has_cc(*e, NULL))
|
||||
log_notice("Environment variable $%.*s contains control characters, importing anyway.",
|
||||
(int) strcspn(*e, "="), *e);
|
||||
|
||||
r = sd_bus_message_append_strv(m, copy);
|
||||
|
||||
} else {
|
||||
@ -139,21 +145,30 @@ int import_environment(int argc, char *argv[], void *userdata) {
|
||||
STRV_FOREACH(a, strv_skip(argv, 1)) {
|
||||
|
||||
if (!env_name_is_valid(*a))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid environment variable name: %s", *a);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Not a valid environment variable name: %s", *a);
|
||||
|
||||
bool found = false;
|
||||
STRV_FOREACH(b, environ) {
|
||||
const char *eq;
|
||||
|
||||
eq = startswith(*b, *a);
|
||||
if (eq && *eq == '=') {
|
||||
if (string_has_cc(eq + 1, NULL))
|
||||
log_notice("Environment variable $%.*s contains control characters, importing anyway.",
|
||||
(int) (eq - *b), *b);
|
||||
|
||||
r = sd_bus_message_append(m, "s", *b);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
log_notice("Environment variable $%s not set, ignoring.", *a);
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
|
@ -265,6 +265,7 @@ static void test_env_clean(void) {
|
||||
"another=one",
|
||||
"another=final one",
|
||||
"CRLF=\r\n",
|
||||
"LESS_TERMCAP_mb=\x1b[01;31m",
|
||||
"BASH_FUNC_foo%%=() { echo foo\n}");
|
||||
assert_se(e);
|
||||
assert_se(!strv_env_is_valid(e));
|
||||
@ -277,7 +278,9 @@ static void test_env_clean(void) {
|
||||
assert_se(streq(e[3], "abcd=äöüß"));
|
||||
assert_se(streq(e[4], "xyz=xyz\n"));
|
||||
assert_se(streq(e[5], "another=final one"));
|
||||
assert_se(e[6] == NULL);
|
||||
assert_se(streq(e[6], "CRLF=\r\n"));
|
||||
assert_se(streq(e[7], "LESS_TERMCAP_mb=\x1b[01;31m"));
|
||||
assert_se(e[8] == NULL);
|
||||
}
|
||||
|
||||
static void test_env_name_is_valid(void) {
|
||||
@ -302,8 +305,11 @@ static void test_env_value_is_valid(void) {
|
||||
assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
|
||||
assert_se(env_value_is_valid("tab\tcharacter"));
|
||||
assert_se(env_value_is_valid("new\nline"));
|
||||
assert_se(!env_value_is_valid("Show this?\rNope. Show that!"));
|
||||
assert_se(!env_value_is_valid("new DOS\r\nline"));
|
||||
assert_se(env_value_is_valid("Show this?\rNope. Show that!"));
|
||||
assert_se(env_value_is_valid("new DOS\r\nline"));
|
||||
|
||||
assert_se(!env_value_is_valid("\xc5")); /* A truncated utf-8-encoded "ł".
|
||||
* We currently disallow that. */
|
||||
}
|
||||
|
||||
static void test_env_assignment_is_valid(void) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user