xref: /openbmc/qemu/include/user/safe-syscall.h (revision e4e5cb4a)
1bbf15aafSRichard Henderson /*
2bbf15aafSRichard Henderson  * safe-syscall.h: prototypes for linux-user signal-race-safe syscalls
3bbf15aafSRichard Henderson  *
4bbf15aafSRichard Henderson  *  This program is free software; you can redistribute it and/or modify
5bbf15aafSRichard Henderson  *  it under the terms of the GNU General Public License as published by
6bbf15aafSRichard Henderson  *  the Free Software Foundation; either version 2 of the License, or
7bbf15aafSRichard Henderson  *  (at your option) any later version.
8bbf15aafSRichard Henderson  *
9bbf15aafSRichard Henderson  *  This program is distributed in the hope that it will be useful,
10bbf15aafSRichard Henderson  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11bbf15aafSRichard Henderson  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12bbf15aafSRichard Henderson  *  GNU General Public License for more details.
13bbf15aafSRichard Henderson  *
14bbf15aafSRichard Henderson  *  You should have received a copy of the GNU General Public License
15bbf15aafSRichard Henderson  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16bbf15aafSRichard Henderson  */
17bbf15aafSRichard Henderson 
18bbf15aafSRichard Henderson #ifndef LINUX_USER_SAFE_SYSCALL_H
19bbf15aafSRichard Henderson #define LINUX_USER_SAFE_SYSCALL_H
20bbf15aafSRichard Henderson 
21bbf15aafSRichard Henderson /**
22bbf15aafSRichard Henderson  * safe_syscall:
23bbf15aafSRichard Henderson  * @int number: number of system call to make
24bbf15aafSRichard Henderson  * ...: arguments to the system call
25bbf15aafSRichard Henderson  *
26bbf15aafSRichard Henderson  * Call a system call if guest signal not pending.
27bbf15aafSRichard Henderson  * This has the same API as the libc syscall() function, except that it
28bbf15aafSRichard Henderson  * may return -1 with errno == QEMU_ERESTARTSYS if a signal was pending.
29bbf15aafSRichard Henderson  *
30bbf15aafSRichard Henderson  * Returns: the system call result, or -1 with an error code in errno
31bbf15aafSRichard Henderson  * (Errnos are host errnos; we rely on QEMU_ERESTARTSYS not clashing
32bbf15aafSRichard Henderson  * with any of the host errno values.)
33bbf15aafSRichard Henderson  */
34bbf15aafSRichard Henderson 
35bbf15aafSRichard Henderson /*
36bbf15aafSRichard Henderson  * A guide to using safe_syscall() to handle interactions between guest
37bbf15aafSRichard Henderson  * syscalls and guest signals:
38bbf15aafSRichard Henderson  *
39bbf15aafSRichard Henderson  * Guest syscalls come in two flavours:
40bbf15aafSRichard Henderson  *
41bbf15aafSRichard Henderson  * (1) Non-interruptible syscalls
42bbf15aafSRichard Henderson  *
43bbf15aafSRichard Henderson  * These are guest syscalls that never get interrupted by signals and
44bbf15aafSRichard Henderson  * so never return EINTR. They can be implemented straightforwardly in
45bbf15aafSRichard Henderson  * QEMU: just make sure that if the implementation code has to make any
46bbf15aafSRichard Henderson  * blocking calls that those calls are retried if they return EINTR.
47bbf15aafSRichard Henderson  * It's also OK to implement these with safe_syscall, though it will be
48bbf15aafSRichard Henderson  * a little less efficient if a signal is delivered at the 'wrong' moment.
49bbf15aafSRichard Henderson  *
50bbf15aafSRichard Henderson  * Some non-interruptible syscalls need to be handled using block_signals()
51bbf15aafSRichard Henderson  * to block signals for the duration of the syscall. This mainly applies
52bbf15aafSRichard Henderson  * to code which needs to modify the data structures used by the
53bbf15aafSRichard Henderson  * host_signal_handler() function and the functions it calls, including
54bbf15aafSRichard Henderson  * all syscalls which change the thread's signal mask.
55bbf15aafSRichard Henderson  *
56bbf15aafSRichard Henderson  * (2) Interruptible syscalls
57bbf15aafSRichard Henderson  *
58bbf15aafSRichard Henderson  * These are guest syscalls that can be interrupted by signals and
59bbf15aafSRichard Henderson  * for which we need to either return EINTR or arrange for the guest
60bbf15aafSRichard Henderson  * syscall to be restarted. This category includes both syscalls which
61bbf15aafSRichard Henderson  * always restart (and in the kernel return -ERESTARTNOINTR), ones
62bbf15aafSRichard Henderson  * which only restart if there is no handler (kernel returns -ERESTARTNOHAND
63bbf15aafSRichard Henderson  * or -ERESTART_RESTARTBLOCK), and the most common kind which restart
64bbf15aafSRichard Henderson  * if the handler was registered with SA_RESTART (kernel returns
65bbf15aafSRichard Henderson  * -ERESTARTSYS). System calls which are only interruptible in some
66bbf15aafSRichard Henderson  * situations (like 'open') also need to be handled this way.
67bbf15aafSRichard Henderson  *
68bbf15aafSRichard Henderson  * Here it is important that the host syscall is made
69bbf15aafSRichard Henderson  * via this safe_syscall() function, and *not* via the host libc.
70bbf15aafSRichard Henderson  * If the host libc is used then the implementation will appear to work
71bbf15aafSRichard Henderson  * most of the time, but there will be a race condition where a
72bbf15aafSRichard Henderson  * signal could arrive just before we make the host syscall inside libc,
737a21bee2SDaniel P. Berrangé  * and then the guest syscall will not correctly be interrupted.
74bbf15aafSRichard Henderson  * Instead the implementation of the guest syscall can use the safe_syscall
75bbf15aafSRichard Henderson  * function but otherwise just return the result or errno in the usual
76bbf15aafSRichard Henderson  * way; the main loop code will take care of restarting the syscall
77bbf15aafSRichard Henderson  * if appropriate.
78bbf15aafSRichard Henderson  *
79bbf15aafSRichard Henderson  * (If the implementation needs to make multiple host syscalls this is
80bbf15aafSRichard Henderson  * OK; any which might really block must be via safe_syscall(); for those
81bbf15aafSRichard Henderson  * which are only technically blocking (ie which we know in practice won't
82bbf15aafSRichard Henderson  * stay in the host kernel indefinitely) it's OK to use libc if necessary.
83bbf15aafSRichard Henderson  * You must be able to cope with backing out correctly if some safe_syscall
84bbf15aafSRichard Henderson  * you make in the implementation returns either -QEMU_ERESTARTSYS or
85bbf15aafSRichard Henderson  * EINTR though.)
86bbf15aafSRichard Henderson  *
87bbf15aafSRichard Henderson  * block_signals() cannot be used for interruptible syscalls.
88bbf15aafSRichard Henderson  *
89bbf15aafSRichard Henderson  *
90bbf15aafSRichard Henderson  * How and why the safe_syscall implementation works:
91bbf15aafSRichard Henderson  *
92bbf15aafSRichard Henderson  * The basic setup is that we make the host syscall via a known
93bbf15aafSRichard Henderson  * section of host native assembly. If a signal occurs, our signal
94669dcb60SMichael Tokarev  * handler checks the interrupted host PC against the address of that
95bbf15aafSRichard Henderson  * known section. If the PC is before or at the address of the syscall
96bbf15aafSRichard Henderson  * instruction then we change the PC to point at a "return
97bbf15aafSRichard Henderson  * -QEMU_ERESTARTSYS" code path instead, and then exit the signal handler
98bbf15aafSRichard Henderson  * (causing the safe_syscall() call to immediately return that value).
99bbf15aafSRichard Henderson  * Then in the main.c loop if we see this magic return value we adjust
100bbf15aafSRichard Henderson  * the guest PC to wind it back to before the system call, and invoke
101bbf15aafSRichard Henderson  * the guest signal handler as usual.
102bbf15aafSRichard Henderson  *
103bbf15aafSRichard Henderson  * This winding-back will happen in two cases:
104bbf15aafSRichard Henderson  * (1) signal came in just before we took the host syscall (a race);
105bbf15aafSRichard Henderson  *   in this case we'll take the guest signal and have another go
106bbf15aafSRichard Henderson  *   at the syscall afterwards, and this is indistinguishable for the
107bbf15aafSRichard Henderson  *   guest from the timing having been different such that the guest
108bbf15aafSRichard Henderson  *   signal really did win the race
109bbf15aafSRichard Henderson  * (2) signal came in while the host syscall was blocking, and the
110bbf15aafSRichard Henderson  *   host kernel decided the syscall should be restarted;
111bbf15aafSRichard Henderson  *   in this case we want to restart the guest syscall also, and so
112bbf15aafSRichard Henderson  *   rewinding is the right thing. (Note that "restart" semantics mean
113bbf15aafSRichard Henderson  *   "first call the signal handler, then reattempt the syscall".)
114bbf15aafSRichard Henderson  * The other situation to consider is when a signal came in while the
115bbf15aafSRichard Henderson  * host syscall was blocking, and the host kernel decided that the syscall
116bbf15aafSRichard Henderson  * should not be restarted; in this case QEMU's host signal handler will
117bbf15aafSRichard Henderson  * be invoked with the PC pointing just after the syscall instruction,
118bbf15aafSRichard Henderson  * with registers indicating an EINTR return; the special code in the
119bbf15aafSRichard Henderson  * handler will not kick in, and we will return EINTR to the guest as
120bbf15aafSRichard Henderson  * we should.
121bbf15aafSRichard Henderson  *
122bbf15aafSRichard Henderson  * Notice that we can leave the host kernel to make the decision for
123bbf15aafSRichard Henderson  * us about whether to do a restart of the syscall or not; we do not
124bbf15aafSRichard Henderson  * need to check SA_RESTART flags in QEMU or distinguish the various
125bbf15aafSRichard Henderson  * kinds of restartability.
126bbf15aafSRichard Henderson  */
127bbf15aafSRichard Henderson 
128bbf15aafSRichard Henderson /* The core part of this function is implemented in assembly */
129f703f1efSPhilippe Mathieu-Daudé long safe_syscall_base(int *pending, long number, ...);
130f703f1efSPhilippe Mathieu-Daudé long safe_syscall_set_errno_tail(int value);
131bbf15aafSRichard Henderson 
132bbf15aafSRichard Henderson /* These are defined by the safe-syscall.inc.S file */
133bbf15aafSRichard Henderson extern char safe_syscall_start[];
134bbf15aafSRichard Henderson extern char safe_syscall_end[];
135bbf15aafSRichard Henderson 
136bbf15aafSRichard Henderson #define safe_syscall(...)                                                 \
137*e4e5cb4aSIlya Leoshkevich     safe_syscall_base(&get_task_state(thread_cpu)->signal_pending,        \
138bbf15aafSRichard Henderson                       __VA_ARGS__)
139bbf15aafSRichard Henderson 
140bbf15aafSRichard Henderson #endif
141