1
1
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:
Lennart Poettering 2015-05-21 16:30:58 +02:00
parent ef6fc8ee57
commit 03cfe0d514
10 changed files with 1009 additions and 692 deletions

View File

@ -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>

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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)