@@ -224,6 +224,95 @@ impl CreateRequest {
224224
225225 Ok ( ( ) )
226226 }
227+
228+ fn pivot_fs ( & self ) -> Result < ( ) > {
229+ debug ! ( "early mount!" ) ;
230+
231+ let rootfs = self
232+ . rootfs
233+ . clone ( )
234+ . expect ( "expected rootfs to be configured" ) ;
235+
236+ // Unshare rootfs mount so we can later pivot to a new rootfs.
237+ // The unshared root mount will be cleaned up once the new rootfs is
238+ // in place.
239+ let oldroot = MountSpec {
240+ source : None ,
241+ target : "/" . to_string ( ) ,
242+ fstype : None ,
243+ bind : false ,
244+ recurse : true ,
245+ unshare : true ,
246+ safe : false ,
247+ create_mountpoint : false ,
248+ } ;
249+
250+ oldroot
251+ . mount ( )
252+ . expect ( "failed to unshare / in new mount namespace" ) ;
253+
254+ // Now mount the new rootfs.
255+ let newroot = MountSpec {
256+ source : Some ( rootfs. clone ( ) ) ,
257+ target : rootfs. clone ( ) ,
258+ fstype : Some ( "none" . to_string ( ) ) ,
259+ bind : true ,
260+ recurse : true ,
261+ unshare : false ,
262+ safe : false ,
263+ create_mountpoint : false ,
264+ } ;
265+
266+ newroot. mount ( ) . expect ( "failed to bind new rootfs" ) ;
267+
268+ // Mount /proc.
269+ let procfs = MountSpec {
270+ source : Some ( "proc" . to_string ( ) ) ,
271+ target : format ! ( "{rootfs}/proc" ) ,
272+ fstype : Some ( "proc" . to_string ( ) ) ,
273+ bind : false ,
274+ recurse : true ,
275+ unshare : false ,
276+ safe : true ,
277+ create_mountpoint : false ,
278+ } ;
279+
280+ procfs. mount ( ) . expect ( "failed to mount /proc" ) ;
281+
282+ if let Some ( mounts) = & self . mounts {
283+ for mount in mounts {
284+ let parented_target = format ! ( "{}/{}" , rootfs, mount. target) ;
285+ let parented_mount = MountSpec {
286+ source : mount. source . clone ( ) ,
287+ target : parented_target. clone ( ) ,
288+ fstype : mount. fstype . clone ( ) ,
289+ bind : mount. bind ,
290+ recurse : mount. recurse ,
291+ unshare : mount. unshare ,
292+ safe : mount. safe ,
293+ create_mountpoint : mount. create_mountpoint ,
294+ } ;
295+
296+ parented_mount
297+ . mount ( )
298+ . expect ( "failed to process mount spec" ) ;
299+ }
300+ }
301+
302+ if let Some ( mutations) = & self . mutations {
303+ for mutation in mutations {
304+ match mutation {
305+ Mutation :: CreateDir ( cdm) => {
306+ cdm. mutate ( & rootfs) . expect ( "failed to create directory" ) ;
307+ }
308+ } ;
309+ }
310+ }
311+
312+ newroot. pivot ( ) . expect ( "failed to pivot to new rootfs" ) ;
313+
314+ Ok ( ( ) )
315+ }
227316}
228317
229318impl Wrappable for CreateRequest {
@@ -312,91 +401,13 @@ impl Wrappable for CreateRequest {
312401 process:: exit ( exitcode) ;
313402 }
314403
315- debug ! ( "early mount!" ) ;
316-
317- let rootfs = self
318- . rootfs
319- . clone ( )
320- . expect ( "expected rootfs to be configured" ) ;
321-
322- // Unshare rootfs mount so we can later pivot to a new rootfs.
323- // The unshared root mount will be cleaned up once the new rootfs is
324- // in place.
325- let oldroot = MountSpec {
326- source : None ,
327- target : "/" . to_string ( ) ,
328- fstype : None ,
329- bind : false ,
330- recurse : true ,
331- unshare : true ,
332- safe : false ,
333- create_mountpoint : false ,
334- } ;
335-
336- oldroot
337- . mount ( )
338- . expect ( "failed to unshare / in new mount namespace" ) ;
339-
340- // Now mount the new rootfs.
341- let newroot = MountSpec {
342- source : Some ( rootfs. clone ( ) ) ,
343- target : rootfs. clone ( ) ,
344- fstype : Some ( "none" . to_string ( ) ) ,
345- bind : true ,
346- recurse : true ,
347- unshare : false ,
348- safe : false ,
349- create_mountpoint : false ,
350- } ;
351-
352- newroot. mount ( ) . expect ( "failed to bind new rootfs" ) ;
353-
354- // Mount /proc.
355- let procfs = MountSpec {
356- source : Some ( "proc" . to_string ( ) ) ,
357- target : format ! ( "{rootfs}/proc" ) ,
358- fstype : Some ( "proc" . to_string ( ) ) ,
359- bind : false ,
360- recurse : true ,
361- unshare : false ,
362- safe : true ,
363- create_mountpoint : false ,
364- } ;
365-
366- procfs. mount ( ) . expect ( "failed to mount /proc" ) ;
367-
368- if let Some ( mounts) = & self . mounts {
369- for mount in mounts {
370- let parented_target = format ! ( "{}/{}" , rootfs, mount. target) ;
371- let parented_mount = MountSpec {
372- source : mount. source . clone ( ) ,
373- target : parented_target. clone ( ) ,
374- fstype : mount. fstype . clone ( ) ,
375- bind : mount. bind ,
376- recurse : mount. recurse ,
377- unshare : mount. unshare ,
378- safe : mount. safe ,
379- create_mountpoint : mount. create_mountpoint ,
380- } ;
381-
382- parented_mount
383- . mount ( )
384- . expect ( "failed to process mount spec" ) ;
385- }
386- }
387-
388- if let Some ( mutations) = & self . mutations {
389- for mutation in mutations {
390- match mutation {
391- Mutation :: CreateDir ( cdm) => {
392- cdm. mutate ( & rootfs) . expect ( "failed to create directory" ) ;
393- }
394- } ;
395- }
404+ if target_ns. contains ( & Namespace :: Mount ) {
405+ self . pivot_fs ( ) ?;
406+ } else {
407+ warn ! ( "mount namespace not present in requested namespaces, trying to work anyway..." ) ;
408+ warn ! ( "this is an insecure configuration!" ) ;
396409 }
397410
398- newroot. pivot ( ) . expect ( "failed to pivot to new rootfs" ) ;
399-
400411 debug ! ( "mount tree finalized, doing final prep" ) ;
401412 let mut pef = unsafe { File :: from_raw_fd ( parent_efd) } ;
402413
0 commit comments