1
0
mirror of https://github.com/systemd/systemd synced 2025-11-17 07:44:46 +01:00

Compare commits

..

No commits in common. "0885e4a6e7ca93d3aef8186640bee911e81e3f4f" and "404d9bfb62a2ce14939b194e1f9f03e9dc537ae5" have entirely different histories.

22 changed files with 63 additions and 292 deletions

View File

@ -1601,7 +1601,7 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
<listitem><para>Binds the home directory of the specified user on the host into the container. Takes
the name of an existing user on the host as argument. May be used multiple times to bind multiple
users into the container. This does two things:</para>
users into the container. This does three things:</para>
<orderedlist>
<listitem><para>The user's home directory is bind mounted from the host into
@ -1616,7 +1616,7 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
user/group databases.</para></listitem>
</orderedlist>
<para>The combination of the two operations above ensures that it is possible to log into the
<para>The combination of the three operations above ensures that it is possible to log into the
container using the same account information as on the host. The user is only mapped transiently,
while the container is running, and the mapping itself does not result in persistent changes to the
container (except maybe for log messages generated at login time, and similar). Note that in
@ -1667,19 +1667,6 @@ After=sys-subsystem-net-devices-ens1.device</programlisting>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--bind-user-group=<replaceable>NAME</replaceable></option></term>
<listitem><para>When used with <option>--bind-user=</option>, includes the specified group as an
auxiliary group in the user records of users bound into the container. Takes a group name.</para>
<para>Note: This will not check whether the specified groups exist in the container.</para>
<para>This operation is only supported in combination with <option>--bind-user=</option>.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--inaccessible=</option></term>

View File

@ -526,20 +526,6 @@
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--bind-user-group=<replaceable>NAME</replaceable></option></term>
<listitem><para>When used with <option>--bind-user=</option>, includes the specified group as an
auxiliary group in the user records of users bound into the virtual machine. Takes a group name.</para>
<para>Note: This will not check whether the specified groups exist in the virtual machine.</para>
<para>This operation is only supported in combination with <option>--bind-user=</option>.</para>
<xi:include href="version-info.xml" xpointer="v259"/></listitem>
</varlistentry>
</variablelist>
</refsect2>

View File

@ -6347,17 +6347,15 @@ ServerAddress=192.168.0.1/24</programlisting>
<refsect1>
<title>[BridgeVLAN] Section Options</title>
<para>
The [BridgeVLAN] section manages the VLAN ID configuration of a bridge master or enslaved device.
To make the settings in this section take an effect,
The [BridgeVLAN] section manages the VLAN ID configurations of a bridge master or port, and accepts the
following keys. To make the settings in this section take an effect,
<varname>VLANFiltering=</varname> option has to be enabled on the bridge master, see the [Bridge]
section in
<citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>, and
each enslaved device needs to define the relevant VLAN IDs in its own [BridgeVLAN] section, which it
has in common with the bridge master.
All assigned VLAN IDs on the interface that are not configured in the .network file will be removed. If
<citerefentry><refentrytitle>systemd.netdev</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
If at least one valid settings specified in this section in a .network file for an interface, all
assigned VLAN IDs on the interface that are not configured in the .network file will be removed. If
VLAN IDs on an interface need to be managed by other tools, then the settings in this section cannot
be used in the matching .network file and <varname>VLANFiltering=</varname> needs to be disabled on
the bridge master.
be used in the matching .network file.
</para>
<variablelist class='network-directives'>

View File

@ -1485,8 +1485,7 @@ ExecStart=/bin/echo $ONE $TWO $THREE</programlisting>
<literal>too</literal>.
</para>
<para>Unless for commands with the special executable prefix <literal>:</literal>,
to pass a literal dollar sign, use <literal>$$</literal>.
<para>To pass a literal dollar sign, use <literal>$$</literal>.
Variables whose value is not known at expansion time are treated
as empty strings. Note that the first argument (i.e. the program
to execute) may not be a variable.</para>

View File

