summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/basic/missing.h7
-rw-r--r--src/core/execute.c91
-rw-r--r--src/network/networkd-link.c24
3 files changed, 73 insertions, 49 deletions
diff --git a/src/basic/missing.h b/src/basic/missing.h
index dc1f244d4c..9811b6b23e 100644
--- a/src/basic/missing.h
+++ b/src/basic/missing.h
@@ -139,6 +139,8 @@ static inline int pivot_root(const char *new_root, const char *put_old) {
# define __NR_memfd_create 385
# elif defined __aarch64__
# define __NR_memfd_create 279
+# elif defined __s390__
+# define __NR_memfd_create 350
# elif defined _MIPS_SIM
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define __NR_memfd_create 4354
@@ -1028,7 +1030,12 @@ static inline int renameat2(int oldfd, const char *oldname, int newfd, const cha
#if !HAVE_DECL_KCMP
static inline int kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
+#if defined(__NR_kcmp)
return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
}
#endif
diff --git a/src/core/execute.c b/src/core/execute.c
index 6e14848cd4..7796c07fcf 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -50,6 +50,7 @@
#include <sys/apparmor.h>
#endif
+#include "barrier.h"
#include "sd-messages.h"
#include "rm-rf.h"
#include "strv.h"
@@ -768,10 +769,11 @@ static int setup_pam(
.appdata_ptr = NULL
};
+ _cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
pam_handle_t *handle = NULL;
sigset_t old_ss;
int pam_code = PAM_SUCCESS;
- int err;
+ int err = 0;
char **e = NULL;
bool close_session = false;
pid_t pam_pid = 0, parent_pid;
@@ -788,6 +790,10 @@ static int setup_pam(
* daemon. We do things this way to ensure that the main PID
* of the daemon is the one we initially fork()ed. */
+ err = barrier_create(&barrier);
+ if (err < 0)
+ goto fail;
+
if (log_get_max_level() < LOG_DEBUG)
flags |= PAM_SILENT;
@@ -836,6 +842,7 @@ static int setup_pam(
/* The child's job is to reset the PAM session on
* termination */
+ barrier_set_role(&barrier, BARRIER_CHILD);
/* This string must fit in 10 chars (i.e. the length
* of "/sbin/init"), to look pretty in /bin/ps */
@@ -863,6 +870,11 @@ static int setup_pam(
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
goto child_finish;
+ /* Tell the parent that our setup is done. This is especially
+ * important regarding dropping privileges. Otherwise, unit
+ * setup might race against our setresuid(2) call. */
+ barrier_place(&barrier);
+
/* Check if our parent process might already have
* died? */
if (getppid() == parent_pid) {
@@ -898,6 +910,8 @@ static int setup_pam(
_exit(r);
}
+ barrier_set_role(&barrier, BARRIER_PARENT);
+
/* If the child was forked off successfully it will do all the
* cleanups, so forget about the handle here. */
handle = NULL;
@@ -909,6 +923,11 @@ static int setup_pam(
* might have opened it, but we don't want this fd around. */
closelog();
+ /* Synchronously wait for the child to initialize. We don't care for
+ * errors as we cannot recover. However, warn loudly if it happens. */
+ if (!barrier_place_and_sync(&barrier))
+ log_error("PAM initialization failed");
+
*pam_env = e;
e = NULL;
@@ -919,7 +938,7 @@ fail:
log_error("PAM failed: %s", pam_strerror(handle, pam_code));
err = -EPERM; /* PAM errors do not map to errno */
} else {
- err = log_error_errno(errno, "PAM failed: %m");
+ err = log_error_errno(err < 0 ? err : errno, "PAM failed: %m");
}
if (handle) {
@@ -1582,25 +1601,50 @@ static int exec_child(
}
}
+ umask(context->umask);
+
if (params->apply_permissions) {
r = enforce_groups(context, username, gid);
if (r < 0) {
*exit_status = EXIT_GROUP;
return r;
}
- }
+#ifdef HAVE_SMACK
+ if (context->smack_process_label) {
+ r = mac_smack_apply_pid(0, context->smack_process_label);
+ if (r < 0) {
+ *exit_status = EXIT_SMACK_PROCESS_LABEL;
+ return r;
+ }
+ }
+#ifdef SMACK_DEFAULT_PROCESS_LABEL
+ else {
+ _cleanup_free_ char *exec_label = NULL;
- umask(context->umask);
+ r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
+ if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) {
+ *exit_status = EXIT_SMACK_PROCESS_LABEL;
+ return r;
+ }
+ r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
+ if (r < 0) {
+ *exit_status = EXIT_SMACK_PROCESS_LABEL;
+ return r;
+ }
+ }
+#endif
+#endif
#ifdef HAVE_PAM
- if (params->apply_permissions && context->pam_name && username) {
- r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
- if (r < 0) {
- *exit_status = EXIT_PAM;
- return r;
+ if (context->pam_name && username) {
+ r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
+ if (r < 0) {
+ *exit_status = EXIT_PAM;
+ return r;
+ }
}
- }
#endif
+ }
if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
r = setup_netns(runtime->netns_storage_socket);
@@ -1729,33 +1773,6 @@ static int exec_child(
}
}
-#ifdef HAVE_SMACK
- if (context->smack_process_label) {
- r = mac_smack_apply_pid(0, context->smack_process_label);
- if (r < 0) {
- *exit_status = EXIT_SMACK_PROCESS_LABEL;
- return r;
- }
- }
-#ifdef SMACK_DEFAULT_PROCESS_LABEL
- else {
- _cleanup_free_ char *exec_label = NULL;
-
- r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
- if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) {
- *exit_status = EXIT_SMACK_PROCESS_LABEL;
- return r;
- }
-
- r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
- if (r < 0) {
- *exit_status = EXIT_SMACK_PROCESS_LABEL;
- return r;
- }
- }
-#endif
-#endif
-
if (context->user) {
r = enforce_user(context, uid);
if (r < 0) {
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0a7e75c89c..5dd14b1104 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1797,7 +1797,6 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
static int link_set_ipv6_accept_ra(Link *link) {
const char *p = NULL, *v = NULL;
- bool b;
int r;
/* Make this a NOP if IPv6 is not available */
@@ -1807,20 +1806,21 @@ static int link_set_ipv6_accept_ra(Link *link) {
if (link->flags & IFF_LOOPBACK)
return 0;
- /* if unset check the ip forwarding setting maintained for the interface
- * and then set it to depending on that. enabled if local forwarding
- * is disabled. disabled if local forwarding is enabled.
+ /* If unset use system default (enabled if local forwarding is disabled.
+ * disabled if local forwarding is enabled).
+ * If set, ignore or enforce RA independent of local forwarding state.
*/
if (link->network->ipv6_accept_ra < 0) {
- if (IN_SET(link->network->ip_forward, ADDRESS_FAMILY_YES, ADDRESS_FAMILY_IPV6))
- b = false;
- else
- b = true;
- } else
- b = link->network->ipv6_accept_ra;
-
+ /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
+ v = "1";
+ } else if (link->network->ipv6_accept_ra > 0) {
+ /* "2" means accept RA even if ip_forward is enabled */
+ v = "2";
+ } else {
+ /* "0" means ignore RA */
+ v = "0";
+ }
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
- v = one_zero(b);
r = write_string_file(p, v, 0);
if (r < 0) {