@@ -3632,7 +3632,7 @@ static int outer_child(
36323632
36333633 _cleanup_ (bind_user_context_freep ) BindUserContext * bind_user_context = NULL ;
36343634 _cleanup_strv_free_ char * * os_release_pairs = NULL ;
3635- _cleanup_close_ int fd = -1 ;
3635+ _cleanup_close_ int fd = -1 , mntns_fd = - EBADF ;
36363636 bool idmap = false;
36373637 const char * p ;
36383638 pid_t pid ;
@@ -3697,6 +3697,15 @@ static int outer_child(
36973697 return r ;
36983698
36993699 if (arg_userns_mode != USER_NAMESPACE_NO ) {
3700+ r = namespace_open (0 , NULL , & mntns_fd , NULL , NULL , NULL );
3701+ if (r < 0 )
3702+ return log_error_errno (r , "Failed to pin outer mount namespace: %m" );
3703+
3704+ l = send_one_fd (notify_socket , mntns_fd , 0 );
3705+ if (l < 0 )
3706+ return log_error_errno (l , "Failed to send outer mount namespace fd: %m" );
3707+ mntns_fd = safe_close (mntns_fd );
3708+
37003709 /* Let the parent know which UID shift we read from the image */
37013710 l = send (uid_shift_socket , & arg_uid_shift , sizeof (arg_uid_shift ), MSG_NOSIGNAL );
37023711 if (l < 0 )
@@ -3974,6 +3983,20 @@ static int outer_child(
39743983 if (r < 0 )
39753984 return log_error_errno (r , "Failed to move root directory: %m" );
39763985
3986+ if (arg_userns_mode != USER_NAMESPACE_NO ) {
3987+ /* In order to mount procfs and sysfs in an unprivileged container the kernel
3988+ * requires that a fully visible instance is already present in the target mount
3989+ * namespace. Mount one here so the inner child can mount its own instances. Later
3990+ * we umount the temporary instances created here before we actually exec the
3991+ * payload. Since the rootfs is shared the umount will propagate into the container.
3992+ * Note, the inner child wouldn't be able to unmount the instances on its own since
3993+ * it doesn't own the originating mount namespace. IOW, the outer child needs to do
3994+ * this. */
3995+ r = pin_fully_visible_fs ();
3996+ if (r < 0 )
3997+ return r ;
3998+ }
3999+
39774000 fd = setup_notify_child ();
39784001 if (fd < 0 )
39794002 return fd ;
@@ -4731,12 +4754,12 @@ static int run_container(
47314754 rtnl_socket_pair [2 ] = { -1 , -1 },
47324755 pid_socket_pair [2 ] = { -1 , -1 },
47334756 uuid_socket_pair [2 ] = { -1 , -1 },
4734- notify_socket_pair [2 ] = { -1 , -1 },
4757+ fd_socket_pair [2 ] = { - EBADF , - EBADF },
47354758 uid_shift_socket_pair [2 ] = { -1 , -1 },
47364759 master_pty_socket_pair [2 ] = { -1 , -1 },
47374760 unified_cgroup_hierarchy_socket_pair [2 ] = { -1 , -1 };
47384761
4739- _cleanup_close_ int notify_socket = -1 ;
4762+ _cleanup_close_ int notify_socket = -1 , mntns_fd = - EBADF ;
47404763 _cleanup_ (barrier_destroy ) Barrier barrier = BARRIER_NULL ;
47414764 _cleanup_ (sd_event_source_unrefp ) sd_event_source * notify_event_source = NULL ;
47424765 _cleanup_ (sd_event_unrefp ) sd_event * event = NULL ;
@@ -4783,7 +4806,7 @@ static int run_container(
47834806 if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , uuid_socket_pair ) < 0 )
47844807 return log_error_errno (errno , "Failed to create id socket pair: %m" );
47854808
4786- if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , notify_socket_pair ) < 0 )
4809+ if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , fd_socket_pair ) < 0 )
47874810 return log_error_errno (errno , "Failed to create notify socket pair: %m" );
47884811
47894812 if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , master_pty_socket_pair ) < 0 )
@@ -4836,7 +4859,7 @@ static int run_container(
48364859 rtnl_socket_pair [0 ] = safe_close (rtnl_socket_pair [0 ]);
48374860 pid_socket_pair [0 ] = safe_close (pid_socket_pair [0 ]);
48384861 uuid_socket_pair [0 ] = safe_close (uuid_socket_pair [0 ]);
4839- notify_socket_pair [0 ] = safe_close (notify_socket_pair [0 ]);
4862+ fd_socket_pair [0 ] = safe_close (fd_socket_pair [0 ]);
48404863 master_pty_socket_pair [0 ] = safe_close (master_pty_socket_pair [0 ]);
48414864 uid_shift_socket_pair [0 ] = safe_close (uid_shift_socket_pair [0 ]);
48424865 unified_cgroup_hierarchy_socket_pair [0 ] = safe_close (unified_cgroup_hierarchy_socket_pair [0 ]);
@@ -4850,7 +4873,7 @@ static int run_container(
48504873 secondary ,
48514874 pid_socket_pair [1 ],
48524875 uuid_socket_pair [1 ],
4853- notify_socket_pair [1 ],
4876+ fd_socket_pair [1 ],
48544877 kmsg_socket_pair [1 ],
48554878 rtnl_socket_pair [1 ],
48564879 uid_shift_socket_pair [1 ],
@@ -4872,12 +4895,16 @@ static int run_container(
48724895 rtnl_socket_pair [1 ] = safe_close (rtnl_socket_pair [1 ]);
48734896 pid_socket_pair [1 ] = safe_close (pid_socket_pair [1 ]);
48744897 uuid_socket_pair [1 ] = safe_close (uuid_socket_pair [1 ]);
4875- notify_socket_pair [1 ] = safe_close (notify_socket_pair [1 ]);
4898+ fd_socket_pair [1 ] = safe_close (fd_socket_pair [1 ]);
48764899 master_pty_socket_pair [1 ] = safe_close (master_pty_socket_pair [1 ]);
48774900 uid_shift_socket_pair [1 ] = safe_close (uid_shift_socket_pair [1 ]);
48784901 unified_cgroup_hierarchy_socket_pair [1 ] = safe_close (unified_cgroup_hierarchy_socket_pair [1 ]);
48794902
48804903 if (arg_userns_mode != USER_NAMESPACE_NO ) {
4904+ mntns_fd = receive_one_fd (fd_socket_pair [0 ], 0 );
4905+ if (mntns_fd < 0 )
4906+ return log_error_errno (mntns_fd , "Failed to receive mount namespace fd from outer child: %m" );
4907+
48814908 /* The child just let us know the UID shift it might have read from the image. */
48824909 l = recv (uid_shift_socket_pair [0 ], & arg_uid_shift , sizeof arg_uid_shift , 0 );
48834910 if (l < 0 )
@@ -4954,7 +4981,7 @@ static int run_container(
49544981 return log_error_errno (SYNTHETIC_ERRNO (EIO ), "Short read while reading container machined ID." );
49554982
49564983 /* We also retrieve the socket used for notifications generated by outer child */
4957- notify_socket = receive_one_fd (notify_socket_pair [0 ], 0 );
4984+ notify_socket = receive_one_fd (fd_socket_pair [0 ], 0 );
49584985 if (notify_socket < 0 )
49594986 return log_error_errno (notify_socket ,
49604987 "Failed to receive notification socket from the outer child: %m" );
@@ -5139,6 +5166,13 @@ static int run_container(
51395166 if (r < 0 )
51405167 return r ;
51415168
5169+ if (arg_userns_mode != USER_NAMESPACE_NO ) {
5170+ r = wipe_fully_visible_fs (mntns_fd );
5171+ if (r < 0 )
5172+ return r ;
5173+ mntns_fd = safe_close (mntns_fd );
5174+ }
5175+
51425176 /* Let the child know that we are ready and wait that the child is completely ready now. */
51435177 if (!barrier_place_and_sync (& barrier )) /* #5 */
51445178 return log_error_errno (SYNTHETIC_ERRNO (ESRCH ), "Child died too early." );
0 commit comments