From 1ccc0f807d3f22fa9ade1c607c112e04df833a72 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Tue, 2 Apr 2019 10:57:24 +0200 Subject: environment: '-C' creates namespaces where the user is not root. * guix/scripts/environment.scm (launch-environment/container): Add UID and GID. Use them in PASSWD and GROUPS. Pass them as #:guest-uid and #:guest-gid to 'call-with-container'. * tests/guix-environment-container.sh: Test the inner UID. In '--user' test, replace hard-coded 0 with 1000. * doc/guix.texi (Invoking guix environment): Adjust accordingly. --- doc/guix.texi | 13 ++++++++----- guix/scripts/environment.scm | 8 ++++++-- tests/guix-environment-container.sh | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 616970b505..616c2ef305 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4557,9 +4557,11 @@ Run @var{command} within an isolated container. The current working directory outside the container is mapped inside the container. Additionally, unless overridden with @code{--user}, a dummy home directory is created that matches the current user's home directory, and -@file{/etc/passwd} is configured accordingly. The spawned process runs -as the current user outside the container, but has root privileges in -the context of the container. +@file{/etc/passwd} is configured accordingly. + +The spawned process runs as the current user outside the container. Inside +the container, it has the same UID and GID as the current user, unless +@option{--user} is passed (see below.) @item --network @itemx -N @@ -4587,8 +4589,9 @@ the environment. @itemx -u @var{user} For containers, use the username @var{user} in place of the current user. The generated @file{/etc/passwd} entry within the container will -contain the name @var{user}; the home directory will be -@file{/home/USER}; and no user GECOS data will be copied. @var{user} +contain the name @var{user}, the home directory will be +@file{/home/@var{user}}, and no user GECOS data will be copied. Furthermore, +the UID and GID inside the container are 1000. @var{user} need not exist on the system. Additionally, any shared or exposed path (see @code{--share} and diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm index c27edc7982..2d1ba4c938 100644 --- a/guix/scripts/environment.scm +++ b/guix/scripts/environment.scm @@ -459,17 +459,19 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from (return (let* ((cwd (getcwd)) (home (getenv "HOME")) + (uid (if user 1000 (getuid))) + (gid (if user 1000 (getgid))) (passwd (let ((pwd (getpwuid (getuid)))) (password-entry (name (or user (passwd:name pwd))) (real-name (if user "" (passwd:gecos pwd))) - (uid 0) (gid 0) (shell bash) + (uid uid) (gid gid) (shell bash) (directory (if user (string-append "/home/" user) (passwd:dir pwd)))))) - (groups (list (group-entry (name "users") (gid 0)) + (groups (list (group-entry (name "users") (gid gid)) (group-entry (gid 65534) ;the overflow GID (name "overflow")))) (home-dir (password-entry-directory passwd)) @@ -541,6 +543,8 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from ;; A container's environment is already purified, so no need to ;; request it be purified again. (launch-environment command profile manifest #:pure? #f))) + #:guest-uid uid + #:guest-gid gid #:namespaces (if network? (delq 'net %namespaces) ; share host network %namespaces))))))) diff --git a/tests/guix-environment-container.sh b/tests/guix-environment-container.sh index f2221af95b..78507f76c0 100644 --- a/tests/guix-environment-container.sh +++ b/tests/guix-environment-container.sh @@ -44,6 +44,19 @@ else test $? = 42 fi +# By default, the UID inside the container should be the same as outside. +uid="`id -u`" +inner_uid="`guix environment -C --ad-hoc --bootstrap guile-bootstrap \ + -- guile -c '(display (getuid))'`" +test $inner_uid = $uid + +# When '--user' is passed, the UID should be 1000. (Note: Use a separate HOME +# so that we don't run into problems when the test directory is under /home.) +export tmpdir +inner_uid="`HOME=$tmpdir guix environment -C --ad-hoc --bootstrap guile-bootstrap \ + --user=gnu-guix -- guile -c '(display (getuid))'`" +test $inner_uid = 1000 + if test "x$USER" = "x"; then USER="`id -un`"; fi # Check whether /etc/passwd and /etc/group are valid. @@ -123,7 +136,7 @@ rm $tmpdir/mounts # Test that user can be mocked. usertest='(exit (and (string=? (getenv "HOME") "/home/foognu") - (string=? (passwd:name (getpwuid 0)) "foognu") + (string=? (passwd:name (getpwuid 1000)) "foognu") (file-exists? "/home/foognu/umock")))' touch "$tmpdir/umock" HOME="$tmpdir" guix environment --bootstrap --container --user=foognu \ -- cgit v1.2.3