Skip to content

Commit 1beab8b

Browse files
poetteringkeszybz
authored andcommitted
namespace: be more careful when handling namespacing failures gracefully
This makes two changes to the namespacing code: 1. We'll only gracefully skip service namespacing on access failure if exclusively sandboxing options where selected, and not mount-related options that result in a very different view of the world. For example, ignoring RootDirectory=, RootImage= or Bind= is really probablematic, but ReadOnlyPaths= is just a weaker sandbox. 2. The namespacing code will now return a clearly recognizable error code when it cannot enforce its namespacing, so that we cannot confuse EPERM errors from mount() with those from unshare(). Only the errors from the first unshare() are now taken as hint to gracefully disable namespacing. Fixes: systemd#9844 systemd#9835
1 parent b257b19 commit 1beab8b

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

src/core/execute.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,10 +2386,15 @@ static int apply_mount_namespace(
23862386

23872387
bind_mount_free_many(bind_mounts, n_bind_mounts);
23882388

2389-
/* If we couldn't set up the namespace this is probably due to a
2390-
* missing capability. In this case, silently proceeed. */
2391-
if (IN_SET(r, -EPERM, -EACCES)) {
2392-
log_unit_debug_errno(u, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
2389+
/* If we couldn't set up the namespace this is probably due to a missing capability. setup_namespace() reports
2390+
* that with a special, recognizable error ENOANO. In this case, silently proceeed, but only if exclusively
2391+
* sandboxing options were used, i.e. nothing such as RootDirectory= or BindMount= that would result in a
2392+
* completely different execution environment. */
2393+
if (r == -ENOANO &&
2394+
n_bind_mounts == 0 && context->n_temporary_filesystems == 0 &&
2395+
!root_dir && !root_image &&
2396+
!context->dynamic_user) {
2397+
log_unit_debug(u, "Failed to set up namespace, assuming containerized execution and ignoring.");
23932398
return 0;
23942399
}
23952400

src/core/namespace.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,8 +1290,17 @@ int setup_namespace(
12901290
normalize_mounts(root, mounts, &n_mounts);
12911291
}
12921292

1293+
/* All above is just preparation, figuring out what to do. Let's now actually start doing something. */
1294+
12931295
if (unshare(CLONE_NEWNS) < 0) {
12941296
r = log_debug_errno(errno, "Failed to unshare the mount namespace: %m");
1297+
if (IN_SET(r, -EACCES, -EPERM, -EOPNOTSUPP, -ENOSYS))
1298+
/* If the kernel doesn't support namespaces, or when there's a MAC or seccomp filter in place
1299+
* that doesn't allow us to create namespaces (or a missing cap), then propagate a recognizable
1300+
* error back, which the caller can use to detect this case (and only this) and optionally
1301+
* continue without namespacing applied. */
1302+
r = -ENOANO;
1303+
12951304
goto finish;
12961305
}
12971306

0 commit comments

Comments
 (0)