@@ -11,6 +11,7 @@ use oci::{Mount, Spec, LinuxDevice, LinuxDeviceType};
1111use selinux:: setfilecon;
1212use std:: collections:: HashMap ;
1313use std:: fs:: { create_dir_all, canonicalize, remove_file} ;
14+ use std:: fs:: OpenOptions ;
1415use std:: os:: unix:: fs:: symlink;
1516use std:: path:: { Path , PathBuf } ;
1617
@@ -54,6 +55,15 @@ pub fn init_rootfs(
5455 let linux = spec. linux . as_ref ( ) . unwrap ( ) ;
5556 mount ( None :: < & str > , "/" , None :: < & str > , flags, None :: < & str > ) ?;
5657
58+ // mount root dir
59+ mount (
60+ Some ( rootfs) ,
61+ rootfs,
62+ None :: < & str > ,
63+ MS_BIND | MS_REC ,
64+ None :: < & str > ,
65+ ) ?;
66+
5767 for m in & spec. mounts {
5868 // TODO: check for nasty destinations involving symlinks and illegal
5969 // locations.
@@ -91,15 +101,6 @@ pub fn init_rootfs(
91101
92102 chdir ( & olddir) ?;
93103
94- // mount root dir
95- mount (
96- Some ( rootfs) ,
97- rootfs,
98- None :: < & str > ,
99- MS_BIND | MS_REC ,
100- None :: < & str > ,
101- ) ?;
102-
103104 Ok ( ( ) )
104105}
105106
@@ -296,26 +297,41 @@ fn mount_from(
296297
297298 let dest = format ! { "{}{}" , rootfs, & m. destination} ;
298299
299- let src = if m. typ == "bind" {
300- canonicalize ( & m. source ) ?
301- } else {
302- PathBuf :: from ( & m. source )
303- } ;
304-
305300 debug ! (
306301 "mounting {} to {} as {} with data '{}'" ,
307302 & m. source,
308303 & m. destination,
309304 & m. typ,
310305 & d
311306 ) ;
312- if let Err ( e) = create_dir_all ( & dest) {
313- debug ! (
314- "ignoring create dir fail for mount {}: {}" ,
315- & m. destination,
316- e
317- )
318- }
307+
308+ let src = if m. typ == "bind" {
309+ let src = canonicalize ( & m. source ) ?;
310+ let dir = if src. is_file ( ) {
311+ Path :: new ( & dest) . parent ( ) . unwrap ( )
312+ } else {
313+ Path :: new ( & dest)
314+ } ;
315+ if let Err ( e) = create_dir_all ( & dir) {
316+ debug ! ( "ignoring create dir fail of {:?}: {}" , & dir, e)
317+ }
318+ // make sure file exists so we can bind over it
319+ if src. is_file ( ) {
320+ if let Err ( e) = OpenOptions :: new ( ) . create ( true ) . write ( true ) . open (
321+ & dest,
322+ )
323+ {
324+ debug ! ( "ignoring touch fail of {:?}: {}" , & dest, e)
325+ }
326+ }
327+ src
328+ } else {
329+ if let Err ( e) = create_dir_all ( & dest) {
330+ debug ! ( "ignoring create dir fail of {:?}: {}" , & dest, e)
331+ }
332+ PathBuf :: from ( & m. source )
333+ } ;
334+
319335 if let Err ( e) = mount (
320336 Some ( & * src) ,
321337 & * dest,
@@ -338,15 +354,19 @@ fn mount_from(
338354 }
339355 // remount bind mounts if they have other flags (like MS_RDONLY)
340356 if flags. contains ( MS_BIND ) &&
341- flags. intersects ( !( MS_REC | MS_REMOUNT | MS_BIND ) )
357+ flags. intersects (
358+ !( MS_REC | MS_REMOUNT | MS_BIND | MS_PRIVATE | MS_SHARED |
359+ MS_SLAVE ) ,
360+ )
342361 {
362+ let chain = || format ! ( "remount of {} failed" , & dest) ;
343363 mount (
344364 Some ( & * dest) ,
345365 & * dest,
346366 None :: < & str > ,
347367 flags | MS_REMOUNT ,
348368 None :: < & str > ,
349- ) ?;
369+ ) . chain_err ( chain ) ?;
350370 }
351371 Ok ( ( ) )
352372}
0 commit comments