machined: pass user as positional argument in machine_default_shell_args()
Instead of interpolating the user name directly into the sh -c script
body via asprintf %s, pass it as a positional parameter ($1) in a
separate argv entry. This avoids the user string being parsed as part
of the shell script syntax.
Also validate the user name in bus_machine_method_open_shell() with
valid_user_group_name(), matching the validation already done on the
Varlink path via json_dispatch_const_user_group_name().
Follow-up for 49af9e1368
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
|
||||
static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string);
|
||||
@@ -366,6 +367,9 @@ int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bu
|
||||
return r;
|
||||
user = isempty(user) ? "root" : user;
|
||||
|
||||
if (!valid_user_group_name(user, VALID_USER_RELAX))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name '%s'", user);
|
||||
|
||||
/* Ensure only root can shell into the root namespace. This is to avoid unprivileged users registering
|
||||
* a process they own in the root user namespace, and then shelling in as root or another user. Note that
|
||||
* the shell operation is privileged and requires 'auth_admin', so we do not need to check the caller's uid,
|
||||
|
||||
+13
-9
@@ -1103,11 +1103,10 @@ int machine_start_shell(
|
||||
|
||||
char** machine_default_shell_args(const char *user) {
|
||||
_cleanup_strv_free_ char **args = NULL;
|
||||
int r;
|
||||
|
||||
assert(user);
|
||||
|
||||
args = new0(char*, 3 + 1);
|
||||
args = new0(char*, 5 + 1);
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
@@ -1119,14 +1118,19 @@ char** machine_default_shell_args(const char *user) {
|
||||
if (!args[1])
|
||||
return NULL;
|
||||
|
||||
r = asprintf(&args[2],
|
||||
"shell=$(getent passwd %s 2>/dev/null | { IFS=: read _ _ _ _ _ _ x; echo \"$x\"; })\n"\
|
||||
"exec \"${shell:-/bin/sh}\" -l", /* -l is means --login */
|
||||
user);
|
||||
if (r < 0) {
|
||||
args[2] = NULL;
|
||||
args[2] = strdup(
|
||||
"shell=$(getent passwd \"$1\" 2>/dev/null | { IFS=: read _ _ _ _ _ _ x; echo \"$x\"; })\n"
|
||||
"exec \"${shell:-/bin/sh}\" -l"); /* -l means --login */
|
||||
if (!args[2])
|
||||
return NULL;
|
||||
|
||||
args[3] = strdup("sh"); /* $0 placeholder for sh -c */
|
||||
if (!args[3])
|
||||
return NULL;
|
||||
|
||||
args[4] = strdup(user); /* becomes $1 in the script */
|
||||
if (!args[4])
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TAKE_PTR(args);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user