mirror of
https://github.com/systemd/systemd.git
synced 2024-11-30 22:03:41 +08:00
Merge pull request #34020 from YHNdnzj/cred-no-mountover
core/dbus-service: refuse bind mounting over /run/credentials/
This commit is contained in:
commit
871b0ee995
@ -13,6 +13,7 @@
|
||||
#include "dbus-service.h"
|
||||
#include "dbus-util.h"
|
||||
#include "execute.h"
|
||||
#include "exec-credential.h"
|
||||
#include "exit-status.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -129,33 +130,36 @@ static int property_get_exit_status_set(
|
||||
}
|
||||
|
||||
static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_bus_error *error, bool is_image) {
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
const char *dest, *src, *propagate_directory;
|
||||
int read_only, make_file_or_directory;
|
||||
Unit *u = ASSERT_PTR(userdata);
|
||||
ExecContext *c;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
if (!MANAGER_IS_SYSTEM(u->manager))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Adding bind mounts at runtime is only supported for system managers.");
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Adding bind mounts at runtime is only supported by system manager");
|
||||
|
||||
if (u->type != UNIT_SERVICE)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not of type .service");
|
||||
|
||||
r = mac_selinux_unit_access_check(u, message, "start", error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
|
||||
const char *src, *dest;
|
||||
int read_only, make_file_or_directory;
|
||||
|
||||
r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_file_or_directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(src) || !path_is_normalized(src))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized");
|
||||
|
||||
if (!is_image && isempty(dest))
|
||||
dest = src;
|
||||
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized");
|
||||
|
||||
if (is_image) {
|
||||
r = bus_read_mount_options(message, error, &options, NULL, "");
|
||||
@ -174,26 +178,28 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
||||
if (r == 0)
|
||||
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
|
||||
|
||||
if (u->type != UNIT_SERVICE)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not of type .service");
|
||||
const PidRef *unit_pid = unit_main_pid(u);
|
||||
if (!pidref_is_set(unit_pid) || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
return sd_bus_error_set(error, BUS_ERROR_UNIT_INACTIVE, "Unit is not running");
|
||||
|
||||
/* If it would be dropped at startup time, return an error. The context should always be available, but
|
||||
* there's an assert in exec_needs_mount_namespace, so double-check just in case. */
|
||||
c = unit_get_exec_context(u);
|
||||
/* The context should always be available, but there's an assert in exec_needs_mount_namespace,
|
||||
* so double-check just in case. */
|
||||
ExecContext *c = unit_get_exec_context(u);
|
||||
if (!c)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot access unit execution context");
|
||||
if (path_startswith_strv(dest, c->inaccessible_paths))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s is not accessible to this unit", dest);
|
||||
return -ENXIO;
|
||||
|
||||
/* Ensure that the unit was started in a private mount namespace */
|
||||
if (!exec_needs_mount_namespace(c, NULL, unit_get_exec_runtime(u)))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit not running in private mount namespace, cannot activate bind mount");
|
||||
|
||||
PidRef* unit_pid = unit_main_pid(u);
|
||||
if (!pidref_is_set(unit_pid) || !UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u)))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
|
||||
if (mount_point_is_credentials(u->manager->prefix[EXEC_DIRECTORY_RUNTIME], dest))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Refusing to bind mount over credential mounts");
|
||||
|
||||
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
|
||||
/* If it would be dropped at startup time, return an error. */
|
||||
if (path_startswith_strv(dest, c->inaccessible_paths))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "%s is not accessible to this unit", dest);
|
||||
|
||||
const char *propagate_directory = strjoina("/run/systemd/propagate/", u->id);
|
||||
if (is_image)
|
||||
r = mount_image_in_namespace(
|
||||
unit_pid,
|
||||
@ -213,7 +219,7 @@ static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_
|
||||
read_only,
|
||||
make_file_or_directory);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in unit's namespace: %m", src, dest);
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to mount '%s' on '%s' in unit's namespace: %m", src, dest);
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
@ -242,6 +242,19 @@ bool exec_context_has_encrypted_credentials(const ExecContext *c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mount_point_is_credentials(const char *runtime_prefix, const char *path) {
|
||||
const char *e;
|
||||
|
||||
assert(runtime_prefix);
|
||||
assert(path);
|
||||
|
||||
e = path_startswith(path, runtime_prefix);
|
||||
if (!e)
|
||||
return false;
|
||||
|
||||
return path_startswith(e, "credentials");
|
||||
}
|
||||
|
||||
static int get_credential_directory(
|
||||
const char *runtime_prefix,
|
||||
const char *unit,
|
||||
|
@ -67,3 +67,5 @@ int exec_setup_credentials(
|
||||
const char *unit,
|
||||
uid_t uid,
|
||||
gid_t gid);
|
||||
|
||||
bool mount_point_is_credentials(const char *runtime_prefix, const char *path);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "dbus-mount.h"
|
||||
#include "dbus-unit.h"
|
||||
#include "device.h"
|
||||
#include "exec-credential.h"
|
||||
#include "exit-status.h"
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
@ -425,22 +426,6 @@ static bool mount_is_extrinsic(Unit *u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mount_point_is_credentials(Manager *manager, const char *path) {
|
||||
const char *e;
|
||||
|
||||
assert(manager);
|
||||
assert(path);
|
||||
|
||||
/* Returns true if this is a credentials mount. We don't want to generate mount units for them,
|
||||
* since their lifetime is strictly bound to services. */
|
||||
|
||||
e = path_startswith(path, manager->prefix[EXEC_DIRECTORY_RUNTIME]);
|
||||
if (!e)
|
||||
return false;
|
||||
|
||||
return !isempty(path_startswith(e, "credentials"));
|
||||
}
|
||||
|
||||
static int mount_add_default_ordering_dependencies(Mount *m, MountParameters *p, UnitDependencyMask mask) {
|
||||
const char *after, *before, *e;
|
||||
int r;
|
||||
@ -581,7 +566,7 @@ static int mount_verify(Mount *m) {
|
||||
return log_unit_error_errno(UNIT(m), SYNTHETIC_ERRNO(ENOEXEC),
|
||||
"Cannot create mount unit for API file system '%s'. Refusing.", m->where);
|
||||
|
||||
if (mount_point_is_credentials(UNIT(m)->manager, m->where))
|
||||
if (mount_point_is_credentials(UNIT(m)->manager->prefix[EXEC_DIRECTORY_RUNTIME], m->where))
|
||||
return log_unit_error_errno(UNIT(m), SYNTHETIC_ERRNO(ENOEXEC),
|
||||
"Cannot create mount unit for credential mount '%s'. Refusing.", m->where);
|
||||
|
||||
@ -1830,8 +1815,10 @@ static int mount_setup_unit(
|
||||
assert(fstype);
|
||||
|
||||
/* Ignore API and credential mount points. They should never be referenced in dependencies ever.
|
||||
* Also check the comment for mount_point_is_credentials(). */
|
||||
if (mount_point_is_api(where) || mount_point_ignore(where) || mount_point_is_credentials(m, where))
|
||||
* Furthermore, the lifetime of credential mounts is strictly bound to the owning services,
|
||||
* so mount units make little sense for them. */
|
||||
if (mount_point_is_api(where) || mount_point_ignore(where) ||
|
||||
mount_point_is_credentials(m->prefix[EXEC_DIRECTORY_RUNTIME], where))
|
||||
return 0;
|
||||
|
||||
if (streq(fstype, "autofs"))
|
||||
|
Loading…
Reference in New Issue
Block a user