d0545ad5eae1ecfb1ca2601146b305c05cd1dcbd
[platform/upstream/glibc.git] / libio / iopopen.c
1 /* Copyright (C) 1993-2023 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.
17
18    As a special exception, if you link the code in this file with
19    files compiled with a GNU compiler to produce an executable,
20    that does not cause the resulting executable to be covered by
21    the GNU Lesser General Public License.  This exception does not
22    however invalidate any other reasons why the executable file
23    might be covered by the GNU Lesser General Public License.
24    This exception applies to code released by its copyright holders
25    in files containing the exception.  */
26
27 #include "libioP.h"
28 #include <fcntl.h>
29 #include <signal.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <shlib-compat.h>
33 #include <not-cancel.h>
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <spawn.h>
37 #include <paths.h>
38
39 struct _IO_proc_file
40 {
41   struct _IO_FILE_plus file;
42   /* Following fields must match those in class procbuf (procbuf.h) */
43   pid_t pid;
44   struct _IO_proc_file *next;
45 };
46 typedef struct _IO_proc_file _IO_proc_file;
47
48 static const struct _IO_jump_t _IO_proc_jumps;
49
50 static struct _IO_proc_file *proc_file_chain;
51
52 #ifdef _IO_MTSAFE_IO
53 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
54
55 static void
56 unlock (void *not_used)
57 {
58   _IO_lock_unlock (proc_file_chain_lock);
59 }
60 #endif
61
62 /* POSIX states popen shall ensure that any streams from previous popen()
63    calls that remain open in the parent process should be closed in the new
64    child process.
65    To avoid a race-condition between checking which file descriptors need to
66    be close (by transversing the proc_file_chain list) and the insertion of a
67    new one after a successful posix_spawn this function should be called
68    with proc_file_chain_lock acquired.  */
69 static int
70 spawn_process (posix_spawn_file_actions_t *fa, FILE *fp, const char *command,
71                int do_cloexec, int pipe_fds[2], int parent_end, int child_end,
72                int child_pipe_fd)
73 {
74   int err = 0;
75
76   for (struct _IO_proc_file *p = proc_file_chain; p; p = p->next)
77     {
78       int fd = _IO_fileno ((FILE *) p);
79
80       /* If any stream from previous popen() calls has fileno
81          child_pipe_fd, it has been already closed by the adddup2 action
82          above.  */
83       if (fd != child_pipe_fd)
84         {
85           err = __posix_spawn_file_actions_addclose (fa, fd);
86           if (err != 0)
87             return err;
88         }
89     }
90
91   err = __posix_spawn (&((_IO_proc_file *) fp)->pid, _PATH_BSHELL, fa, 0,
92                        (char *const[]){ (char*) "sh", (char*) "-c",
93                        (char *) command, NULL }, __environ);
94   if (err != 0)
95     return err;
96
97   __close_nocancel (pipe_fds[child_end]);
98
99   if (!do_cloexec)
100     /* Undo the effects of the pipe2 call which set the
101        close-on-exec flag.  */
102     __fcntl (pipe_fds[parent_end], F_SETFD, 0);
103
104   _IO_fileno (fp) = pipe_fds[parent_end];
105
106   ((_IO_proc_file *) fp)->next = proc_file_chain;
107   proc_file_chain = (_IO_proc_file *) fp;
108
109   return 0;
110 }
111
112 FILE *
113 _IO_new_proc_open (FILE *fp, const char *command, const char *mode)
114 {
115   int read_or_write;
116   /* These are indexes for pipe_fds.  */
117   int parent_end, child_end;
118   int pipe_fds[2];
119   int child_pipe_fd;
120   int err;
121
122   int do_read = 0;
123   int do_write = 0;
124   int do_cloexec = 0;
125   while (*mode != '\0')
126     switch (*mode++)
127       {
128       case 'r':
129         do_read = 1;
130         break;
131       case 'w':
132         do_write = 1;
133         break;
134       case 'e':
135         do_cloexec = 1;
136         break;
137       default:
138       errout:
139         __set_errno (EINVAL);
140         return NULL;
141       }
142
143   if ((do_read ^ do_write) == 0)
144     goto errout;
145
146   if (_IO_file_is_open (fp))
147     return NULL;
148
149   /* Atomically set the O_CLOEXEC flag for the pipe end used by the
150      child process (to avoid leaking the file descriptor in case of a
151      concurrent fork).  This is later reverted in the child process.
152      When popen returns, the parent pipe end can be O_CLOEXEC or not,
153      depending on the 'e' open mode, but there is only one flag which
154      controls both descriptors.  The parent end is adjusted below,
155      after creating the child process.  (In the child process, the
156      parent end should be closed on execve, so O_CLOEXEC remains set
157      there.)  */
158   if (__pipe2 (pipe_fds, O_CLOEXEC) < 0)
159     return NULL;
160
161   if (do_read)
162     {
163       parent_end = 0;
164       child_end = 1;
165       read_or_write = _IO_NO_WRITES;
166       child_pipe_fd = 1;
167     }
168   else
169     {
170       parent_end = 1;
171       child_end = 0;
172       read_or_write = _IO_NO_READS;
173       child_pipe_fd = 0;
174     }
175
176   posix_spawn_file_actions_t fa;
177   /* posix_spawn_file_actions_init does not fail.  */
178   __posix_spawn_file_actions_init (&fa);
179
180   /* The descriptor is already the one the child will use.  In this case
181      it must be moved to another one otherwise, there is no safe way to
182      remove the close-on-exec flag in the child without creating a FD leak
183      race in the parent.  */
184   if (pipe_fds[child_end] == child_pipe_fd)
185     {
186       int tmp = __fcntl (child_pipe_fd, F_DUPFD_CLOEXEC, 0);
187       if (tmp < 0)
188         goto spawn_failure;
189       __close_nocancel (pipe_fds[child_end]);
190       pipe_fds[child_end] = tmp;
191     }
192
193   err = __posix_spawn_file_actions_adddup2 (&fa, pipe_fds[child_end],
194                                             child_pipe_fd);
195   if (err != 0)
196     goto spawn_failure;
197
198 #ifdef _IO_MTSAFE_IO
199   _IO_cleanup_region_start_noarg (unlock);
200   _IO_lock_lock (proc_file_chain_lock);
201 #endif
202   err = spawn_process (&fa, fp, command, do_cloexec, pipe_fds, parent_end,
203                        child_end, child_pipe_fd);
204 #ifdef _IO_MTSAFE_IO
205   _IO_lock_unlock (proc_file_chain_lock);
206   _IO_cleanup_region_end (0);
207 #endif
208
209   __posix_spawn_file_actions_destroy (&fa);
210
211   if (err != 0)
212     {
213       __set_errno (err);
214     spawn_failure:
215       __close_nocancel (pipe_fds[child_end]);
216       __close_nocancel (pipe_fds[parent_end]);
217       return NULL;
218     }
219
220   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
221   return fp;
222 }
223
224 FILE *
225 _IO_new_popen (const char *command, const char *mode)
226 {
227   struct locked_FILE
228   {
229     struct _IO_proc_file fpx;
230 #ifdef _IO_MTSAFE_IO
231     _IO_lock_t lock;
232 #endif
233   } *new_f;
234   FILE *fp;
235
236   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
237   if (new_f == NULL)
238     return NULL;
239 #ifdef _IO_MTSAFE_IO
240   new_f->fpx.file.file._lock = &new_f->lock;
241 #endif
242   fp = &new_f->fpx.file.file;
243   _IO_init_internal (fp, 0);
244   _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
245   _IO_new_file_init_internal (&new_f->fpx.file);
246   if (_IO_new_proc_open (fp, command, mode) != NULL)
247     return (FILE *) &new_f->fpx.file;
248   _IO_un_link (&new_f->fpx.file);
249   free (new_f);
250   return NULL;
251 }
252
253 int
254 _IO_new_proc_close (FILE *fp)
255 {
256   /* This is not name-space clean. FIXME! */
257   int wstatus;
258   _IO_proc_file **ptr = &proc_file_chain;
259   pid_t wait_pid;
260   int status = -1;
261
262   /* Unlink from proc_file_chain. */
263 #ifdef _IO_MTSAFE_IO
264   _IO_cleanup_region_start_noarg (unlock);
265   _IO_lock_lock (proc_file_chain_lock);
266 #endif
267   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
268     {
269       if (*ptr == (_IO_proc_file *) fp)
270         {
271           *ptr = (*ptr)->next;
272           status = 0;
273           break;
274         }
275     }
276 #ifdef _IO_MTSAFE_IO
277   _IO_lock_unlock (proc_file_chain_lock);
278   _IO_cleanup_region_end (0);
279 #endif
280
281   if (status < 0 || __close_nocancel (_IO_fileno(fp)) < 0)
282     return -1;
283   /* POSIX.2 Rationale:  "Some historical implementations either block
284      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
285      for the child process to terminate.  Since this behavior is not
286      described in POSIX.2, such implementations are not conforming." */
287   do
288     {
289       int state;
290       __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
291       wait_pid = __waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
292       __pthread_setcancelstate (state, NULL);
293     }
294   while (wait_pid == -1 && errno == EINTR);
295   if (wait_pid == -1)
296     return -1;
297   return wstatus;
298 }
299
300 static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
301   JUMP_INIT_DUMMY,
302   JUMP_INIT(finish, _IO_new_file_finish),
303   JUMP_INIT(overflow, _IO_new_file_overflow),
304   JUMP_INIT(underflow, _IO_new_file_underflow),
305   JUMP_INIT(uflow, _IO_default_uflow),
306   JUMP_INIT(pbackfail, _IO_default_pbackfail),
307   JUMP_INIT(xsputn, _IO_new_file_xsputn),
308   JUMP_INIT(xsgetn, _IO_default_xsgetn),
309   JUMP_INIT(seekoff, _IO_new_file_seekoff),
310   JUMP_INIT(seekpos, _IO_default_seekpos),
311   JUMP_INIT(setbuf, _IO_new_file_setbuf),
312   JUMP_INIT(sync, _IO_new_file_sync),
313   JUMP_INIT(doallocate, _IO_file_doallocate),
314   JUMP_INIT(read, _IO_file_read),
315   JUMP_INIT(write, _IO_new_file_write),
316   JUMP_INIT(seek, _IO_file_seek),
317   JUMP_INIT(close, _IO_new_proc_close),
318   JUMP_INIT(stat, _IO_file_stat),
319   JUMP_INIT(showmanyc, _IO_default_showmanyc),
320   JUMP_INIT(imbue, _IO_default_imbue)
321 };
322
323 strong_alias (_IO_new_popen, __new_popen)
324 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
325 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
326 versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
327 versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);