1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-26 14:04:03 +03:00

Merge pull request #20157 from keszybz/numerical-uids-in--M

Allow numerical UIDs in systemctl -M uid@ and similar
This commit is contained in:
Luca Boccassi 2021-07-09 16:58:45 +01:00 committed by GitHub
commit 5c8cf104e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 74 deletions

View File

@ -8,6 +8,7 @@
#include "escape.h"
#include "hexdecoct.h"
#include "macro.h"
#include "strv.h"
#include "utf8.h"
int cescape_char(char c, char *buf) {
@ -542,3 +543,23 @@ char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
return str_realloc(buf);
}
char* quote_command_line(char **argv) {
_cleanup_free_ char *result = NULL;
assert(argv);
char **a;
STRV_FOREACH(a, argv) {
_cleanup_free_ char *t = NULL;
t = shell_maybe_quote(*a, SHELL_ESCAPE_EMPTY);
if (!t)
return NULL;
if (!strextend_with_separator(&result, " ", t))
return NULL;
}
return TAKE_PTR(result);
}

View File

@ -68,3 +68,4 @@ char* escape_non_printable_full(const char *str, size_t console_width, XEscapeFl
char* shell_escape(const char *s, const char *bad);
char* shell_maybe_quote(const char *s, ShellEscapeFlags flags);
char* quote_command_line(char **argv);

View File

@ -52,6 +52,7 @@
#include "env-file.h"
#include "env-util.h"
#include "errno-list.h"
#include "escape.h"
#include "execute.h"
#include "exit-status.h"
#include "fd-util.h"
@ -3638,8 +3639,6 @@ static int compile_suggested_paths(const ExecContext *c, const ExecParameters *p
return 0;
}
static char *exec_command_line(char **argv);
static int exec_parameters_get_cgroup_path(const ExecParameters *params, char **ret) {
bool using_subcgroup;
char *p;
@ -3842,7 +3841,7 @@ static int exec_child(
const char *vc = params->confirm_spawn;
_cleanup_free_ char *cmdline = NULL;
cmdline = exec_command_line(command->argv);
cmdline = quote_command_line(command->argv);
if (!cmdline) {
*exit_status = EXIT_MEMORY;
return log_oom();
@ -4688,12 +4687,15 @@ static int exec_child(
if (DEBUG_LOGGING) {
_cleanup_free_ char *line = NULL;
line = exec_command_line(final_argv);
if (line)
log_unit_struct(unit, LOG_DEBUG,
"EXECUTABLE=%s", executable,
LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
LOG_UNIT_INVOCATION_ID(unit));
line = quote_command_line(final_argv);
if (!line) {
*exit_status = EXIT_MEMORY;
return log_oom();
}
log_unit_struct(unit, LOG_DEBUG,
"EXECUTABLE=%s", executable,
LOG_UNIT_MESSAGE(unit, "Executing: %s", line));
}
if (exec_fd >= 0) {
@ -4777,7 +4779,7 @@ int exec_spawn(Unit *unit,
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
line = exec_command_line(command->argv);
line = quote_command_line(command->argv);
if (!line)
return log_oom();
@ -5992,46 +5994,6 @@ void exec_status_dump(const ExecStatus *s, FILE *f, const char *prefix) {
prefix, s->status);
}
static char *exec_command_line(char **argv) {
size_t k;
char *n, *p, **a;
bool first = true;
assert(argv);
k = 1;
STRV_FOREACH(a, argv)
k += strlen(*a)+3;
n = new(char, k);
if (!n)
return NULL;
p = n;
STRV_FOREACH(a, argv) {
if (!first)
*(p++) = ' ';
else
first = false;
if (strpbrk(*a, WHITESPACE)) {
*(p++) = '\'';
p = stpcpy(p, *a);
*(p++) = '\'';
} else
p = stpcpy(p, *a);
}
*p = 0;
/* FIXME: this doesn't really handle arguments that have
* spaces and ticks in them */
return n;
}
static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
_cleanup_free_ char *cmd = NULL;
const char *prefix2;
@ -6042,7 +6004,7 @@ static void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
prefix = strempty(prefix);
prefix2 = strjoina(prefix, "\t");
cmd = exec_command_line(c->argv);
cmd = quote_command_line(c->argv);
fprintf(f,
"%sCommand Line: %s\n",
prefix, cmd ? cmd : strerror_safe(ENOMEM));

View File

@ -37,11 +37,11 @@ int bus_container_connect_socket(sd_bus *b) {
r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
if (r < 0)
return r;
return log_debug_errno(r, "Failed to open namespace of PID "PID_FMT": %m", b->nspid);
b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (b->input_fd < 0)
return -errno;
return log_debug_errno(errno, "Failed to create a socket: %m");
b->input_fd = fd_move_above_stdio(b->input_fd);
@ -50,12 +50,12 @@ int bus_container_connect_socket(sd_bus *b) {
bus_socket_setup(b);
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
return -errno;
return log_debug_errno(errno, "Failed to create a socket pair: %m");
r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
if (r < 0)
return r;
return log_debug_errno(r, "Failed to create namespace for (sd-buscntr): %m");
if (r == 0) {
pair[0] = safe_close(pair[0]);
@ -80,20 +80,22 @@ int bus_container_connect_socket(sd_bus *b) {
n = read(pair[0], &error_buf, sizeof(error_buf));
if (n < 0)
return -errno;
return log_debug_errno(errno, "Failed to read error status from (sd-buscntr): %m");
if (n > 0) {
if (n != sizeof(error_buf))
return -EIO;
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Read error status of unexpected length %zd from (sd-buscntr): %m", n);
if (error_buf < 0)
return -EIO;
return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
"Got unexpected error status from (sd-buscntr): %m");
if (error_buf == EINPROGRESS)
return 1;
if (error_buf > 0)
return -error_buf;
return log_debug_errno(error_buf, "Got error from (sd-buscntr): %m");
}
return bus_socket_start_auth(b);

View File

@ -12,6 +12,7 @@
#include "bus-internal.h"
#include "bus-message.h"
#include "bus-socket.h"
#include "escape.h"
#include "fd-util.h"
#include "format-util.h"
#include "fs-util.h"
@ -962,8 +963,17 @@ int bus_socket_exec(sd_bus *b) {
assert(b->exec_path);
assert(b->busexec_pid == 0);
log_debug("sd-bus: starting bus%s%s with %s...",
b->description ? " " : "", strempty(b->description), b->exec_path);
if (DEBUG_LOGGING) {
_cleanup_free_ char *line = NULL;
if (b->exec_argv)
line = quote_command_line(b->exec_argv);
log_debug("sd-bus: starting bus%s%s with %s%s",
b->description ? " " : "", strempty(b->description),
line ?: b->exec_path,
b->exec_argv && !line ? "" : "");
}
r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
if (r < 0)
@ -984,10 +994,8 @@ int bus_socket_exec(sd_bus *b) {
if (b->exec_argv)
execvp(b->exec_path, b->exec_argv);
else {
const char *argv[] = { b->exec_path, NULL };
execvp(b->exec_path, (char**) argv);
}
else
execvp(b->exec_path, STRV_MAKE(b->exec_path));
_exit(EXIT_FAILURE);
}

View File

@ -39,6 +39,7 @@
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strv.h"
#include "user-util.h"
@ -1617,7 +1618,7 @@ static int user_and_machine_valid(const char *user_and_machine) {
if (!user)
return -ENOMEM;
if (!isempty(user) && !valid_user_group_name(user, VALID_USER_RELAX))
if (!isempty(user) && !valid_user_group_name(user, VALID_USER_RELAX | VALID_USER_ALLOW_NUMERIC))
return false;
h++;
@ -1648,17 +1649,25 @@ static int user_and_machine_equivalent(const char *user_and_machine) {
/* Otherwise, if we are root, then we can also allow the ".host" syntax, as that's the user this
* would connect to. */
if (geteuid() == 0 && STR_IN_SET(user_and_machine, ".host", "root@.host"))
uid_t uid = geteuid();
if (uid == 0 && STR_IN_SET(user_and_machine, ".host", "root@.host", "0@.host"))
return true;
/* Otherwise, we have to figure our user name, and compare things with that. */
un = getusername_malloc();
if (!un)
return -ENOMEM;
/* Otherwise, we have to figure out our user id and name, and compare things with that. */
char buf[DECIMAL_STR_MAX(uid_t)];
xsprintf(buf, UID_FMT, uid);
f = startswith(user_and_machine, un);
if (!f)
return false;
f = startswith(user_and_machine, buf);
if (!f) {
un = getusername_malloc();
if (!un)
return -ENOMEM;
f = startswith(user_and_machine, un);
if (!f)
return false;
}
return STR_IN_SET(f, "@", "@.host");
}

View File

@ -8,6 +8,8 @@
static void test_cescape(void) {
_cleanup_free_ char *t;
log_info("/* %s */", __func__);
assert_se(t = cescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313"));
assert_se(streq(t, "abc\\\\\\\"\\b\\f\\n\\r\\t\\v\\a\\003\\177\\234\\313"));
}
@ -15,6 +17,8 @@ static void test_cescape(void) {
static void test_xescape(void) {
_cleanup_free_ char *t;
log_info("/* %s */", __func__);
assert_se(t = xescape("abc\\\"\b\f\n\r\t\v\a\003\177\234\313", ""));
assert_se(streq(t, "abc\\x5c\"\\x08\\x0c\\x0a\\x0d\\x09\\x0b\\x07\\x03\\x7f\\x9c\\xcb"));
}
@ -26,6 +30,8 @@ static void test_xescape_full(bool eight_bits) {
const unsigned full_fit = !eight_bits ? 55 : 46;
XEscapeFlags flags = eight_bits * XESCAPE_8_BIT;
log_info("/* %s */", __func__);
for (unsigned i = 0; i < 60; i++) {
_cleanup_free_ char *t, *q;
@ -60,6 +66,8 @@ static void test_xescape_full(bool eight_bits) {
static void test_cunescape(void) {
_cleanup_free_ char *unescaped;
log_info("/* %s */", __func__);
assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", 0, &unescaped) < 0);
assert_se(cunescape("abc\\\\\\\"\\b\\f\\a\\n\\r\\t\\v\\003\\177\\234\\313\\000\\x00", UNESCAPE_RELAX, &unescaped) >= 0);
assert_se(streq_ptr(unescaped, "abc\\\"\b\f\a\n\r\t\v\003\177\234\313\\000\\x00"));
@ -133,6 +141,8 @@ static void test_shell_escape_one(const char *s, const char *bad, const char *ex
}
static void test_shell_escape(void) {
log_info("/* %s */", __func__);
test_shell_escape_one("", "", "");
test_shell_escape_one("\\", "", "\\\\");
test_shell_escape_one("foobar", "", "foobar");
@ -150,6 +160,7 @@ static void test_shell_maybe_quote_one(const char *s, ShellEscapeFlags flags, co
}
static void test_shell_maybe_quote(void) {
log_info("/* %s */", __func__);
test_shell_maybe_quote_one("", 0, "");
test_shell_maybe_quote_one("", SHELL_ESCAPE_EMPTY, "\"\"");
@ -192,6 +203,29 @@ static void test_shell_maybe_quote(void) {
test_shell_maybe_quote_one("głąb\002\003rząd", SHELL_ESCAPE_POSIX, "$'głąb\\002\\003rząd'");
}
static void test_quote_command_line_one(char **argv, const char *expected) {
_cleanup_free_ char *s;
assert_se(s = quote_command_line(argv));
log_info("%s", s);
assert_se(streq(s, expected));
}
static void test_quote_command_line(void) {
log_info("/* %s */", __func__);
test_quote_command_line_one(STRV_MAKE("true", "true"),
"true true");
test_quote_command_line_one(STRV_MAKE("true", "with a space"),
"true \"with a space\"");
test_quote_command_line_one(STRV_MAKE("true", "with a 'quote'"),
"true \"with a 'quote'\"");
test_quote_command_line_one(STRV_MAKE("true", "with a \"quote\""),
"true \"with a \\\"quote\\\"\"");
test_quote_command_line_one(STRV_MAKE("true", "$dollar"),
"true \"\\$dollar\"");
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@ -202,6 +236,7 @@ int main(int argc, char *argv[]) {
test_cunescape();
test_shell_escape();
test_shell_maybe_quote();
test_quote_command_line();
return 0;
}