mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-10-27 01:55:32 +03:00
nspawn: finish user namespace support
This commit is contained in:
parent
ef6fc8ee57
commit
03cfe0d514
@ -320,6 +320,42 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--private-users=</option></term>
|
||||
|
||||
<listitem><para>Enables user namespacing. If enabled the
|
||||
container will run with its own private set of Unix user and
|
||||
group ids (UIDs and GIDs). Takes none, one or two
|
||||
colon-separated parameters: the first parameter specifies the
|
||||
first host UID to assign to the container, the second
|
||||
parameter specifies the number of host UIDs to assign to the
|
||||
container. If the second parameter is omitted, 65536 UIDs are
|
||||
assigned. If the first parameter is also ommitted (and hence
|
||||
no parameter passed at all), the first UID assigned to the
|
||||
container is read from the owner of the root directory of the
|
||||
container's directory tree. By default no user namespacing is
|
||||
applied.</para>
|
||||
|
||||
<para>Note that user namespacing currently requires OS trees
|
||||
that are prepared for the UID shift that is being applied:
|
||||
UIDs and GIDs used for file ownership or in file ACL entries
|
||||
must be shifted to the container UID base that is
|
||||
used during container runtime.</para>
|
||||
|
||||
<para>It is recommended to assign as least 65536 UIDs to each
|
||||
container, so that the usable UID range in the container
|
||||
covers 16bit. For best security do not assign overlapping UID
|
||||
ranges to multiple containers. It is hence a good idea to use
|
||||
the upper 16bit of the host 32bit UIDs as container
|
||||
identifier, while the lower 16bit encode the container UID
|
||||
used.</para>
|
||||
|
||||
<para>When user namespaces are used the GID range assigned to
|
||||
each container is always chosen identical to the UID
|
||||
range.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--private-network</option></term>
|
||||
|
||||
|
@ -373,7 +373,7 @@ int mount_setup(bool loaded_policy) {
|
||||
/* Create a few default symlinks, which are normally created
|
||||
* by udevd, but some scripts might need them before we start
|
||||
* udevd. */
|
||||
dev_setup(NULL);
|
||||
dev_setup(NULL, UID_INVALID, GID_INVALID);
|
||||
|
||||
/* Mark the root directory as shared in regards to mount
|
||||
* propagation. The kernel defaults to "private", but we think
|
||||
|
@ -224,7 +224,7 @@ static int mount_dev(BindMount *m) {
|
||||
}
|
||||
}
|
||||
|
||||
dev_setup(temporary_mount);
|
||||
dev_setup(temporary_mount, UID_INVALID, GID_INVALID);
|
||||
|
||||
/* Create the /dev directory if missing. It is more likely to be
|
||||
* missing when the service is started with RootDirectory. This is
|
||||
|
1604
src/nspawn/nspawn.c
1604
src/nspawn/nspawn.c
File diff suppressed because it is too large
Load Diff
@ -41,13 +41,16 @@ static const BaseFilesystem table[] = {
|
||||
{ "lib", 0, "usr/lib\0", NULL },
|
||||
{ "root", 0755, NULL, NULL },
|
||||
{ "sbin", 0, "usr/sbin\0", NULL },
|
||||
{ "usr", 0755, NULL, NULL },
|
||||
{ "var", 0755, NULL, NULL },
|
||||
{ "etc", 0755, NULL, NULL },
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
{ "lib64", 0, "usr/lib/x86_64-linux-gnu\0"
|
||||
"usr/lib64\0", "ld-linux-x86-64.so.2" },
|
||||
#endif
|
||||
};
|
||||
|
||||
int base_filesystem_create(const char *root) {
|
||||
int base_filesystem_create(const char *root, uid_t uid, gid_t gid) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
unsigned i;
|
||||
int r = 0;
|
||||
@ -90,6 +93,12 @@ int base_filesystem_create(const char *root) {
|
||||
r = symlinkat(target, fd, table[i].dir);
|
||||
if (r < 0 && errno != EEXIST)
|
||||
return log_error_errno(errno, "Failed to create symlink at %s/%s: %m", root, table[i].dir);
|
||||
|
||||
if (uid != UID_INVALID || gid != UID_INVALID) {
|
||||
if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
return log_error_errno(errno, "Failed to chown symlink at %s/%s: %m", root, table[i].dir);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -97,6 +106,11 @@ int base_filesystem_create(const char *root) {
|
||||
r = mkdirat(fd, table[i].dir, table[i].mode);
|
||||
if (r < 0 && errno != EEXIST)
|
||||
return log_error_errno(errno, "Failed to create directory at %s/%s: %m", root, table[i].dir);
|
||||
|
||||
if (uid != UID_INVALID || gid != UID_INVALID) {
|
||||
if (fchownat(fd, table[i].dir, uid, gid, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
return log_error_errno(errno, "Failed to chown directory at %s/%s: %m", root, table[i].dir);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -21,4 +21,6 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int base_filesystem_create(const char *root);
|
||||
#include <sys/types.h>
|
||||
|
||||
int base_filesystem_create(const char *root, uid_t uid, gid_t gid);
|
||||
|
@ -23,13 +23,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dev-setup.h"
|
||||
#include "util.h"
|
||||
#include "label.h"
|
||||
#include "path-util.h"
|
||||
#include "dev-setup.h"
|
||||
|
||||
int dev_setup(const char *prefix) {
|
||||
const char *j, *k;
|
||||
|
||||
int dev_setup(const char *prefix, uid_t uid, gid_t gid) {
|
||||
static const char symlinks[] =
|
||||
"-/proc/kcore\0" "/dev/core\0"
|
||||
"/proc/self/fd\0" "/dev/fd\0"
|
||||
@ -37,7 +36,13 @@ int dev_setup(const char *prefix) {
|
||||
"/proc/self/fd/1\0" "/dev/stdout\0"
|
||||
"/proc/self/fd/2\0" "/dev/stderr\0";
|
||||
|
||||
const char *j, *k;
|
||||
int r;
|
||||
|
||||
NULSTR_FOREACH_PAIR(j, k, symlinks) {
|
||||
_cleanup_free_ char *link_name = NULL;
|
||||
const char *n;
|
||||
|
||||
if (j[0] == '-') {
|
||||
j++;
|
||||
|
||||
@ -46,15 +51,21 @@ int dev_setup(const char *prefix) {
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
_cleanup_free_ char *link_name = NULL;
|
||||
|
||||
link_name = strjoin(prefix, "/", k, NULL);
|
||||
link_name = prefix_root(prefix, k);
|
||||
if (!link_name)
|
||||
return -ENOMEM;
|
||||
|
||||
symlink_label(j, link_name);
|
||||
n = link_name;
|
||||
} else
|
||||
symlink_label(j, k);
|
||||
n = k;
|
||||
|
||||
r = symlink_label(j, n);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to symlink %s to %s: %m", j, n);
|
||||
|
||||
if (uid != UID_INVALID || gid != GID_INVALID)
|
||||
if (lchown(n, uid, gid) < 0)
|
||||
log_debug_errno(errno, "Failed to chown %s: %m", n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -21,4 +21,6 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int dev_setup(const char *pathprefix);
|
||||
#include <sys/types.h>
|
||||
|
||||
int dev_setup(const char *prefix, uid_t uid, gid_t gid);
|
||||
|
@ -105,7 +105,7 @@ int switch_root(const char *new_root, const char *oldroot, bool detach_oldroot,
|
||||
* to look like. They might even boot, if they are RO and
|
||||
* don't have the FS layout. Just ignore the error and
|
||||
* switch_root() nevertheless. */
|
||||
(void) base_filesystem_create(new_root);
|
||||
(void) base_filesystem_create(new_root, UID_INVALID, GID_INVALID);
|
||||
|
||||
if (chdir(new_root) < 0)
|
||||
return log_error_errno(errno, "Failed to change directory to %s: %m", new_root);
|
||||
|
@ -1484,7 +1484,7 @@ int main(int argc, char *argv[]) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dev_setup(NULL);
|
||||
dev_setup(NULL, UID_INVALID, GID_INVALID);
|
||||
|
||||
r = manager_new(&manager);
|
||||
if (r < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user