Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion man/systemd.socket.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
socket passing (i.e. sockets passed in via standard input and output, using
<varname>StandardInput=socket</varname> in the service file).</para>

<para>All network sockets allocated through <filename>.socket</filename> units are allocated in the host's network
<para>By default, network sockets allocated through <filename>.socket</filename> units are allocated in the host's network
namespace (see <citerefentry
project='man-pages'><refentrytitle>network_namespaces</refentrytitle><manvolnum>7</manvolnum></citerefentry>). This
does not mean however that the service activated by a configured socket unit has to be part of the host's network
Expand All @@ -101,6 +101,11 @@
the host's network namespace is only permitted through the activation sockets passed in while all sockets allocated
from the service code itself will be associated with the service's own namespace, and thus possibly subject to a
restrictive configuration.</para>

<para>Alternatively, it is possible to run a <filename>.socket</filename> unit in another network namespace
by setting <option>PrivateNetwork=yes</option> in combination with <varname>JoinsNamespaceOf=</varname>, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> and
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details.</para>
</refsect1>

<refsect1>
Expand Down
35 changes: 15 additions & 20 deletions src/basic/process-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,34 +389,30 @@ int container_get_leader(const char *machine, pid_t *pid) {
}

int pid_is_kernel_thread(pid_t pid) {
_cleanup_free_ char *line = NULL;
unsigned long long flags;
size_t l, i;
const char *p;
char *q;
int r;

if (IN_SET(pid, 0, 1) || pid == getpid_cached()) /* pid 1, and we ourselves certainly aren't a kernel thread */
return 0;
if (!pid_is_valid(pid))
return -EINVAL;

p = procfs_file_alloca(pid, "stat");
const char *p = procfs_file_alloca(pid, "stat");
_cleanup_free_ char *line = NULL;
r = read_one_line_file(p, &line);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;

/* Skip past the comm field */
q = strrchr(line, ')');
char *q = strrchr(line, ')');
if (!q)
return -EINVAL;
q++;

/* Skip 6 fields to reach the flags field */
for (i = 0; i < 6; i++) {
l = strspn(q, WHITESPACE);
for (size_t i = 0; i < 6; i++) {
size_t l = strspn(q, WHITESPACE);
if (l < 1)
return -EINVAL;
q += l;
Expand All @@ -428,7 +424,7 @@ int pid_is_kernel_thread(pid_t pid) {
}

/* Skip preceding whitespace */
l = strspn(q, WHITESPACE);
size_t l = strspn(q, WHITESPACE);
if (l < 1)
return -EINVAL;
q += l;
Expand All @@ -439,6 +435,7 @@ int pid_is_kernel_thread(pid_t pid) {
return -EINVAL;
q[l] = 0;

unsigned long long flags;
r = safe_atollu(q, &flags);
if (r < 0)
return r;
Expand Down Expand Up @@ -883,25 +880,23 @@ int pidref_wait_for_terminate_and_check(const char *name, PidRef *pidref, WaitFl
siginfo_t status;
r = pidref_wait_for_terminate(pidref, &status);
if (r < 0)
return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
return log_full_errno(prio, r, "Failed to wait for '%s': %m", strna(name));

if (status.si_code == CLD_EXITED) {
if (status.si_status != EXIT_SUCCESS)
log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
"%s failed with exit status %i.", strna(name), status.si_status);
"'%s' failed with exit status %i.", strna(name), status.si_status);
else
log_debug("%s succeeded.", name);
log_debug("'%s' succeeded.", name);

return status.si_status;

} else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {

log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
return -EPROTO;
}
} else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED))
return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
"'%s' terminated by signal %s.", strna(name), signal_to_string(status.si_status));

log_full(prio, "%s failed due to unknown reason.", strna(name));
return -EPROTO;
return log_full_errno(prio, SYNTHETIC_ERRNO(EPROTO),
"'%s' failed due to unknown reason.", strna(name));
}

