@@ -2037,32 +2037,41 @@ static int setup_pts(const char *dest) {
20372037 return 0 ;
20382038}
20392039
2040- static int setup_dev_console (const char * dest , const char * console ) {
2041- _cleanup_umask_ mode_t u ;
2042- const char * to ;
2040+ static int setup_stdio_as_dev_console (void ) {
2041+ int terminal ;
20432042 int r ;
20442043
2045- assert ( dest );
2046-
2047- u = umask ( 0000 );
2044+ terminal = open_terminal ( "/dev/console" , O_RDWR );
2045+ if ( terminal < 0 )
2046+ return log_error_errno ( terminal , "Failed to open console: %m" );
20482047
2049- if (!console )
2050- return 0 ;
2048+ /* Make sure we can continue logging to the original stderr, even if
2049+ * stderr points elsewhere now */
2050+ r = log_dup_console ();
2051+ if (r < 0 )
2052+ return log_error_errno (r , "Failed to duplicate stderr: %m" );
20512053
2052- r = chmod_and_chown (console , 0600 , arg_uid_shift , arg_uid_shift );
2054+ /* invalidates 'terminal' on success and failure */
2055+ r = rearrange_stdio (terminal , terminal , terminal );
20532056 if (r < 0 )
2054- return log_error_errno (r , "Failed to correct access mode for TTY: %m" );
2057+ return log_error_errno (r , "Failed to move console to stdin/stdout/stderr: %m" );
2058+
2059+ return 0 ;
2060+ }
20552061
2056- /* We need to bind mount the right tty to /dev/ console since
2057- * ptys can only exist on pts file systems. To have something
2058- * to bind mount things on we create a empty regular file. */
2062+ static int setup_dev_console ( const char * console ) {
2063+ _cleanup_free_ char * p = NULL ;
2064+ int r ;
20592065
2060- to = prefix_roota ( dest , " /dev/console" );
2061- r = touch ( to );
2066+ /* Create /dev/console symlink */
2067+ r = path_make_relative ( "/dev" , console , & p );
20622068 if (r < 0 )
2063- return log_error_errno (r , "touch() for /dev/console failed: %m" );
2069+ return log_error_errno (r , "Failed to create relative path: %m" );
2070+
2071+ if (symlink (p , "/dev/console" ) < 0 )
2072+ return log_error_errno (errno , "Failed to create /dev/console symlink: %m" );
20642073
2065- return mount_verbose ( LOG_ERR , console , to , NULL , MS_BIND , NULL ) ;
2074+ return 0 ;
20662075}
20672076
20682077static int setup_keyring (void ) {
@@ -2775,8 +2784,10 @@ static int inner_child(
27752784 bool secondary ,
27762785 int kmsg_socket ,
27772786 int rtnl_socket ,
2787+ int master_pty_socket ,
27782788 FDSet * fds ) {
27792789
2790+ _cleanup_close_ int master = -1 ;
27802791 _cleanup_free_ char * home = NULL ;
27812792 char as_uuid [37 ];
27822793 size_t n_env = 1 ;
@@ -2908,6 +2919,36 @@ static int inner_child(
29082919 rtnl_socket = safe_close (rtnl_socket );
29092920 }
29102921
2922+ if (arg_console_mode != CONSOLE_PIPE ) {
2923+ _cleanup_free_ char * console = NULL ;
2924+
2925+ /* Allocate a pty and make it available as /dev/console. */
2926+
2927+ master = posix_openpt (O_RDWR |O_NOCTTY |O_CLOEXEC |O_NONBLOCK );
2928+ if (master < 0 )
2929+ return log_error_errno (errno , "Failed to acquire pseudo tty: %m" );
2930+
2931+ r = ptsname_malloc (master , & console );
2932+ if (r < 0 )
2933+ return log_error_errno (r , "Failed to determine tty name: %m" );
2934+
2935+ if (unlockpt (master ) < 0 )
2936+ return log_error_errno (errno , "Failed to unlock tty: %m" );
2937+
2938+ r = setup_dev_console (console );
2939+ if (r < 0 )
2940+ return log_error_errno (r , "Failed to setup /dev/console: %m" );
2941+
2942+ r = send_one_fd (master_pty_socket , master , 0 );
2943+ if (r < 0 )
2944+ return log_error_errno (r , "Failed to send master fd: %m" );
2945+ master_pty_socket = safe_close (master_pty_socket );
2946+
2947+ r = setup_stdio_as_dev_console ();
2948+ if (r < 0 )
2949+ return r ;
2950+ }
2951+
29112952 r = patch_sysctl ();
29122953 if (r < 0 )
29132954 return r ;
@@ -3129,7 +3170,6 @@ static int setup_sd_notify_child(void) {
31293170static int outer_child (
31303171 Barrier * barrier ,
31313172 const char * directory ,
3132- const char * console ,
31333173 DissectedImage * dissected_image ,
31343174 bool secondary ,
31353175 int pid_socket ,
@@ -3138,6 +3178,7 @@ static int outer_child(
31383178 int kmsg_socket ,
31393179 int rtnl_socket ,
31403180 int uid_shift_socket ,
3181+ int master_pty_socket ,
31413182 int unified_cgroup_hierarchy_socket ,
31423183 FDSet * fds ,
31433184 int netns_fd ) {
@@ -3157,32 +3198,14 @@ static int outer_child(
31573198 assert (pid_socket >= 0 );
31583199 assert (uuid_socket >= 0 );
31593200 assert (notify_socket >= 0 );
3201+ assert (master_pty_socket >= 0 );
31603202 assert (kmsg_socket >= 0 );
31613203
31623204 log_debug ("Outer child is initializing." );
31633205
31643206 if (prctl (PR_SET_PDEATHSIG , SIGKILL ) < 0 )
31653207 return log_error_errno (errno , "PR_SET_PDEATHSIG failed: %m" );
31663208
3167- if (arg_console_mode != CONSOLE_PIPE ) {
3168- int terminal ;
3169-
3170- assert (console );
3171-
3172- terminal = open_terminal (console , O_RDWR );
3173- if (terminal < 0 )
3174- return log_error_errno (terminal , "Failed to open console: %m" );
3175-
3176- /* Make sure we can continue logging to the original stderr, even if stderr points elsewhere now */
3177- r = log_dup_console ();
3178- if (r < 0 )
3179- return log_error_errno (r , "Failed to duplicate stderr: %m" );
3180-
3181- r = rearrange_stdio (terminal , terminal , terminal ); /* invalidates 'terminal' on success and failure */
3182- if (r < 0 )
3183- return log_error_errno (r , "Failed to move console to stdin/stdout/stderr: %m" );
3184- }
3185-
31863209 r = reset_audit_loginuid ();
31873210 if (r < 0 )
31883211 return r ;
@@ -3337,10 +3360,6 @@ static int outer_child(
33373360 if (r < 0 )
33383361 return r ;
33393362
3340- r = setup_dev_console (directory , console );
3341- if (r < 0 )
3342- return r ;
3343-
33443363 r = setup_keyring ();
33453364 if (r < 0 )
33463365 return r ;
@@ -3415,7 +3434,7 @@ static int outer_child(
34153434 return log_error_errno (r , "Failed to join network namespace: %m" );
34163435 }
34173436
3418- r = inner_child (barrier , directory , secondary , kmsg_socket , rtnl_socket , fds );
3437+ r = inner_child (barrier , directory , secondary , kmsg_socket , rtnl_socket , master_pty_socket , fds );
34193438 if (r < 0 )
34203439 _exit (EXIT_FAILURE );
34213440
@@ -3443,6 +3462,7 @@ static int outer_child(
34433462 pid_socket = safe_close (pid_socket );
34443463 uuid_socket = safe_close (uuid_socket );
34453464 notify_socket = safe_close (notify_socket );
3465+ master_pty_socket = safe_close (master_pty_socket );
34463466 kmsg_socket = safe_close (kmsg_socket );
34473467 rtnl_socket = safe_close (rtnl_socket );
34483468 netns_fd = safe_close (netns_fd );
@@ -4042,14 +4062,13 @@ static int load_oci_bundle(void) {
40424062 return merge_settings (settings , arg_oci_bundle );
40434063}
40444064
4045- static int run_container (int master ,
4046- const char * console ,
4065+ static int run_container (
40474066 DissectedImage * dissected_image ,
40484067 bool secondary ,
40494068 FDSet * fds ,
40504069 char veth_name [IFNAMSIZ ], bool * veth_created ,
40514070 union in_addr_union * exposed ,
4052- pid_t * pid , int * ret ) {
4071+ int * master , pid_t * pid , int * ret ) {
40534072
40544073 static const struct sigaction sa = {
40554074 .sa_handler = nop_signal_handler ,
@@ -4065,9 +4084,10 @@ static int run_container(int master,
40654084 uuid_socket_pair [2 ] = { -1 , -1 },
40664085 notify_socket_pair [2 ] = { -1 , -1 },
40674086 uid_shift_socket_pair [2 ] = { -1 , -1 },
4087+ master_pty_socket_pair [2 ] = { -1 , -1 },
40684088 unified_cgroup_hierarchy_socket_pair [2 ] = { -1 , -1 };
40694089
4070- _cleanup_close_ int notify_socket = -1 ;
4090+ _cleanup_close_ int notify_socket = -1 ;
40714091 _cleanup_ (barrier_destroy ) Barrier barrier = BARRIER_NULL ;
40724092 _cleanup_ (sd_event_source_unrefp ) sd_event_source * notify_event_source = NULL ;
40734093 _cleanup_ (sd_event_unrefp ) sd_event * event = NULL ;
@@ -4115,6 +4135,9 @@ static int run_container(int master,
41154135 if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , notify_socket_pair ) < 0 )
41164136 return log_error_errno (errno , "Failed to create notify socket pair: %m" );
41174137
4138+ if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , master_pty_socket_pair ) < 0 )
4139+ return log_error_errno (errno , "Failed to create console socket pair: %m" );
4140+
41184141 if (arg_userns_mode != USER_NAMESPACE_NO )
41194142 if (socketpair (AF_UNIX , SOCK_SEQPACKET |SOCK_CLOEXEC , 0 , uid_shift_socket_pair ) < 0 )
41204143 return log_error_errno (errno , "Failed to create uid shift socket pair: %m" );
@@ -4158,13 +4181,12 @@ static int run_container(int master,
41584181 /* The outer child only has a file system namespace. */
41594182 barrier_set_role (& barrier , BARRIER_CHILD );
41604183
4161- master = safe_close (master );
4162-
41634184 kmsg_socket_pair [0 ] = safe_close (kmsg_socket_pair [0 ]);
41644185 rtnl_socket_pair [0 ] = safe_close (rtnl_socket_pair [0 ]);
41654186 pid_socket_pair [0 ] = safe_close (pid_socket_pair [0 ]);
41664187 uuid_socket_pair [0 ] = safe_close (uuid_socket_pair [0 ]);
41674188 notify_socket_pair [0 ] = safe_close (notify_socket_pair [0 ]);
4189+ master_pty_socket_pair [0 ] = safe_close (master_pty_socket_pair [0 ]);
41684190 uid_shift_socket_pair [0 ] = safe_close (uid_shift_socket_pair [0 ]);
41694191 unified_cgroup_hierarchy_socket_pair [0 ] = safe_close (unified_cgroup_hierarchy_socket_pair [0 ]);
41704192
@@ -4173,7 +4195,6 @@ static int run_container(int master,
41734195
41744196 r = outer_child (& barrier ,
41754197 arg_directory ,
4176- console ,
41774198 dissected_image ,
41784199 secondary ,
41794200 pid_socket_pair [1 ],
@@ -4182,6 +4203,7 @@ static int run_container(int master,
41824203 kmsg_socket_pair [1 ],
41834204 rtnl_socket_pair [1 ],
41844205 uid_shift_socket_pair [1 ],
4206+ master_pty_socket_pair [1 ],
41854207 unified_cgroup_hierarchy_socket_pair [1 ],
41864208 fds ,
41874209 netns_fd );
@@ -4200,6 +4222,7 @@ static int run_container(int master,
42004222 pid_socket_pair [1 ] = safe_close (pid_socket_pair [1 ]);
42014223 uuid_socket_pair [1 ] = safe_close (uuid_socket_pair [1 ]);
42024224 notify_socket_pair [1 ] = safe_close (notify_socket_pair [1 ]);
4225+ master_pty_socket_pair [1 ] = safe_close (master_pty_socket_pair [1 ]);
42034226 uid_shift_socket_pair [1 ] = safe_close (uid_shift_socket_pair [1 ]);
42044227 unified_cgroup_hierarchy_socket_pair [1 ] = safe_close (unified_cgroup_hierarchy_socket_pair [1 ]);
42054228
@@ -4474,17 +4497,40 @@ static int run_container(int master,
44744497
44754498 rtnl_socket_pair [0 ] = safe_close (rtnl_socket_pair [0 ]);
44764499
4477- if (IN_SET (arg_console_mode , CONSOLE_INTERACTIVE , CONSOLE_READ_ONLY )) {
4478- assert (master >= 0 );
4500+ if (arg_console_mode != CONSOLE_PIPE ) {
4501+ _cleanup_close_ int fd = -1 ;
4502+ PTYForwardFlags flags = 0 ;
44794503
4480- r = pty_forward_new (event , master ,
4481- PTY_FORWARD_IGNORE_VHANGUP | (arg_console_mode == CONSOLE_READ_ONLY ? PTY_FORWARD_READ_ONLY : 0 ),
4482- & forward );
4483- if (r < 0 )
4484- return log_error_errno (r , "Failed to create PTY forwarder: %m" );
4504+ /* Retrieve the master pty allocated by inner child */
4505+ fd = receive_one_fd (master_pty_socket_pair [0 ], 0 );
4506+ if (fd < 0 )
4507+ return log_error_errno (fd , "Failed to receive master pty from the inner child: %m" );
4508+
4509+ switch (arg_console_mode ) {
44854510
4486- if (arg_console_width != (unsigned ) -1 || arg_console_height != (unsigned ) -1 )
4487- (void ) pty_forward_set_width_height (forward , arg_console_width , arg_console_height );
4511+ case CONSOLE_READ_ONLY :
4512+ flags |= PTY_FORWARD_READ_ONLY ;
4513+
4514+ _fallthrough_ ;
4515+
4516+ case CONSOLE_INTERACTIVE :
4517+ flags |= PTY_FORWARD_IGNORE_VHANGUP ;
4518+
4519+ r = pty_forward_new (event , fd , flags , & forward );
4520+ if (r < 0 )
4521+ return log_error_errno (r , "Failed to create PTY forwarder: %m" );
4522+
4523+ if (arg_console_width != (unsigned ) -1 || arg_console_height != (unsigned ) -1 )
4524+ (void ) pty_forward_set_width_height (forward ,
4525+ arg_console_width ,
4526+ arg_console_height );
4527+ break ;
4528+
4529+ default :
4530+ assert (arg_console_mode == CONSOLE_PASSIVE );
4531+ }
4532+
4533+ * master = TAKE_FD (fd );
44884534 }
44894535
44904536 r = sd_event_loop (event );
@@ -4614,7 +4660,6 @@ static int initialize_rlimits(void) {
46144660}
46154661
46164662static int run (int argc , char * argv []) {
4617- _cleanup_free_ char * console = NULL ;
46184663 _cleanup_close_ int master = -1 ;
46194664 _cleanup_fdset_free_ FDSet * fds = NULL ;
46204665 int r , n_fd_passed , ret = EXIT_SUCCESS ;
@@ -4929,31 +4974,6 @@ static int run(int argc, char *argv[]) {
49294974 if (arg_console_mode == CONSOLE_PIPE ) /* if we pass STDERR on to the container, don't add our own logs into it too */
49304975 arg_quiet = true;
49314976
4932- if (arg_console_mode != CONSOLE_PIPE ) {
4933- master = posix_openpt (O_RDWR |O_NOCTTY |O_CLOEXEC |O_NONBLOCK );
4934- if (master < 0 ) {
4935- r = log_error_errno (errno , "Failed to acquire pseudo tty: %m" );
4936- goto finish ;
4937- }
4938-
4939- r = ptsname_malloc (master , & console );
4940- if (r < 0 ) {
4941- r = log_error_errno (r , "Failed to determine tty name: %m" );
4942- goto finish ;
4943- }
4944-
4945- if (arg_selinux_apifs_context ) {
4946- r = mac_selinux_apply (console , arg_selinux_apifs_context );
4947- if (r < 0 )
4948- goto finish ;
4949- }
4950-
4951- if (unlockpt (master ) < 0 ) {
4952- r = log_error_errno (errno , "Failed to unlock tty: %m" );
4953- goto finish ;
4954- }
4955- }
4956-
49574977 if (!arg_quiet )
49584978 log_info ("Spawning container %s on %s.\nPress ^] three times within 1s to kill container." ,
49594979 arg_machine , arg_image ?: arg_directory );
@@ -4966,13 +4986,11 @@ static int run(int argc, char *argv[]) {
49664986 }
49674987
49684988 for (;;) {
4969- r = run_container (master ,
4970- console ,
4971- dissected_image ,
4989+ r = run_container (dissected_image ,
49724990 secondary ,
49734991 fds ,
49744992 veth_name , & veth_created ,
4975- & exposed ,
4993+ & exposed , & master ,
49764994 & pid , & ret );
49774995 if (r <= 0 )
49784996 break ;
0 commit comments