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.
This commit is contained in:
Ludovic Courtès 2019-04-02 10:57:24 +02:00
parent af76c020bf
commit 1ccc0f807d
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
3 changed files with 28 additions and 8 deletions

View File

@ -4557,9 +4557,11 @@ Run @var{command} within an isolated container. The current working
directory outside the container is mapped inside the container. directory outside the container is mapped inside the container.
Additionally, unless overridden with @code{--user}, a dummy home Additionally, unless overridden with @code{--user}, a dummy home
directory is created that matches the current user's home directory, and directory is created that matches the current user's home directory, and
@file{/etc/passwd} is configured accordingly. The spawned process runs @file{/etc/passwd} is configured accordingly.
as the current user outside the container, but has root privileges in
the context of the container. 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 @item --network
@itemx -N @itemx -N
@ -4587,8 +4589,9 @@ the environment.
@itemx -u @var{user} @itemx -u @var{user}
For containers, use the username @var{user} in place of the current For containers, use the username @var{user} in place of the current
user. The generated @file{/etc/passwd} entry within the container will user. The generated @file{/etc/passwd} entry within the container will
contain the name @var{user}; the home directory will be contain the name @var{user}, the home directory will be
@file{/home/USER}; and no user GECOS data will be copied. @var{user} @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. need not exist on the system.
Additionally, any shared or exposed path (see @code{--share} and Additionally, any shared or exposed path (see @code{--share} and

View File

@ -459,17 +459,19 @@ will be used for the passwd entry. LINK-PROFILE? creates a symbolic link from
(return (return
(let* ((cwd (getcwd)) (let* ((cwd (getcwd))
(home (getenv "HOME")) (home (getenv "HOME"))
(uid (if user 1000 (getuid)))
(gid (if user 1000 (getgid)))
(passwd (let ((pwd (getpwuid (getuid)))) (passwd (let ((pwd (getpwuid (getuid))))
(password-entry (password-entry
(name (or user (passwd:name pwd))) (name (or user (passwd:name pwd)))
(real-name (if user (real-name (if user
"" ""
(passwd:gecos pwd))) (passwd:gecos pwd)))
(uid 0) (gid 0) (shell bash) (uid uid) (gid gid) (shell bash)
(directory (if user (directory (if user
(string-append "/home/" user) (string-append "/home/" user)
(passwd:dir pwd)))))) (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 (group-entry (gid 65534) ;the overflow GID
(name "overflow")))) (name "overflow"))))
(home-dir (password-entry-directory passwd)) (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 ;; A container's environment is already purified, so no need to
;; request it be purified again. ;; request it be purified again.
(launch-environment command profile manifest #:pure? #f))) (launch-environment command profile manifest #:pure? #f)))
#:guest-uid uid
#:guest-gid gid
#:namespaces (if network? #:namespaces (if network?
(delq 'net %namespaces) ; share host network (delq 'net %namespaces) ; share host network
%namespaces))))))) %namespaces)))))))

View File

@ -44,6 +44,19 @@ else
test $? = 42 test $? = 42
fi 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 if test "x$USER" = "x"; then USER="`id -un`"; fi
# Check whether /etc/passwd and /etc/group are valid. # Check whether /etc/passwd and /etc/group are valid.
@ -123,7 +136,7 @@ rm $tmpdir/mounts
# Test that user can be mocked. # Test that user can be mocked.
usertest='(exit (and (string=? (getenv "HOME") "/home/foognu") 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")))' (file-exists? "/home/foognu/umock")))'
touch "$tmpdir/umock" touch "$tmpdir/umock"
HOME="$tmpdir" guix environment --bootstrap --container --user=foognu \ HOME="$tmpdir" guix environment --bootstrap --container --user=foognu \