int kill_and_sigcont(pid_t pid, int sig) {
Expand Down
8 changes: 4 additions & 4 deletions src/core/automount.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,10 +804,6 @@ static int automount_start(Unit *u) {
if (path_is_mount_point(a->where) > 0)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EEXIST), "Path %s is already a mount point, refusing start.", a->where);

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
Expand Down Expand Up @@ -1047,6 +1043,10 @@ static int automount_test_startable(Unit *u) {
Automount *a = ASSERT_PTR(AUTOMOUNT(u));
int r;

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_test_start_limit(u);
if (r < 0) {
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
Expand Down
8 changes: 4 additions & 4 deletions src/core/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,10 +632,6 @@ static int path_start(Unit *u) {

assert(IN_SET(p->state, PATH_DEAD, PATH_FAILED));

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
Expand Down Expand Up @@ -902,6 +898,10 @@ static int path_test_startable(Unit *u) {
Path *p = ASSERT_PTR(PATH(u));
int r;

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_test_start_limit(u);
if (r < 0) {
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
Expand Down
28 changes: 14 additions & 14 deletions src/core/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -2623,20 +2623,6 @@ static int socket_start(Unit *u) {
Socket *s = ASSERT_PTR(SOCKET(u));
int r;

/* Cannot run this without the service being around */
if (UNIT_ISSET(s->service)) {
Service *service = ASSERT_PTR(SERVICE(UNIT_DEREF(s->service)));

if (UNIT(service)->load_state != UNIT_LOADED)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOENT),
"Socket service %s not loaded, refusing.", UNIT(service)->id);

/* If the service is already active we cannot start the socket */
if (SOCKET_SERVICE_IS_ACTIVE(service, /* allow_finalize= */ false))
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EBUSY),
"Socket service %s already active, refusing.", UNIT(service)->id);
}

assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED));

r = unit_acquire_invocation_id(u);
Expand Down Expand Up @@ -3642,6 +3628,20 @@ static int socket_test_startable(Unit *u) {
SOCKET_START_POST))
return false;

/* Cannot run this without the service being around */
if (UNIT_ISSET(s->service)) {
Service *service = ASSERT_PTR(SERVICE(UNIT_DEREF(s->service)));

if (UNIT(service)->load_state != UNIT_LOADED)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOENT),
"Socket service %s not loaded, refusing.", UNIT(service)->id);

/* If the service is already active we cannot start the socket */
if (SOCKET_SERVICE_IS_ACTIVE(service, /* allow_finalize= */ false))
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EBUSY),
"Socket service %s already active, refusing.", UNIT(service)->id);
}

r = unit_test_start_limit(u);
if (r < 0) {
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
Expand Down
8 changes: 4 additions & 4 deletions src/core/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,10 +668,6 @@ static int timer_start(Unit *u) {

assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED));

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_acquire_invocation_id(u);
if (r < 0)
return r;
Expand Down Expand Up @@ -917,6 +913,10 @@ static int timer_test_startable(Unit *u) {
Timer *t = ASSERT_PTR(TIMER(u));
int r;

r = unit_test_trigger_loaded(u);
if (r < 0)
return r;

r = unit_test_start_limit(u);
if (r < 0) {
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
Expand Down
4 changes: 2 additions & 2 deletions src/login/inhibit.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,11 +368,11 @@ static int run(int argc, char *argv[]) {
/* Child */
execvp(arguments[0], arguments);
log_open();
log_error_errno(errno, "Failed to execute %s: %m", argv[optind]);
log_error_errno(errno, "Failed to execute '%s': %m", arguments[0]);
_exit(EXIT_FAILURE);
}

return pidref_wait_for_terminate_and_check(argv[optind], &pidref, WAIT_LOG);
return pidref_wait_for_terminate_and_check(argv[optind], &pidref, WAIT_LOG_ABNORMAL);
}
}

