@@ -94,14 +94,15 @@ static int handle_parent(json_t * config, pid_t cpid, int *socket);
9494static int child_func (void * arg );
9595static int handle_child (json_t * config , int * socket , int * exec_fd ,
9696 namespace_fd_t * * namespace_fds );
97- static int set_terminal (json_t * process , int dup_stdin , int * socket );
97+ static int set_terminal (json_t * process , int console , int dup_stdin ,
98+ int * socket );
9899static int set_working_directory (json_t * process );
99100static int set_user_group (json_t * process );
100101static int _capng_name_to_capability (const char * name );
101102static int set_capabilities (json_t * process );
102103static void exec_container_process (json_t * config , int * socket , int * exec_fd );
103- static void exec_process (json_t * process , int dup_stdin , int * socket ,
104- int * exec_fd );
104+ static void exec_process (json_t * process , int console , int dup_stdin ,
105+ int * socket , int * exec_fd );
105106static int get_host_exec_fd (json_t * config , int * exec_fd );
106107static int get_namespace_fds (json_t * config , namespace_fd_t * * namespace_fds );
107108static int run_hooks (json_t * config , const char * name , pid_t cpid );
@@ -121,9 +122,9 @@ static int open_in_path(const char *name, int flags);
121122static int _wait (pid_t pid , const char * name );
122123static char * * json_array_of_strings_value (json_t * array );
123124static int close_pipe (int pipe_fd []);
124- static int sendfd (int socket , int * fd );
125+ static int sendfd (int socket , int * fd , int close_fd );
125126static int recvfd (int socket , int * fd );
126- static int splice_pseudoterminal_master (int * master );
127+ static int splice_pseudoterminal_master (int * master , int * slave );
127128static int mkdir_all (const char * path , mode_t mode );
128129
129130int main (int argc , char * * argv )
@@ -321,6 +322,7 @@ static int validate_config(json_t * config)
321322 "s?s," /* "path": "/proc/123/ns/uts */
322323 "}," /* } (uts) */
323324 "}," /* } (namespaces) */
325+ "s?b," /* "console": { */
324326 "s?{" /* "process": { */
325327 "s?b," /* "terminal": true */
326328 "s?{" /* "user": { */
@@ -358,6 +360,7 @@ static int validate_config(json_t * config)
358360 "path" ,
359361 "uts" ,
360362 "path" ,
363+ "console" ,
361364 "process" ,
362365 "terminal" ,
363366 "user" ,
@@ -555,13 +558,13 @@ static int run_container(json_t * config)
555558
556559static int handle_parent (json_t * config , pid_t cpid , int * socket )
557560{
558- json_t * process , * terminal = NULL ;
561+ json_t * process , * console = NULL , * terminal = NULL ;
559562 char buf [MESSAGE_SIZE ];
560563 struct iovec iov ;
561564 struct msghdr msg = { NULL , 0 , & iov , 1 , NULL , 0 , 0 };
562565 size_t len ;
563566 ssize_t n ;
564- int master = -1 , err = 0 , exit = 0 ;
567+ int master = -1 , slave = -1 , err = 0 , exit = 0 ;
565568
566569 if (set_user_namespace_mappings (config , cpid )) {
567570 err = 1 ;
@@ -618,15 +621,24 @@ static int handle_parent(json_t * config, pid_t cpid, int *socket)
618621 goto wait ;
619622 }
620623
624+ console = json_object_get (config , "console" );
621625 process = json_object_get (config , "process" );
622626 if (process ) {
623627 terminal = json_object_get (process , "terminal" );
624- if (json_boolean_value (terminal )) {
628+ if (json_boolean_value (terminal )
629+ || (console && json_boolean_value (console ))) {
625630 if (recvfd (* socket , & master )) {
626631 err = 1 ;
627632 goto wait ;
628633 }
629634 }
635+
636+ if (console && json_boolean_value (console )) {
637+ if (recvfd (* socket , & slave )) {
638+ err = 1 ;
639+ goto wait ;
640+ }
641+ }
630642 }
631643
632644 wait :
@@ -643,7 +655,7 @@ static int handle_parent(json_t * config, pid_t cpid, int *socket)
643655 * socket = -1 ;
644656
645657 if (!err && master >= 0 ) {
646- if (splice_pseudoterminal_master (& master )) {
658+ if (splice_pseudoterminal_master (& master , & slave )) {
647659 err = 1 ;
648660 kill_child (0 , NULL , NULL );
649661 }
@@ -657,6 +669,14 @@ static int handle_parent(json_t * config, pid_t cpid, int *socket)
657669 }
658670 }
659671
672+ if (slave >= 0 ) {
673+ if (close (slave ) == -1 ) {
674+ PERROR ("close pseudoterminal slave" );
675+ err = 1 ;
676+ kill_child (0 , NULL , NULL );
677+ }
678+ }
679+
660680 exit = _wait (cpid , "container" );
661681
662682 (void )run_hooks (config , "post-stop" , 0 );
@@ -777,18 +797,19 @@ static int handle_child(json_t * config, int *socket, int *exec_fd,
777797 return 1 ;
778798}
779799
780- static int set_terminal (json_t * process , int dup_stdin , int * socket )
800+ static int set_terminal (json_t * process , int console , int dup_stdin ,
801+ int * socket )
781802{
782803 json_t * terminal ;
783804 char * slave_name ;
784805 int err = 0 , master = -1 , slave = -1 ;
785806
786807 terminal = json_object_get (process , "terminal" );
787- if (!terminal ) {
808+ if (!terminal && ! console ) {
788809 return 0 ;
789810 }
790811
791- if (json_boolean_value (terminal )) {
812+ if (json_boolean_value (terminal ) || console ) {
792813 if (socket == NULL ) {
793814 LOG ("cannot create a pseudoterminal without a socket for master\n" );
794815 return 1 ;
@@ -832,38 +853,47 @@ static int set_terminal(json_t * process, int dup_stdin, int *socket)
832853 goto cleanup ;
833854 }
834855
835- if (sendfd (* socket , & master )) {
856+ if (sendfd (* socket , & master , 1 )) {
836857 err = 1 ;
837858 goto cleanup ;
838859 }
839860
840- if (dup_stdin ) {
841- if (dup2 (slave , STDIN_FILENO ) == -1 ) {
842- PERROR ("dup2" );
861+ if (console ) {
862+ LOG ("bind mount %s to /dev/console\n" , slave_name );
863+ if (mount
864+ (slave_name , "/dev/console" , NULL , MS_BIND ,
865+ NULL ) == -1 ) {
866+ PERROR ("mount" );
867+ return 1 ;
868+ }
869+
870+ if (sendfd (* socket , & slave , 0 )) {
843871 err = 1 ;
844872 goto cleanup ;
845873 }
846874 }
847875
848- if (dup2 (slave , STDOUT_FILENO ) == -1 ) {
849- PERROR ("dup2" );
850- err = 1 ;
851- goto cleanup ;
852- }
876+ if (json_boolean_value (terminal )) {
877+ if (dup_stdin ) {
878+ if (dup2 (slave , STDIN_FILENO ) == -1 ) {
879+ PERROR ("dup2" );
880+ err = 1 ;
881+ goto cleanup ;
882+ }
883+ }
853884
854- if (dup2 (slave , STDERR_FILENO ) == -1 ) {
855- PERROR ("dup2" );
856- err = 1 ;
857- goto cleanup ;
858- }
885+ if (dup2 (slave , STDOUT_FILENO ) == -1 ) {
886+ PERROR ("dup2" );
887+ err = 1 ;
888+ goto cleanup ;
889+ }
859890
860- if (close (slave ) ) {
861- PERROR ("closing pseudoterminal slave " );
862- slave = - 1 ;
863- err = 1 ;
864- goto cleanup ;
891+ if (dup2 (slave , STDERR_FILENO ) == -1 ) {
892+ PERROR ("dup2 " );
893+ err = 1 ;
894+ goto cleanup ;
895+ }
865896 }
866- slave = -1 ;
867897 }
868898
869899 cleanup :
@@ -1034,20 +1064,22 @@ static int set_capabilities(json_t * process)
10341064
10351065static void exec_container_process (json_t * config , int * socket , int * exec_fd )
10361066{
1037- json_t * process ;
1067+ json_t * process , * console ;
10381068
10391069 process = json_object_get (config , "process" );
10401070 if (!process ) {
10411071 LOG ("process not defined, exiting\n" );
10421072 exit (0 );
10431073 }
10441074
1045- exec_process (process , 1 , socket , exec_fd );
1075+ console = json_object_get (config , "console" );
1076+ exec_process (process , console
1077+ && json_boolean_value (console ), 1 , socket , exec_fd );
10461078 return ;
10471079}
10481080
1049- static void exec_process (json_t * process , int dup_stdin , int * socket ,
1050- int * exec_fd )
1081+ static void exec_process (json_t * process , int console , int dup_stdin ,
1082+ int * socket , int * exec_fd )
10511083{
10521084 char * path = NULL ;
10531085 char * * argv = NULL , * * env = NULL ;
@@ -1060,7 +1092,7 @@ static void exec_process(json_t * process, int dup_stdin, int *socket,
10601092 exit (0 );
10611093 }
10621094
1063- if (set_terminal (process , dup_stdin , socket )) {
1095+ if (set_terminal (process , console , dup_stdin , socket )) {
10641096 goto cleanup ;
10651097 }
10661098
@@ -1343,7 +1375,7 @@ static int run_hooks(json_t * config, const char *name, pid_t cpid)
13431375 pipe_fd [0 ] = -1 ;
13441376 }
13451377
1346- exec_process (hook , cpid == 0 , & sockets [1 ], NULL );
1378+ exec_process (hook , 0 , cpid == 0 , & sockets [1 ], NULL );
13471379 err = 1 ;
13481380 goto cleanup ;
13491381 }
@@ -1373,7 +1405,7 @@ static int run_hooks(json_t * config, const char *name, pid_t cpid)
13731405 }
13741406
13751407 if (master >= 0 ) {
1376- if (splice_pseudoterminal_master (& master )) {
1408+ if (splice_pseudoterminal_master (& master , NULL )) {
13771409 err = 1 ;
13781410 goto cleanup ;
13791411 }
@@ -2149,7 +2181,7 @@ static int close_pipe(int pipe_fd[])
21492181 return err ;
21502182}
21512183
2152- static int sendfd (int socket , int * fd )
2184+ static int sendfd (int socket , int * fd , int close_fd )
21532185{
21542186 struct cmsghdr * cmsg ;
21552187 union {
@@ -2171,12 +2203,14 @@ static int sendfd(int socket, int *fd)
21712203 return 1 ;
21722204 }
21732205
2174- if (close (* fd )) {
2175- PERROR ("close" );
2206+ if (close_fd ) {
2207+ if (close (* fd )) {
2208+ PERROR ("close" );
2209+ * fd = -1 ;
2210+ return 1 ;
2211+ }
21762212 * fd = -1 ;
2177- return 1 ;
21782213 }
2179- * fd = -1 ;
21802214
21812215 return 0 ;
21822216}
@@ -2208,7 +2242,7 @@ int recvfd(int socket, int *fd)
22082242 return 0 ;
22092243}
22102244
2211- static int splice_pseudoterminal_master (int * master )
2245+ static int splice_pseudoterminal_master (int * master , int * slave )
22122246{
22132247 fd_set rfds , wfds , efds ;
22142248 char in_buf [1024 ];
@@ -2226,6 +2260,12 @@ static int splice_pseudoterminal_master(int *master)
22262260
22272261 if (child_pid < 0 ) { /* don't bother piping to a dead process */
22282262 in_open = in_len = 0 ;
2263+ if (slave && * slave >= 0 ) { /* don't hold the slave open either */
2264+ if (close (* slave )) {
2265+ PERROR ("close pseudoterminal slave" );
2266+ }
2267+ * slave = -1 ;
2268+ }
22292269 }
22302270
22312271 if (in_open && in_len == 0 ) { /* wait for new data */
@@ -2369,6 +2409,13 @@ static int splice_pseudoterminal_master(int *master)
23692409 * master = -1 ;
23702410 }
23712411
2412+ if (slave && * slave >= 0 ) {
2413+ if (close (* slave )) {
2414+ PERROR ("close pseudoterminal slave" );
2415+ }
2416+ * slave = -1 ;
2417+ }
2418+
23722419 return err ;
23732420}
23742421
0 commit comments