@ -3,6 +3,10 @@
"uid": 4711,
"disposition": "regular",
"enforcePasswordPolicy": false,
"memberOf": [
"wheel",
"systemd-journal"
],
"shell": "/bin/bash",
"privileged": {
"hashedPassword": ["$1$kqp7NF1f$tNnQcshPX53CSfRKTQD0R1"]

View File

@ -114,26 +114,6 @@ int path_is_extension_tree(ImageClass image_class, const char *path, const char
return 1;
}
int fd_is_os_tree(int fd) {
int r;
assert(fd >= 0);
r = open_extension_release_at(
fd,
IMAGE_MACHINE,
/* extension= */ NULL,
/* relax_extension_release_check= */ false,
/* ret_path= */ NULL,
/* ret_fd= */ NULL);
if (r == -ENOENT)
return false;
if (r < 0)
return r;
return true;
}
static int extension_release_strict_xattr_value(int extension_release_fd, const char *extension_release_dir_path, const char *filename) {
int r;

View File

@ -28,7 +28,6 @@ int path_is_extension_tree(ImageClass image_class, const char *path, const char
static inline int path_is_os_tree(const char *path) {
return path_is_extension_tree(_IMAGE_CLASS_INVALID, path, NULL, false);
}
int fd_is_os_tree(int fd);
int open_extension_release(const char *root, ImageClass image_class, const char *extension, bool relax_extension_release_check, char **ret_path, int *ret_fd);
int open_extension_release_at(int rfd, ImageClass image_class, const char *extension, bool relax_extension_release_check, char **ret_path, int *ret_fd);

View File

@ -148,27 +148,19 @@ int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid) {
return TAKE_FD(pipefd[0]);
}
int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
int import_mangle_os_tree(const char *path) {
_cleanup_free_ char *child = NULL, *t = NULL, *joined = NULL;
_cleanup_closedir_ DIR *d = NULL, *cd = NULL;
struct dirent *dent;
struct stat st;
int r;
assert(tree_fd >= 0);
if (FLAGS_SET(flags, IMPORT_FOREIGN_UID) && userns_fd >= 0)
return import_mangle_os_tree_fd_foreign(tree_fd, userns_fd);
assert(path);
/* Some tarballs contain a single top-level directory that contains the actual OS directory tree. Try to
* recognize this, and move the tree one level up. */
_cleanup_free_ char *path = NULL;
r = fd_get_path(tree_fd, &path);
if (r < 0)
return log_error_errno(r, "Failed to determine path of fd: %m");
r = fd_is_os_tree(tree_fd);
r = path_is_os_tree(path);
if (r < 0)
return log_error_errno(r, "Failed to determine whether '%s' is an OS tree: %m", path);
if (r > 0) {
@ -178,9 +170,9 @@ int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
log_debug("Directory tree '%s' is not recognizable as OS tree, checking whether to rearrange it.", path);
d = xopendirat(tree_fd, /* path= */ NULL, /* flags= */ 0);
d = opendir(path);
if (!d)
return log_error_errno(errno, "Failed to open directory '%s': %m", path);
return log_error_errno(r, "Failed to open directory '%s': %m", path);
errno = 0;
dent = readdir_no_dot(d);
@ -199,29 +191,29 @@ int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
errno = 0;
dent = readdir_no_dot(d);
if (dent) {
if (errno != 0)
return log_error_errno(errno, "Failed to iterate through directory '%s': %m", path);
log_debug("Directory '%s' does not look like an OS tree, and has multiple children, leaving as it is.", path);
return 0;
} else if (errno != 0)
return log_error_errno(errno, "Failed to iterate through directory '%s': %m", path);
_cleanup_close_ int child_fd = openat(dirfd(d), child, O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW|O_NONBLOCK);
if (child_fd < 0) {
if (IN_SET(errno, ENOTDIR, ELOOP)) {
log_debug_errno(errno, "Child '%s' of directory '%s' is not a directory, leaving things as they are.", child, path);
return 0;
}
return log_debug_errno(errno, "Failed to open file '%s/%s': %m", path, child);
}
if (fstat(child_fd, &st) < 0)
if (fstatat(dirfd(d), child, &st, AT_SYMLINK_NOFOLLOW) < 0)
return log_debug_errno(errno, "Failed to stat file '%s/%s': %m", path, child);
r = stat_verify_directory(&st);
if (r < 0) {
log_debug_errno(r, "Child '%s' of directory '%s' is not a directory, leaving things as they are.", child, path);
return 0;
}
joined = path_join(path, child);
if (!joined)
return log_oom();
r = fd_is_os_tree(child_fd);
r = path_is_os_tree(joined);
if (r == -ENOTDIR) {
log_debug("Directory '%s' does not look like an OS tree, and contains a single regular file only, leaving as it is.", path);
return 0;
}
if (r < 0)
return log_error_errno(r, "Failed to determine whether '%s' is an OS tree: %m", joined);
if (r == 0) {
@ -238,7 +230,7 @@ int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
*
* Let's now rearrange things, moving everything in the inner directory one level up */
cd = take_fdopendir(&child_fd);
cd = xopendirat(dirfd(d), child, O_NOFOLLOW);
if (!cd)
return log_error_errno(errno, "Can't open directory '%s': %m", joined);
@ -246,7 +238,7 @@ int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
/* Let's rename the child to an unguessable name so that we can be sure all files contained in it can be
* safely moved up and won't collide with the name. */
r = tempfn_random(child, /* extra= */ NULL, &t);
r = tempfn_random(child, NULL, &t);
if (r < 0)
return log_oom();
r = rename_noreplace(dirfd(d), child, dirfd(d), t);
@ -267,68 +259,15 @@ int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags) {
r = futimens(dirfd(d), (struct timespec[2]) { st.st_atim, st.st_mtim });
if (r < 0)
log_debug_errno(errno, "Failed to adjust top-level timestamps '%s', ignoring: %m", path);
log_debug_errno(r, "Failed to adjust top-level timestamps '%s', ignoring: %m", path);
r = fchmod_and_chown(dirfd(d), st.st_mode, st.st_uid, st.st_gid);
if (r < 0)
return log_error_errno(r, "Failed to adjust top-level directory mode/ownership '%s': %m", path);
log_info("Successfully rearranged OS tree.");
return 0;
}
int import_mangle_os_tree(const char *path, int userns_fd, ImportFlags flags) {
assert(path);
_cleanup_close_ int fd = open(path, O_DIRECTORY|O_CLOEXEC|O_PATH);
if (fd < 0)
return log_error_errno(errno, "Failed to open '%s': %m", path);
return import_mangle_os_tree_fd(fd, userns_fd, flags);
}
int import_mangle_os_tree_fd_foreign(
int tree_fd,
int userns_fd) {
int r;
assert(tree_fd >= 0);
assert(userns_fd >= 0);
r = safe_fork_full(
"mangle-tree",
/* stdio_fds= */ NULL,
(int[]) { userns_fd, tree_fd }, 2,
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG|FORK_WAIT,
/* ret_pid= */ NULL);
if (r < 0)
return r;
if (r == 0) {
/* child */
r = namespace_enter(
/* pidns_fd= */ -EBADF,
/* mntns_fd= */ -EBADF,
/* netns_fd= */ -EBADF,
userns_fd,
/* root_fd= */ -EBADF);
if (r < 0) {
log_error_errno(r, "Failed to join user namespace: %m");
_exit(EXIT_FAILURE);
}
r = import_mangle_os_tree_fd(tree_fd, /* userns_fd= */ -EBADF, /* flags= */ 0);
if (r < 0) {
log_error_errno(r, "Failed to mangle OS tree in foreign UID mode: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
return 0;
}
bool import_validate_local(const char *name, ImportFlags flags) {

View File

@ -37,9 +37,7 @@ typedef enum ImportFlags {
int import_fork_tar_c(int tree_fd, int userns_fd, PidRef *ret_pid);
int import_fork_tar_x(int tree_fd, int userns_fd, PidRef *ret_pid);
int import_mangle_os_tree_fd(int tree_fd, int userns_fd, ImportFlags flags);
int import_mangle_os_tree(const char *path, int userns_fd, ImportFlags flags);
int import_mangle_os_tree_fd_foreign(int tree_fd, int userns_fd);
int import_mangle_os_tree(const char *path);
bool import_validate_local(const char *name, ImportFlags flags);

View File

@ -238,7 +238,7 @@ static int import_fs(int argc, char *argv[], void *userdata) {
return log_error_errno(r, "Failed to copy directory: %m");
}
r = import_mangle_os_tree(dest, /* userns_fd= */ -EBADF, /* flags= */ 0);
r = import_mangle_os_tree(dest);
if (r < 0)
return r;

View File

@ -199,7 +199,7 @@ static int tar_import_finish(TarImport *i) {
assert_se(d = i->temp_path ?: i->local);
r = import_mangle_os_tree_fd(i->tree_fd, i->userns_fd, i->flags);
r = import_mangle_os_tree(d);
if (r < 0)
return r;

View File

@ -497,7 +497,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
tar_pull_report_progress(i, TAR_FINALIZING);
r = import_mangle_os_tree_fd(i->tree_fd, i->userns_fd, i->flags);
r = import_mangle_os_tree(i->local);
if (r < 0)
goto finish;
@ -523,7 +523,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
tar_pull_report_progress(i, TAR_FINALIZING);
r = import_mangle_os_tree_fd(i->tree_fd, i->userns_fd, i->flags);
r = import_mangle_os_tree(i->temp_path);
if (r < 0)
goto finish;

View File

@ -1762,14 +1762,8 @@ int dhcp4_start_full(Link *link, bool set_ipv6_connectivity) {
int r;
assert(link);
assert(link->manager);
assert(link->network);
/* On stopping/restarting networkd, we may drop IPv6 connectivity (which depends on KeepConfiguration=
* setting). Do not (re)start DHCPv4 client in that case. See issue #39299. */
if (link->manager->state != MANAGER_RUNNING)
return 0;
if (!link->dhcp_client)
return 0;

View File

@ -2225,7 +2225,7 @@ static int link_update_flags(Link *link, sd_netlink_message *message) {
if (!had_carrier && link_has_carrier(link))
r = link_carrier_gained(link);
else if (had_carrier && !link_has_carrier(link))
r = link_carrier_lost(link);
link_carrier_lost(link);
if (r < 0)
return r;

View File

@ -5,16 +5,12 @@
#include "sd-json.h"
#include "alloc-util.h"
#include "chase.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
#include "log.h"
#include "nspawn.h"
#include "machine-bind-user.h"
#include "nspawn-bind-user.h"
#include "strv.h"
#include "user-record.h"
#include "group-record.h"
#include "path-util.h"
@ -71,40 +67,6 @@ static int write_and_symlink(
return 0;
}
static int write_membership(const char *root, const char *user, const char *group) {
int r;
assert(user);
assert(group);
_cleanup_free_ char *membership = strjoin(user, ":", group, ".membership");
if (!membership)
return log_oom();
_cleanup_free_ char *p = path_join("/run/host/userdb/", membership);
if (!p)
return log_oom();
_cleanup_close_ int fd = chase_and_open(
p,
root,
CHASE_PREFIX_ROOT|CHASE_NO_AUTOFS,
O_WRONLY|O_CREAT|O_CLOEXEC,
/* ret_path= */ NULL);
if (fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", p);
r = userns_chown_at(fd, /* fname= */ NULL, /* uid= */ 0, /* gid= */ 0, /* flags= */ 0);
if (r < 0)
return log_error_errno(r, "Failed to adjust access mode of '%s': %m", p);
r = loop_write(fd, "{}\n", SIZE_MAX);
if (r < 0)
return log_error_errno(r, "Failed to write empty JSON object into %s: %m", p);
return 0;
}
int bind_user_setup(const MachineBindUserContext *c, const char *root) {
static const UserRecordLoadFlags strip_flags = /* Removes privileged info */
USER_RECORD_LOAD_MASK_PRIVILEGED|
@ -168,12 +130,6 @@ int bind_user_setup(const MachineBindUserContext *c, const char *root) {
if (r < 0)
return r;
STRV_FOREACH(u, stripped_group->members) {
r = write_membership(root, *u, stripped_group->group_name);
if (r < 0)
return r;
}
/* Third, write out user shadow data. i.e. extract privileged info from user record */
r = user_record_clone(d->payload_user, shadow_flags, &shadow_user);
if (r < 0)
@ -205,12 +161,6 @@ int bind_user_setup(const MachineBindUserContext *c, const char *root) {
0);
if (r < 0)
return r;
STRV_FOREACH(g, stripped_user->member_of) {
r = write_membership(root, stripped_user->user_name, *g);
if (r < 0)
return r;
}
}
return 1;

View File

@ -240,7 +240,6 @@ static MachineCredentialContext arg_credentials = {};
static char **arg_bind_user = NULL;
static char *arg_bind_user_shell = NULL;
static bool arg_bind_user_shell_copy = false;
static char **arg_bind_user_groups = NULL;
static bool arg_suppress_sync = false;
static char *arg_settings_filename = NULL;
static Architecture arg_architecture = _ARCHITECTURE_INVALID;
@ -284,7 +283,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_cpu_set, cpu_set_done);
STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user_shell, freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user_groups, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_settings_filename, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_background, freep);
@ -431,8 +429,6 @@ static int help(void) {
" --bind-user=NAME Bind user from host to container\n"
" --bind-user-shell=BOOL|PATH\n"
" Configure the shell to use for --bind-user= users\n"
" --bind-user-group=GROUP\n"
" Add an auxiliary group to --bind-user= users\n"
"\n%3$sInput/Output:%4$s\n"
" --console=MODE Select how stdin/stdout/stderr and /dev/console are\n"
" set up for the container.\n"
@ -664,7 +660,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_LOAD_CREDENTIAL,
ARG_BIND_USER,
ARG_BIND_USER_SHELL,
ARG_BIND_USER_GROUP,
ARG_SUPPRESS_SYNC,
ARG_IMAGE_POLICY,
ARG_BACKGROUND,
@ -743,7 +738,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "load-credential", required_argument, NULL, ARG_LOAD_CREDENTIAL },
{ "bind-user", required_argument, NULL, ARG_BIND_USER },
{ "bind-user-shell", required_argument, NULL, ARG_BIND_USER_SHELL },
{ "bind-user-group", required_argument, NULL, ARG_BIND_USER_GROUP },
{ "suppress-sync", required_argument, NULL, ARG_SUPPRESS_SYNC },
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
{ "background", required_argument, NULL, ARG_BACKGROUND },
@ -1520,15 +1514,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_BIND_USER_GROUP:
if (!valid_user_group_name(optarg, /* flags= */ 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid bind user auxiliary group name: %s", optarg);
if (strv_extend(&arg_bind_user_groups, optarg) < 0)
return log_oom();
break;
case ARG_SUPPRESS_SYNC:
r = parse_boolean_argument("--suppress-sync=", optarg, &arg_suppress_sync);
if (r < 0)
@ -1704,16 +1689,12 @@ static int verify_arguments(void) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "AmbientCapability= setting is not useful for boot mode.");
}
/* Drop duplicate --bind-user= and --bind-user-group= entries */
/* Drop duplicate --bind-user= entries */
strv_uniq(arg_bind_user);
strv_uniq(arg_bind_user_groups);
if (arg_bind_user_shell && strv_isempty(arg_bind_user))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --bind-user-shell= without --bind-user=");
if (!strv_isempty(arg_bind_user_groups) && strv_isempty(arg_bind_user))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --bind-user-group= without --bind-user=");
r = custom_mount_check_all();
if (r < 0)
return r;
@ -1752,7 +1733,7 @@ static int in_child_chown(void) {
return IN_SET(arg_userns_mode, USER_NAMESPACE_PICK, USER_NAMESPACE_FIXED);
}
int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags) {
static int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags) {
assert(fd >= 0 || fd == AT_FDCWD);
if (!in_child_chown())
@ -1775,9 +1756,6 @@ int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags)
return -EOVERFLOW;
}
if (isempty(fname))
flags |= AT_EMPTY_PATH;
return RET_NERRNO(fchownat(fd, strempty(fname), uid, gid, flags));
}
@ -4042,7 +4020,6 @@ static int outer_child(
arg_bind_user_shell,
arg_bind_user_shell_copy,
"/run/host/home",
arg_bind_user_groups,
&bind_user_context);
if (r < 0)
return r;

View File

@ -3,7 +3,6 @@
#include "shared-forward.h"
int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags);
int userns_lchown(const char *p, uid_t uid, gid_t gid);
int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t uid, gid_t gid);
int make_run_host(const char *root);

View File

@ -94,7 +94,6 @@ static int convert_user(
const char *shell,
bool shell_copy,
const char *home_mount_directory,
char **groups,
UserRecord **ret_converted_user,
GroupRecord **ret_converted_group) {
@ -146,7 +145,6 @@ static int convert_user(
SD_JSON_BUILD_PAIR("homeDirectory", SD_JSON_BUILD_STRING(h)),
SD_JSON_BUILD_PAIR("service", JSON_BUILD_CONST_STRING("io.systemd.NSpawn")),
JSON_BUILD_PAIR_STRING_NON_EMPTY("shell", shell),
SD_JSON_BUILD_PAIR_STRV("memberOf", groups),
SD_JSON_BUILD_PAIR("privileged", SD_JSON_BUILD_OBJECT(
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(u->hashed_password), "hashedPassword", SD_JSON_BUILD_VARIANT(hp)),
SD_JSON_BUILD_PAIR_CONDITION(!!ssh, "sshAuthorizedKeys", SD_JSON_BUILD_VARIANT(ssh))))));
@ -214,7 +212,6 @@ int machine_bind_user_prepare(
const char *bind_user_shell,
bool bind_user_shell_copy,
const char *bind_user_home_mount_directory,
char **bind_user_groups,
MachineBindUserContext **ret) {
_cleanup_(machine_bind_user_context_freep) MachineBindUserContext *c = NULL;
@ -291,7 +288,6 @@ int machine_bind_user_prepare(
bind_user_shell,
bind_user_shell_copy,
bind_user_home_mount_directory,
bind_user_groups,
&cu, &cg);
if (r < 0)
return r;

View File

@ -28,5 +28,4 @@ int machine_bind_user_prepare(
const char *bind_user_shell,
bool bind_user_shell_copy,
const char *bind_user_home_mount_directory,
char **bind_user_groups,
MachineBindUserContext **ret);

View File

@ -18,7 +18,6 @@
#include "format-table.h"
#include "format-util.h"
#include "fs-util.h"
#include "io-util.h"
#include "log.h"
#include "main-func.h"
#include "mkdir.h"
@ -1197,31 +1196,6 @@ static int ssh_authorized_keys(int argc, char *argv[], void *userdata) {
return r;
}
static int write_membership(int dir_fd, const char *dir, const char *user, const char *group) {
int r;
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(dir);
assert(user);
assert(group);
_cleanup_free_ char *membership = strjoin(user, ":", group, ".membership");
if (!membership)
return log_oom();
_cleanup_close_ int fd = openat(dir_fd, membership, O_WRONLY|O_CREAT|O_CLOEXEC, 0644);
if (fd < 0)
return log_error_errno(errno, "Failed to create %s/%s: %m", dir, membership);
r = loop_write(fd, "{}\n", SIZE_MAX);
if (r < 0)
return log_error_errno(r, "Failed to write empty JSON object into %s/%s: %m", dir, membership);
log_info("Installed %s/%s from credential.", dir, membership);
return 0;
}
static int load_credential_one(
int credential_dir_fd,
const char *name,
@ -1456,15 +1430,27 @@ static int load_credential_one(
if (ur)
STRV_FOREACH(g, ur->member_of) {
r = write_membership(*userdb_dir_fd, userdb_dir, ur->user_name, *g);
if (r < 0)
return r;
_cleanup_free_ char *membership = strjoin(ur->user_name, ":", *g);
if (!membership)
return log_oom();
_cleanup_close_ int fd = openat(*userdb_dir_fd, membership, O_WRONLY|O_CREAT|O_CLOEXEC, 0644);
if (fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", membership);
log_info("Installed %s/%s from credential.", userdb_dir, membership);
}
else
STRV_FOREACH(u, gr->members) {
r = write_membership(*userdb_dir_fd, userdb_dir, *u, gr->group_name);
if (r < 0)
return r;
_cleanup_free_ char *membership = strjoin(*u, ":", gr->group_name);
if (!membership)
return log_oom();
_cleanup_close_ int fd = openat(*userdb_dir_fd, membership, O_WRONLY|O_CREAT|O_CLOEXEC, 0644);
if (fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", membership);
log_info("Installed %s/%s from credential.", userdb_dir, membership);
}
if (ur && user_record_disposition(ur) == USER_REGULAR) {

View File

@ -143,7 +143,6 @@ static bool arg_notify_ready = true;
static char **arg_bind_user = NULL;
static char *arg_bind_user_shell = NULL;
static bool arg_bind_user_shell_copy = false;
static char **arg_bind_user_groups = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_directory, freep);
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
@ -165,7 +164,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_tpm_state_path, freep);
STATIC_DESTRUCTOR_REGISTER(arg_property, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user_shell, freep);
STATIC_DESTRUCTOR_REGISTER(arg_bind_user_groups, strv_freep);
static int help(void) {
_cleanup_free_ char *link = NULL;
@ -229,8 +227,6 @@ static int help(void) {
" --bind-user=NAME Bind user from host to virtual machine\n"
" --bind-user-shell=BOOL|PATH\n"
" Configure the shell to use for --bind-user= users\n"
" --bind-user-group=GROUP\n"
" Add an auxiliary group to --bind-user= users\n"
"\n%3$sIntegration:%4$s\n"
" --forward-journal=FILE|DIR\n"
" Forward the VM's journal to the host\n"
@ -307,7 +303,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NOTIFY_READY,
ARG_BIND_USER,
ARG_BIND_USER_SHELL,
ARG_BIND_USER_GROUP,
};
static const struct option options[] = {
@ -359,7 +354,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "notify-ready", required_argument, NULL, ARG_NOTIFY_READY },
{ "bind-user", required_argument, NULL, ARG_BIND_USER },
{ "bind-user-shell", required_argument, NULL, ARG_BIND_USER_SHELL },
{ "bind-user-group", required_argument, NULL, ARG_BIND_USER_GROUP },
{}
};
@ -721,15 +715,6 @@ static int parse_argv(int argc, char *argv[]) {
break;
}
case ARG_BIND_USER_GROUP:
if (!valid_user_group_name(optarg, /* flags= */ 0))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid bind user auxiliary group name: %s", optarg);
if (strv_extend(&arg_bind_user_groups, optarg) < 0)
return log_oom();
break;
case '?':
return -EINVAL;
@ -737,16 +722,12 @@ static int parse_argv(int argc, char *argv[]) {
assert_not_reached();
}
/* Drop duplicate --bind-user= and --bind-user-group= entries */
/* Drop duplicate --bind-user= entries */
strv_uniq(arg_bind_user);
strv_uniq(arg_bind_user_groups);
if (arg_bind_user_shell && strv_isempty(arg_bind_user))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --bind-user-shell= without --bind-user=");
if (!strv_isempty(arg_bind_user_groups) && strv_isempty(arg_bind_user))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot use --bind-user-group= without --bind-user=");
if (argc > optind) {
arg_kernel_cmdline_extra = strv_copy(argv + optind);
if (!arg_kernel_cmdline_extra)
@ -1859,7 +1840,6 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
arg_bind_user_shell,
arg_bind_user_shell_copy,
"/run/vmhost/home",
arg_bind_user_groups,
&bind_user_context);
if (r < 0)
return r;

View File

@ -162,7 +162,7 @@ rm -f /tmp/core.{output,redirected}
# Unprivileged stuff
# Related issue: https://github.com/systemd/systemd/issues/26912
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" -E SYSTEMD_PAGER --)
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --)
# Trigger a couple of coredumps as an unprivileged user
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"