Expand Down
19 changes: 16 additions & 3 deletions src/nss-systemd/nss-systemd.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ static const struct group root_group = {
static const struct sgrp root_sgrp = {
.sg_namp = (char*) "root",
.sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
.sg_adm = (char*[]) { NULL },
.sg_mem = (char*[]) { NULL },
};

static const struct group nobody_group = {
Expand All @@ -87,6 +89,8 @@ static const struct group nobody_group = {
static const struct sgrp nobody_sgrp = {
.sg_namp = (char*) NOBODY_GROUP_NAME,
.sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
.sg_adm = (char*[]) { NULL },
.sg_mem = (char*[]) { NULL },
};

typedef struct GetentData {
Expand Down Expand Up @@ -257,12 +261,18 @@ static enum nss_status copy_synthesized_sgrp(
assert(src);
assert(src->sg_namp);
assert(src->sg_passwd);
assert(src->sg_adm);
assert(!*src->sg_adm); /* Our synthesized records' sg_adm is always just NULL... */
assert(src->sg_mem);
assert(!*src->sg_mem); /* Our synthesized records' sg_mem is always just NULL... */

size_t required =
strlen(src->sg_namp) + 1 +
strlen(src->sg_passwd) + 1;
strlen(src->sg_passwd) + 1 +
sizeof(char*) + /* NULL terminator storage for src->sg_adm */
sizeof(char*); /* NULL terminator storage for src->sg_mem */

if (buflen < required) {
if (buflen < ALIGN(required)) {
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
Expand All @@ -274,7 +284,10 @@ static enum nss_status copy_synthesized_sgrp(
/* String fields point into the user-provided buffer */
dest->sg_namp = buffer;
dest->sg_passwd = stpcpy(dest->sg_namp, src->sg_namp) + 1;
strcpy(dest->sg_passwd, src->sg_passwd);
dest->sg_adm = ALIGN_PTR(stpcpy(dest->sg_passwd, src->sg_passwd) + 1);
*dest->sg_adm = NULL;
dest->sg_mem = dest->sg_adm + 1;
*dest->sg_mem = NULL;

return NSS_STATUS_SUCCESS;
}
Expand Down
56 changes: 51 additions & 5 deletions src/nss-systemd/userdb-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,14 +411,49 @@ enum nss_status userdb_getgrgid(
return NSS_STATUS_SUCCESS;
}

/* Counts string pointers (including terminating NULL element) of given
* string vector strv and stores amount of pointers in n and total
* length of all contained strings including NUL bytes in len. */
static void nss_count_strv(char * const *strv, size_t *n, size_t *len) {
STRV_FOREACH(str, strv) {
(*len) += sizeof(char*); /* space for array entry */
(*len) += strlen(*str) + 1;
(*n)++;
}
(*len) += sizeof(char*); /* trailing NULL in array entry */
(*n)++;
}

/* Performs deep copy of given string vector src and stores content
* of contained strings into buf with references to these strings
* in dst. At dst location, a new NULL-terminated string vector is
* created. The dst and buf locations are updated to point just behind
* the last pointer or char respectively. Returns total amount of
* pointers in newly created string vector in dst, including the
* terminating NULL element. */
static size_t nss_deep_copy_strv(char * const *src, char ***dst, char **buf) {
char *p = *buf;
size_t i = 0;

STRV_FOREACH(str, src) {
(*dst)[i++] = p;
p = stpcpy(p, *str) + 1;
}
(*dst)[i++] = NULL;
*dst += i;
*buf = p;
return i;
}

int nss_pack_group_record_shadow(
GroupRecord *hr,
struct sgrp *sgrp,
char *buffer,
size_t buflen) {

const char *hashed;
size_t required;
char **array = NULL, *p;
size_t i = 0, n = 0, required;

assert(hr);
assert(sgrp);
Expand All @@ -429,15 +464,26 @@ int nss_pack_group_record_shadow(
assert_se(hashed = strv_isempty(hr->hashed_password) ? PASSWORD_LOCKED_AND_INVALID : hr->hashed_password[0]);
required += strlen(hashed) + 1;

nss_count_strv(hr->administrators, &n, &required);
nss_count_strv(hr->members, &n, &required);

if (buflen < required)
return -ERANGE;

*sgrp = (struct sgrp) {
.sg_namp = buffer,
};

assert(buffer);

p = buffer + sizeof(void*) * (n + 1); /* place member strings right after the ptr array */
array = (char**) buffer; /* place ptr array at beginning of buffer, under assumption buffer is aligned */

sgrp->sg_mem = array;
i += nss_deep_copy_strv(hr->members, &array, &p);

sgrp->sg_adm = array;
i += nss_deep_copy_strv(hr->administrators, &array, &p);

assert_se(i == n);

sgrp->sg_namp = p;
sgrp->sg_passwd = stpcpy(sgrp->sg_namp, hr->group_name) + 1;
strcpy(sgrp->sg_passwd, hashed);

Expand Down
7 changes: 6 additions & 1 deletion src/shared/install.c
Original file line number Diff line number Diff line change
Expand Up @@ -1942,6 +1942,7 @@ int unit_file_verify_alias(

static int install_info_symlink_alias(
RuntimeScope scope,
UnitFileFlags file_flags,
InstallInfo *info,
const LookupPaths *lp,
const char *config_path,
Expand Down Expand Up @@ -1996,6 +1997,10 @@ static int install_info_symlink_alias(
broken = r == 0; /* symlink target does not exist? */

r = create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes);
if (r == -EEXIST && FLAGS_SET(file_flags, UNIT_FILE_IGNORE_AUXILIARY_FAILURE))
/* We cannot realize the alias because a conflicting alias exists.
* Do not propagate this as error. */
continue;
if (r != 0 && ret >= 0)
ret = r;
}
Expand Down Expand Up @@ -2160,7 +2165,7 @@ static int install_info_apply(
* because they might would pointing to a non-existent or wrong unit. */
return r;

r = install_info_symlink_alias(scope, info, lp, config_path, force, changes, n_changes);
r = install_info_symlink_alias(scope, file_flags, info, lp, config_path, force, changes, n_changes);

q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->wanted_by, ".wants/", changes, n_changes);
if (q != 0 && r >= 0)
Expand Down
Loading
Loading