mirror of
https://github.com/systemd/systemd.git
synced 2025-03-22 06:50:18 +03:00
nspawn: refuse politely when we are run in the non-host netns in combination with --image=
Strictly speaking this doesn't really fix #15079, but it at least means we won't hang anymore. Fixes: #15079
This commit is contained in:
parent
1433e0f212
commit
287b737693
@ -4820,6 +4820,58 @@ static int initialize_rlimits(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cant_be_in_netns(void) {
|
||||
union sockaddr_union sa = {
|
||||
.un = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = "/run/udev/control",
|
||||
},
|
||||
};
|
||||
char udev_path[STRLEN("/proc//ns/net") + DECIMAL_STR_MAX(pid_t)];
|
||||
_cleanup_free_ char *udev_ns = NULL, *our_ns = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
struct ucred ucred;
|
||||
int r;
|
||||
|
||||
/* Check if we are in the same netns as udev. If we aren't, then device monitoring (and thus waiting
|
||||
* for loopback block devices) won't work, and we will hang. Detect this case and exit early with a
|
||||
* nice message. */
|
||||
|
||||
if (!arg_image) /* only matters if --image= us used, i.e. we actually need to use loopback devices */
|
||||
return 0;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to allocate udev control socket: %m");
|
||||
|
||||
if (connect(fd, &sa.un, SOCKADDR_UN_LEN(sa.un)) < 0) {
|
||||
|
||||
if (errno == ENOENT || ERRNO_IS_DISCONNECT(errno))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Sorry, but --image= requires access to the host's /run/ hierarchy, since we need access to udev.");
|
||||
|
||||
return log_error_errno(errno, "Failed to connect socket to udev control socket: %m");
|
||||
}
|
||||
|
||||
r = getpeercred(fd, &ucred);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine peer of udev control socket: %m");
|
||||
|
||||
xsprintf(udev_path, "/proc/" PID_FMT "/ns/net", ucred.pid);
|
||||
r = readlink_malloc(udev_path, &udev_ns);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read network namespace of udev: %m");
|
||||
|
||||
r = readlink_malloc("/proc/self/ns/net", &our_ns);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read our own network namespace: %m");
|
||||
|
||||
if (!streq(our_ns, udev_ns))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Sorry, but --image= is only supported in the main network namespace, since we need access to udev/AF_NETLINK.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
bool secondary = false, remove_directory = false, remove_image = false,
|
||||
veth_created = false, remove_tmprootdir = false;
|
||||
@ -4846,6 +4898,10 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = cant_be_in_netns();
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = initialize_rlimits();
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
Loading…
x
Reference in New Issue
Block a user