summaryrefslogtreecommitdiff
path: root/gnu/build/linux-container.scm
diff options
context:
space:
mode:
authorDavid Thompson <dthompson2@worcester.edu>2015-08-01 21:04:31 -0400
committerDavid Thompson <dthompson2@worcester.edu>2015-08-08 14:04:13 -0400
commit831bc1468ea27732ba59d58e4b38a192151aa123 (patch)
tree7e6474a505e7721ad27a203ac24ff28a0f12697e /gnu/build/linux-container.scm
parent8c812f2aeeed8398a27f1594c20914031d97db58 (diff)
build: container: Add #:host-uids argument to call-with-container.
It's not always possible to map 65536 uids when creating a container as the root user within another user namespace. This is true when building Guix within the build daemon's container. By using a uid range of 1 by default, even as the root user, the tests now pass. * gnu/build/linux-container.scm (initialize-user-namespace, run-container): Add 'host-uids' argument. (call-with-container): Add #:host-uids keyword argument. * tests/containers.scm ("container-excursion"): Update 'run-container' call.
Diffstat (limited to 'gnu/build/linux-container.scm')
-rw-r--r--gnu/build/linux-container.scm38
1 files changed, 19 insertions, 19 deletions
diff --git a/gnu/build/linux-container.scm b/gnu/build/linux-container.scm
index 7a03a29d2ce..af599040a1a 100644
--- a/gnu/build/linux-container.scm
+++ b/gnu/build/linux-container.scm
@@ -120,23 +120,17 @@ to ROOT, then make ROOT the new root directory for the process."
120 (umount "real-root" MNT_DETACH) 120 (umount "real-root" MNT_DETACH)
121 (rmdir "real-root"))) 121 (rmdir "real-root")))
122 122
123(define (initialize-user-namespace pid) 123(define (initialize-user-namespace pid host-uids)
124 "Configure the user namespace for PID." 124 "Configure the user namespace for PID. HOST-UIDS specifies the number of
125host user identifiers to map into the user namespace."
125 (define proc-dir 126 (define proc-dir
126 (string-append "/proc/" (number->string pid))) 127 (string-append "/proc/" (number->string pid)))
127 128
128 (define (scope file) 129 (define (scope file)
129 (string-append proc-dir file)) 130 (string-append proc-dir file))
130 131
131 ;; Only root can map more than a single uid/gid. A range of 65536 uid/gids 132 (let ((uid (getuid))
132 ;; is used to cover 16 bits worth of users and groups, which is sufficient 133 (gid (getgid)))
133 ;; for most cases.
134 ;;
135 ;; See also: http://www.freedesktop.org/software/systemd/man/systemd-nspawn.html#--private-users=
136 (let* ((uid (getuid))
137 (gid (getgid))
138 (uid-range (if (zero? uid) 65536 1))
139 (gid-range (if (zero? gid) 65536 1)))
140 134
141 ;; Only root can write to the gid map without first disabling the 135 ;; Only root can write to the gid map without first disabling the
142 ;; setgroups syscall. 136 ;; setgroups syscall.
@@ -149,10 +143,10 @@ to ROOT, then make ROOT the new root directory for the process."
149 ;; within the container. 143 ;; within the container.
150 (call-with-output-file (scope "/uid_map") 144 (call-with-output-file (scope "/uid_map")
151 (lambda (port) 145 (lambda (port)
152 (format port "0 ~d ~d" uid uid-range))) 146 (format port "0 ~d ~d" uid host-uids)))
153 (call-with-output-file (scope "/gid_map") 147 (call-with-output-file (scope "/gid_map")
154 (lambda (port) 148 (lambda (port)
155 (format port "0 ~d ~d" gid gid-range))))) 149 (format port "0 ~d ~d" gid host-uids)))))
156 150
157(define (namespaces->bit-mask namespaces) 151(define (namespaces->bit-mask namespaces)
158 "Return the number suitable for the 'flags' argument of 'clone' that 152 "Return the number suitable for the 'flags' argument of 'clone' that
@@ -167,12 +161,13 @@ corresponds to the symbols in NAMESPACES."
167 ('net CLONE_NEWNET)) 161 ('net CLONE_NEWNET))
168 namespaces))) 162 namespaces)))
169 163
170(define (run-container root mounts namespaces thunk) 164(define (run-container root mounts namespaces host-uids thunk)
171 "Run THUNK in a new container process and return its PID. ROOT specifies 165 "Run THUNK in a new container process and return its PID. ROOT specifies
172the root directory for the container. MOUNTS is a list of file system specs 166the root directory for the container. MOUNTS is a list of file system specs
173that specify the mapping of host file systems into the container. NAMESPACES 167that specify the mapping of host file systems into the container. NAMESPACES
174is a list of symbols that correspond to the possible Linux namespaces: mnt, 168is a list of symbols that correspond to the possible Linux namespaces: mnt,
175ipc, uts, user, and net." 169ipc, uts, user, and net. HOST-UIDS specifies the number of
170host user identifiers to map into the user namespace."
176 ;; The parent process must initialize the user namespace for the child 171 ;; The parent process must initialize the user namespace for the child
177 ;; before it can boot. To negotiate this, a pipe is used such that the 172 ;; before it can boot. To negotiate this, a pipe is used such that the
178 ;; child process blocks until the parent writes to it. 173 ;; child process blocks until the parent writes to it.
@@ -196,26 +191,31 @@ ipc, uts, user, and net."
196 (thunk)))) 191 (thunk))))
197 (pid 192 (pid
198 (when (memq 'user namespaces) 193 (when (memq 'user namespaces)
199 (initialize-user-namespace pid)) 194 (initialize-user-namespace pid host-uids))
200 ;; TODO: Initialize cgroups. 195 ;; TODO: Initialize cgroups.
201 (close in) 196 (close in)
202 (write 'ready out) 197 (write 'ready out)
203 (close out) 198 (close out)
204 pid)))))) 199 pid))))))
205 200
206(define* (call-with-container mounts thunk #:key (namespaces %namespaces)) 201(define* (call-with-container mounts thunk #:key (namespaces %namespaces)
202 (host-uids 1))
207 "Run THUNK in a new container process and return its exit status. 203 "Run THUNK in a new container process and return its exit status.
208MOUNTS is a list of file system specs that specify the mapping of host file 204MOUNTS is a list of file system specs that specify the mapping of host file
209systems into the container. NAMESPACES is a list of symbols corresponding to 205systems into the container. NAMESPACES is a list of symbols corresponding to
210the identifiers for Linux namespaces: mnt, ipc, uts, pid, user, and net. By 206the identifiers for Linux namespaces: mnt, ipc, uts, pid, user, and net. By
211default, all namespaces are used. 207default, all namespaces are used. HOST-UIDS is the number of host user
208identifiers to map into the container's user namespace, if there is one. By
209default, only a single uid/gid, that of the current user, is mapped into the
210container. The host user that creates the container is the root user (uid/gid
2110) within the container. Only root can map more than a single uid/gid.
212 212
213Note that if THUNK needs to load any additional Guile modules, the relevant 213Note that if THUNK needs to load any additional Guile modules, the relevant
214module files must be present in one of the mappings in MOUNTS and the Guile 214module files must be present in one of the mappings in MOUNTS and the Guile
215load path must be adjusted as needed." 215load path must be adjusted as needed."
216 (call-with-temporary-directory 216 (call-with-temporary-directory
217 (lambda (root) 217 (lambda (root)
218 (let ((pid (run-container root mounts namespaces thunk))) 218 (let ((pid (run-container root mounts namespaces host-uids thunk)))
219 ;; Catch SIGINT and kill the container process. 219 ;; Catch SIGINT and kill the container process.
220 (sigaction SIGINT 220 (sigaction SIGINT
221 (lambda (signum) 221 (lambda (signum)