Skip to content
Snippets Groups Projects
  • Timothy Baldwin's avatar
    4d330cee
    linux-user: Provide safe_syscall for fixing races between signals and syscalls · 4d330cee
    Timothy Baldwin authored
    
    If a signal is delivered immediately before a blocking system call the
    handler will only be called after the system call returns, which may be a
    long time later or never.
    
    This is fixed by using a function (safe_syscall) that checks if a guest
    signal is pending prior to making a system call, and if so does not call the
    system call and returns -TARGET_ERESTARTSYS. If a signal is received between
    the check and the system call host_signal_handler() rewinds execution to
    before the check. This rewinding has the effect of closing the race window
    so that safe_syscall will reliably either (a) go into the host syscall
    with no unprocessed guest signals pending or or (b) return
    -TARGET_ERESTARTSYS so that the caller can deal with the signals.
    Implementing this requires a per-host-architecture assembly language
    fragment.
    
    This will also resolve the mishandling of the SA_RESTART flag where
    we would restart a host system call and not call the guest signal handler
    until the syscall finally completed -- syscall restarting now always
    happens at the guest syscall level so the guest signal handler will run.
    (The host syscall will never be restarted because if the host kernel
    rewinds the PC to point at the syscall insn for a restart then our
    host_signal_handler() will see this and arrange the guest PC rewind.)
    
    This commit contains the infrastructure for implementing safe_syscall
    and the assembly language fragment for x86-64, but does not change any
    syscalls to use it.
    
    Signed-off-by: default avatarTimothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
    Message-id: 1441497448-32489-14-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
    [PMM:
     * Avoid having an architecture if-ladder in configure by putting
       linux-user/host/$(ARCH) on the include path and including
       safe-syscall.inc.S from it
     * Avoid ifdef ladder in signal.c by creating new hostdep.h to hold
       host-architecture-specific things
     * Added copyright/license header to safe-syscall.inc.S
     * Rewrote commit message
     * Added comments to safe-syscall.inc.S
     * Changed calling convention of safe_syscall() to match syscall()
       (returns -1 and host error in errno on failure)
     * Added a long comment in qemu.h about how to use safe_syscall()
       to implement guest syscalls.
    ]
    RV: squashed Peters "fixup! linux-user: compile on non-x86-64 hosts"
    patch
    Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
    4d330cee
    History
    linux-user: Provide safe_syscall for fixing races between signals and syscalls
    Timothy Baldwin authored
    
    If a signal is delivered immediately before a blocking system call the
    handler will only be called after the system call returns, which may be a
    long time later or never.
    
    This is fixed by using a function (safe_syscall) that checks if a guest
    signal is pending prior to making a system call, and if so does not call the
    system call and returns -TARGET_ERESTARTSYS. If a signal is received between
    the check and the system call host_signal_handler() rewinds execution to
    before the check. This rewinding has the effect of closing the race window
    so that safe_syscall will reliably either (a) go into the host syscall
    with no unprocessed guest signals pending or or (b) return
    -TARGET_ERESTARTSYS so that the caller can deal with the signals.
    Implementing this requires a per-host-architecture assembly language
    fragment.
    
    This will also resolve the mishandling of the SA_RESTART flag where
    we would restart a host system call and not call the guest signal handler
    until the syscall finally completed -- syscall restarting now always
    happens at the guest syscall level so the guest signal handler will run.
    (The host syscall will never be restarted because if the host kernel
    rewinds the PC to point at the syscall insn for a restart then our
    host_signal_handler() will see this and arrange the guest PC rewind.)
    
    This commit contains the infrastructure for implementing safe_syscall
    and the assembly language fragment for x86-64, but does not change any
    syscalls to use it.
    
    Signed-off-by: default avatarTimothy Edward Baldwin <T.E.Baldwin99@members.leeds.ac.uk>
    Message-id: 1441497448-32489-14-git-send-email-T.E.Baldwin99@members.leeds.ac.uk
    [PMM:
     * Avoid having an architecture if-ladder in configure by putting
       linux-user/host/$(ARCH) on the include path and including
       safe-syscall.inc.S from it
     * Avoid ifdef ladder in signal.c by creating new hostdep.h to hold
       host-architecture-specific things
     * Added copyright/license header to safe-syscall.inc.S
     * Rewrote commit message
     * Added comments to safe-syscall.inc.S
     * Changed calling convention of safe_syscall() to match syscall()
       (returns -1 and host error in errno on failure)
     * Added a long comment in qemu.h about how to use safe_syscall()
       to implement guest syscalls.
    ]
    RV: squashed Peters "fixup! linux-user: compile on non-x86-64 hosts"
    patch
    Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>