@@ -848,6 +848,10 @@ static int parse_argv(int argc, char *argv[]) {
848848 return log_error_errno (SYNTHETIC_ERRNO (EINVAL ),
849849 "Network interface name not valid: %s" , optarg );
850850
851+ r = test_network_interface_initialized (optarg );
852+ if (r < 0 )
853+ return r ;
854+
851855 if (strv_extend (& arg_network_interfaces , optarg ) < 0 )
852856 return log_oom ();
853857
@@ -861,6 +865,10 @@ static int parse_argv(int argc, char *argv[]) {
861865 return log_error_errno (SYNTHETIC_ERRNO (EINVAL ),
862866 "MACVLAN network interface name not valid: %s" , optarg );
863867
868+ r = test_network_interface_initialized (optarg );
869+ if (r < 0 )
870+ return r ;
871+
864872 if (strv_extend (& arg_network_macvlan , optarg ) < 0 )
865873 return log_oom ();
866874
@@ -874,6 +882,10 @@ static int parse_argv(int argc, char *argv[]) {
874882 return log_error_errno (SYNTHETIC_ERRNO (EINVAL ),
875883 "IPVLAN network interface name not valid: %s" , optarg );
876884
885+ r = test_network_interface_initialized (optarg );
886+ if (r < 0 )
887+ return r ;
888+
877889 if (strv_extend (& arg_network_ipvlan , optarg ) < 0 )
878890 return log_oom ();
879891
@@ -4199,7 +4211,7 @@ static int run_container(
41994211 int ifi = 0 , r ;
42004212 ssize_t l ;
42014213 sigset_t mask_chld ;
4202- _cleanup_close_ int netns_fd = -1 ;
4214+ _cleanup_close_ int child_netns_fd = -1 ;
42034215
42044216 assert_se (sigemptyset (& mask_chld ) == 0 );
42054217 assert_se (sigaddset (& mask_chld , SIGCHLD ) == 0 );
@@ -4258,11 +4270,11 @@ static int run_container(
42584270 return log_error_errno (errno , "Failed to install SIGCHLD handler: %m" );
42594271
42604272 if (arg_network_namespace_path ) {
4261- netns_fd = open (arg_network_namespace_path , O_RDONLY |O_NOCTTY |O_CLOEXEC );
4262- if (netns_fd < 0 )
4273+ child_netns_fd = open (arg_network_namespace_path , O_RDONLY |O_NOCTTY |O_CLOEXEC );
4274+ if (child_netns_fd < 0 )
42634275 return log_error_errno (errno , "Cannot open file %s: %m" , arg_network_namespace_path );
42644276
4265- r = fd_is_network_ns (netns_fd );
4277+ r = fd_is_network_ns (child_netns_fd );
42664278 if (r == - EUCLEAN )
42674279 log_debug_errno (r , "Cannot determine if passed network namespace path '%s' really refers to a network namespace, assuming it does." , arg_network_namespace_path );
42684280 else if (r < 0 )
@@ -4307,7 +4319,7 @@ static int run_container(
43074319 master_pty_socket_pair [1 ],
43084320 unified_cgroup_hierarchy_socket_pair [1 ],
43094321 fds ,
4310- netns_fd );
4322+ child_netns_fd );
43114323 if (r < 0 )
43124324 _exit (EXIT_FAILURE );
43134325
@@ -4409,7 +4421,15 @@ static int run_container(
44094421 return log_error_errno (SYNTHETIC_ERRNO (ESRCH ), "Child died too early" );
44104422 }
44114423
4412- r = move_network_interfaces (* pid , arg_network_interfaces );
4424+ if (child_netns_fd < 0 ) {
4425+ /* Make sure we have an open file descriptor to the child's network
4426+ * namespace so it stays alive even if the child exits. */
4427+ r = namespace_open (* pid , NULL , NULL , & child_netns_fd , NULL , NULL );
4428+ if (r < 0 )
4429+ return log_error_errno (r , "Failed to open child network namespace: %m" );
4430+ }
4431+
4432+ r = move_network_interfaces (child_netns_fd , arg_network_interfaces );
44134433 if (r < 0 )
44144434 return r ;
44154435
@@ -4655,6 +4675,36 @@ static int run_container(
46554675 /* Normally redundant, but better safe than sorry */
46564676 (void ) kill (* pid , SIGKILL );
46574677
4678+ if (arg_private_network ) {
4679+ /* Move network interfaces back to the parent network namespace. We use `safe_fork`
4680+ * to avoid having to move the parent to the child network namespace. */
4681+ r = safe_fork (NULL , FORK_RESET_SIGNALS |FORK_DEATHSIG |FORK_WAIT |FORK_LOG , NULL );
4682+ if (r < 0 )
4683+ return r ;
4684+
4685+ if (r == 0 ) {
4686+ _cleanup_close_ int parent_netns_fd = -1 ;
4687+
4688+ r = namespace_open (getpid (), NULL , NULL , & parent_netns_fd , NULL , NULL );
4689+ if (r < 0 ) {
4690+ log_error_errno (r , "Failed to open parent network namespace: %m" );
4691+ _exit (EXIT_FAILURE );
4692+ }
4693+
4694+ r = namespace_enter (-1 , -1 , child_netns_fd , -1 , -1 );
4695+ if (r < 0 ) {
4696+ log_error_errno (r , "Failed to enter child network namespace: %m" );
4697+ _exit (EXIT_FAILURE );
4698+ }
4699+
4700+ r = move_network_interfaces (parent_netns_fd , arg_network_interfaces );
4701+ if (r < 0 )
4702+ log_error_errno (r , "Failed to move network interfaces back to parent network namespace: %m" );
4703+
4704+ _exit (r < 0 ? EXIT_FAILURE : EXIT_SUCCESS );
4705+ }
4706+ }
4707+
46584708 r = wait_for_container (* pid , & container_status );
46594709 * pid = 0 ;
46604710
0 commit comments