return r;
}
-int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group) {
+int dynamic_creds_make(Manager *m, const char *user, const char *group, DynamicCreds **ret) {
+ _cleanup_(dynamic_creds_unrefp) DynamicCreds *creds = NULL;
bool acquired = false;
int r;
- assert(creds);
assert(m);
+ assert(ret);
+
+ if (!user && !group) {
+ *ret = NULL;
+ return 0;
+ }
+
+ creds = new0(DynamicCreds, 1);
+ if (!creds)
+ return -ENOMEM;
/* A DynamicUser object encapsulates an allocation of both a UID and a GID for a specific name. However, some
* services use different user and groups. For cases like that there's DynamicCreds containing a pair of user
* and group. This call allocates a pair. */
- if (!creds->user && user) {
+ if (user) {
r = dynamic_user_acquire(m, user, &creds->user);
if (r < 0)
return r;
acquired = true;
}
- if (!creds->group) {
-
- if (creds->user && (!group || streq_ptr(user, group)))
- creds->group = dynamic_user_ref(creds->user);
- else if (group) {
- r = dynamic_user_acquire(m, group, &creds->group);
- if (r < 0) {
- if (acquired)
- creds->user = dynamic_user_unref(creds->user);
- return r;
- }
+ if (creds->user && (!group || streq_ptr(user, group)))
+ creds->group = dynamic_user_ref(creds->user);
+ else if (group) {
+ r = dynamic_user_acquire(m, group, &creds->group);
+ if (r < 0) {
+ if (acquired)
+ creds->user = dynamic_user_unref(creds->user);
+ return r;
}
}
+ *ret = TAKE_PTR(creds);
+
return 0;
}
return 0;
}
-void dynamic_creds_unref(DynamicCreds *creds) {
- assert(creds);
+DynamicCreds* dynamic_creds_unref(DynamicCreds *creds) {
+ if (!creds)
+ return NULL;
creds->user = dynamic_user_unref(creds->user);
creds->group = dynamic_user_unref(creds->group);
+
+ return mfree(creds);
}
-void dynamic_creds_destroy(DynamicCreds *creds) {
- assert(creds);
+DynamicCreds* dynamic_creds_destroy(DynamicCreds *creds) {
+ if (!creds)
+ return NULL;
creds->user = dynamic_user_destroy(creds->user);
creds->group = dynamic_user_destroy(creds->group);
+
+ return mfree(creds);
}
int dynamic_user_lookup_uid(Manager *m, uid_t uid, char **ret);
int dynamic_user_lookup_name(Manager *m, const char *name, uid_t *ret);
-int dynamic_creds_acquire(DynamicCreds *creds, Manager *m, const char *user, const char *group);
+int dynamic_creds_make(Manager *m, const char *user, const char *group, DynamicCreds **ret);
int dynamic_creds_realize(DynamicCreds *creds, char **suggested_paths, uid_t *uid, gid_t *gid);
-void dynamic_creds_unref(DynamicCreds *creds);
-void dynamic_creds_destroy(DynamicCreds *creds);
+DynamicCreds *dynamic_creds_unref(DynamicCreds *creds);
+DynamicCreds *dynamic_creds_destroy(DynamicCreds *creds);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(DynamicCreds*, dynamic_creds_destroy);
static int close_remaining_fds(
const ExecParameters *params,
const ExecRuntime *runtime,
- const DynamicCreds *dcreds,
int user_lookup_fd,
int socket_fd,
const int *fds, size_t n_fds) {
append_socket_pair(dont_close, &n_dont_close, runtime->shared->ipcns_storage_socket);
}
- if (dcreds) {
- if (dcreds->user)
- append_socket_pair(dont_close, &n_dont_close, dcreds->user->storage_socket);
- if (dcreds->group)
- append_socket_pair(dont_close, &n_dont_close, dcreds->group->storage_socket);
+ if (runtime && runtime->dynamic_creds) {
+ if (runtime->dynamic_creds->user)
+ append_socket_pair(dont_close, &n_dont_close, runtime->dynamic_creds->user->storage_socket);
+ if (runtime->dynamic_creds->group)
+ append_socket_pair(dont_close, &n_dont_close, runtime->dynamic_creds->group->storage_socket);
}
if (user_lookup_fd >= 0)
const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime,
- DynamicCreds *dcreds,
const CGroupContext *cgroup_context,
int socket_fd,
const int named_iofds[static 3],
}
#endif
- r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, keep_fds, n_keep_fds);
+ r = close_remaining_fds(params, runtime, user_lookup_fd, socket_fd, keep_fds, n_keep_fds);
if (r < 0) {
*exit_status = EXIT_FDS;
return log_unit_error_errno(unit, r, "Failed to close unwanted file descriptors: %m");
return log_unit_error_errno(unit, errno, "Failed to update environment: %m");
}
- if (context->dynamic_user && dcreds) {
+ if (context->dynamic_user && runtime && runtime->dynamic_creds) {
_cleanup_strv_free_ char **suggested_paths = NULL;
/* On top of that, make sure we bypass our own NSS module nss-systemd comprehensively for any NSS
return log_oom();
}
- r = dynamic_creds_realize(dcreds, suggested_paths, &uid, &gid);
+ r = dynamic_creds_realize(runtime->dynamic_creds, suggested_paths, &uid, &gid);
if (r < 0) {
*exit_status = EXIT_USER;
if (r == -EILSEQ)
return log_unit_error_errno(unit, SYNTHETIC_ERRNO(ESRCH), "GID validation failed for \""GID_FMT"\"", gid);
}
- if (dcreds->user)
- username = dcreds->user->name;
+ if (runtime->dynamic_creds->user)
+ username = runtime->dynamic_creds->user->name;
} else {
r = get_fixed_user(context, &username, &uid, &gid, &home, &shell);
const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime,
- DynamicCreds *dcreds,
const CGroupContext *cgroup_context,
pid_t *ret) {
context,
params,
runtime,
- dcreds,
cgroup_context,
socket_fd,
named_iofds,
}
}
-int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret) {
+int exec_runtime_make(ExecSharedRuntime *shared, DynamicCreds *creds, ExecRuntime **ret) {
_cleanup_(exec_runtime_freep) ExecRuntime *rt = NULL;
assert(ret);
- if (!shared) {
+ if (!shared && !creds) {
*ret = NULL;
return 0;
}
*rt = (ExecRuntime) {
.shared = shared,
+ .dynamic_creds = creds,
};
*ret = TAKE_PTR(rt);
return NULL;
exec_shared_runtime_unref(rt->shared);
+ dynamic_creds_unref(rt->dynamic_creds);
return mfree(rt);
}
return NULL;
rt->shared = exec_shared_runtime_destroy(rt->shared);
+ rt->dynamic_creds = dynamic_creds_destroy(rt->dynamic_creds);
return exec_runtime_free(rt);
}
typedef struct ExecCommand ExecCommand;
typedef struct ExecContext ExecContext;
typedef struct ExecSharedRuntime ExecSharedRuntime;
+typedef struct DynamicCreds DynamicCreds;
typedef struct ExecRuntime ExecRuntime;
typedef struct ExecParameters ExecParameters;
typedef struct Manager Manager;
struct ExecRuntime {
ExecSharedRuntime *shared;
+ DynamicCreds *dynamic_creds;
};
typedef enum ExecDirectoryType {
const ExecContext *context,
const ExecParameters *exec_params,
ExecRuntime *runtime,
- DynamicCreds *dynamic_creds,
const CGroupContext *cgroup_context,
pid_t *ret);
int exec_shared_runtime_deserialize_one(Manager *m, const char *value, FDSet *fds);
void exec_shared_runtime_vacuum(Manager *m);
-int exec_runtime_make(ExecSharedRuntime *shared, ExecRuntime **ret);
+int exec_runtime_make(ExecSharedRuntime *shared, DynamicCreds *creds, ExecRuntime **ret);
ExecRuntime* exec_runtime_free(ExecRuntime *rt);
DEFINE_TRIVIAL_CLEANUP_FUNC(ExecRuntime*, exec_runtime_free);
ExecRuntime* exec_runtime_destroy(ExecRuntime *rt);
exec_command_done_array(m->exec_command, _MOUNT_EXEC_COMMAND_MAX);
m->control_command = NULL;
- dynamic_creds_unref(&m->dynamic_creds);
-
mount_unwatch_control_pid(m);
m->timer_event_source = sd_event_source_disable_unref(m->timer_event_source);
return r;
}
- if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED)) {
- (void) unit_setup_dynamic_creds(u);
+ if (!IN_SET(m->deserialized_state, MOUNT_DEAD, MOUNT_FAILED))
(void) unit_setup_exec_runtime(u);
- }
mount_set_state(m, m->deserialized_state);
return 0;
&m->exec_context,
&exec_params,
m->exec_runtime,
- &m->dynamic_creds,
&m->cgroup_context,
&pid);
if (r < 0)
unit_unref_uid_gid(UNIT(m), true);
- dynamic_creds_destroy(&m->dynamic_creds);
-
/* Any dependencies based on /proc/self/mountinfo are now stale. Let's re-generate dependencies from
* .mount unit. */
(void) mount_add_non_exec_dependencies(m);
.cgroup_context_offset = offsetof(Mount, cgroup_context),
.kill_context_offset = offsetof(Mount, kill_context),
.exec_runtime_offset = offsetof(Mount, exec_runtime),
- .dynamic_creds_offset = offsetof(Mount, dynamic_creds),
.sections =
"Unit\0"
CGroupContext cgroup_context;
ExecRuntime *exec_runtime;
- DynamicCreds dynamic_creds;
MountState state, deserialized_state;
s->control_command = NULL;
s->main_command = NULL;
- dynamic_creds_unref(&s->dynamic_creds);
-
exit_status_set_free(&s->restart_prevent_status);
exit_status_set_free(&s->restart_force_status);
exit_status_set_free(&s->success_status);
if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART, SERVICE_CLEANING)) {
(void) unit_enqueue_rewatch_pids(u);
- (void) unit_setup_dynamic_creds(u);
(void) unit_setup_exec_runtime(u);
}
&s->exec_context,
&exec_params,
s->exec_runtime,
- &s->dynamic_creds,
&s->cgroup_context,
&pid);
if (r < 0)
/* Get rid of the IPC bits of the user */
unit_unref_uid_gid(UNIT(s), true);
- /* Release the user, and destroy it if we are the only remaining owner */
- dynamic_creds_destroy(&s->dynamic_creds);
-
/* Try to delete the pid file. At this point it will be
* out-of-date, and some software might be confused by it, so
* let's remove it. */
.cgroup_context_offset = offsetof(Service, cgroup_context),
.kill_context_offset = offsetof(Service, kill_context),
.exec_runtime_offset = offsetof(Service, exec_runtime),
- .dynamic_creds_offset = offsetof(Service, dynamic_creds),
.sections =
"Unit\0"
/* Runtime data of the execution context */
ExecRuntime *exec_runtime;
- DynamicCreds dynamic_creds;
pid_t main_pid, control_pid;
exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
s->control_command = NULL;
- dynamic_creds_unref(&s->dynamic_creds);
-
socket_unwatch_control_pid(s);
unit_ref_unset(&s->service);
return r;
}
- if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING)) {
- (void) unit_setup_dynamic_creds(u);
+ if (!IN_SET(s->deserialized_state, SOCKET_DEAD, SOCKET_FAILED, SOCKET_CLEANING))
(void) unit_setup_exec_runtime(u);
- }
socket_set_state(s, s->deserialized_state);
return 0;
&s->exec_context,
&exec_params,
s->exec_runtime,
- &s->dynamic_creds,
&s->cgroup_context,
&pid);
if (r < 0)
unit_destroy_runtime_data(UNIT(s), &s->exec_context);
unit_unref_uid_gid(UNIT(s), true);
-
- dynamic_creds_destroy(&s->dynamic_creds);
}
static void socket_enter_signal(Socket *s, SocketState state, SocketResult f);
.cgroup_context_offset = offsetof(Socket, cgroup_context),
.kill_context_offset = offsetof(Socket, kill_context),
.exec_runtime_offset = offsetof(Socket, exec_runtime),
- .dynamic_creds_offset = offsetof(Socket, dynamic_creds),
.sections =
"Unit\0"
CGroupContext cgroup_context;
ExecRuntime *exec_runtime;
- DynamicCreds dynamic_creds;
/* For Accept=no sockets refers to the one service we'll
* activate. For Accept=yes sockets is either NULL, or filled
exec_command_done_array(s->exec_command, _SWAP_EXEC_COMMAND_MAX);
s->control_command = NULL;
- dynamic_creds_unref(&s->dynamic_creds);
-
swap_unwatch_control_pid(s);
s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source);
return r;
}
- if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED)) {
- (void) unit_setup_dynamic_creds(u);
+ if (!IN_SET(new_state, SWAP_DEAD, SWAP_FAILED))
(void) unit_setup_exec_runtime(u);
- }
swap_set_state(s, new_state);
return 0;
&s->exec_context,
&exec_params,
s->exec_runtime,
- &s->dynamic_creds,
&s->cgroup_context,
&pid);
if (r < 0)
unit_destroy_runtime_data(UNIT(s), &s->exec_context);
unit_unref_uid_gid(UNIT(s), true);
-
- dynamic_creds_destroy(&s->dynamic_creds);
}
static void swap_enter_active(Swap *s, SwapResult f) {
.cgroup_context_offset = offsetof(Swap, cgroup_context),
.kill_context_offset = offsetof(Swap, kill_context),
.exec_runtime_offset = offsetof(Swap, exec_runtime),
- .dynamic_creds_offset = offsetof(Swap, dynamic_creds),
.sections =
"Unit\0"
CGroupContext cgroup_context;
ExecRuntime *exec_runtime;
- DynamicCreds dynamic_creds;
SwapState state, deserialized_state;
int unit_setup_exec_runtime(Unit *u) {
_cleanup_(exec_shared_runtime_unrefp) ExecSharedRuntime *esr = NULL;
+ _cleanup_(dynamic_creds_unrefp) DynamicCreds *dcreds = NULL;
ExecRuntime **rt;
+ ExecContext *ec;
size_t offset;
Unit *other;
int r;
if (*rt)
return 0;
+ ec = unit_get_exec_context(u);
+ assert(ec);
+
/* Try to get it from somebody else */
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_JOINS_NAMESPACE_OF) {
r = exec_shared_runtime_acquire(u->manager, NULL, other->id, false, &esr);
}
if (!esr) {
- r = exec_shared_runtime_acquire(u->manager, unit_get_exec_context(u), u->id, true, &esr);
+ r = exec_shared_runtime_acquire(u->manager, ec, u->id, true, &esr);
if (r < 0)
return r;
}
- r = exec_runtime_make(esr, rt);
+ if (ec->dynamic_user) {
+ r = dynamic_creds_make(u->manager, ec->user, ec->group, &dcreds);
+ if (r < 0)
+ return r;
+ }
+
+ r = exec_runtime_make(esr, dcreds, rt);
if (r < 0)
return r;
TAKE_PTR(esr);
+ TAKE_PTR(dcreds);
return r;
}
-int unit_setup_dynamic_creds(Unit *u) {
- ExecContext *ec;
- DynamicCreds *dcreds;
- size_t offset;
-
- assert(u);
-
- offset = UNIT_VTABLE(u)->dynamic_creds_offset;
- assert(offset > 0);
- dcreds = (DynamicCreds*) ((uint8_t*) u + offset);
-
- ec = unit_get_exec_context(u);
- assert(ec);
-
- if (!ec->dynamic_user)
- return 0;
-
- return dynamic_creds_acquire(dcreds, u->manager, ec->user, ec->group);
-}
-
bool unit_type_supported(UnitType t) {
static int8_t cache[_UNIT_TYPE_MAX] = {}; /* -1: disabled, 1: enabled: 0: don't know */
int r;
if (r < 0)
return r;
- r = unit_setup_dynamic_creds(u);
- if (r < 0)
- return r;
-
return 0;
}
* that */
size_t exec_runtime_offset;
- /* If greater than 0, the offset into the object where the pointer to DynamicCreds is found, if the unit type
- * has that. */
- size_t dynamic_creds_offset;
-
/* The name of the configuration file section with the private settings of this unit */
const char *private_section;
ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_;
int unit_setup_exec_runtime(Unit *u);
-int unit_setup_dynamic_creds(Unit *u);
char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
char* unit_concat_strv(char **l, UnitWriteFlags flags);