mirror of https://github.com/xemu-project/xemu.git
Implement TARGET_SO_PEERSEC
Fix rt signals management -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAl5FPyISHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748z/sP/iXFvyZmpydvZOfE23+XOnrn2LihYnJe 0WgXmdJz4Ie5kJ0LUzM9iDdRJ9jTMpSSqfrflLUFpaKHOiFo4VPkRRrV90aDnCYB l/Wou2haCHavm7KVd/hTw4R5w97zZwXhSRb9j5dgplmT8WM5mCrIPx82LP0ZhPes MwVTKSbckKizEX4T5P4YtD75BmPSwJvFBDxAfz7hyYSnNvmRybaYQP+di73HFCI7 Ux1ossYUs0HSf0AwENavza07NF53kimLqGXFOX/K0ALqvcx1dknF69TtLSo29vwR +Hu8wRHkyZb6EESc+pXKcHJYxIBWB4LXp6KFDkP/NEBcARcCe41kVn4SHaejy1oE 4il6OHzc0FlB7ws3kdDF/lQSJl9sECVeOGLk/n724taY4mLtzcXBfTFnhTyPHDBO 8L98jjUJr8BbzbaCMnozVaEMxavodw30CZyv2AwgzCi37pqWHISuneq6679uJQvT o91Md43ZHMGrCpCoiJ+FaI4ubAhZDK2H09l6r1WoFYgeHz5EoiRk/b3qOJ1ato2t cjWssOeoSpBSG893ZoH5LdVSM0qtjuQLHowUxu9uWbr28DPkJFNqNtY1Vp0fd/0i Uhuw3lygulnzLLQWToWVLmorrlqBFp+/mdQ+X+dXMK5b+1I1Aw2wr4947JwdsYB8 boYSTv1rgYbL =ooan -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0-pull-request' into staging Implement TARGET_SO_PEERSEC Fix rt signals management # gpg: Signature made Thu 13 Feb 2020 12:20:50 GMT # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-5.0-pull-request: linux-user: implement TARGET_SO_PEERSEC linux-user: fix use of SIGRTMIN linux-user: fix TARGET_NSIG and _NSIG uses linux-user: cleanup signal.c linux-user: add missing TARGET_SIGRTMIN for hppa Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # linux-user/signal.c
This commit is contained in:
commit
71cd1bccf3
|
@ -34,6 +34,7 @@
|
|||
#define TARGET_SIGURG 29
|
||||
#define TARGET_SIGXFSZ 30
|
||||
#define TARGET_SIGSYS 31
|
||||
#define TARGET_SIGRTMIN 32
|
||||
|
||||
#define TARGET_SIG_BLOCK 0
|
||||
#define TARGET_SIG_UNBLOCK 1
|
||||
|
|
|
@ -30,6 +30,15 @@ static struct target_sigaction sigact_table[TARGET_NSIG];
|
|||
static void host_signal_handler(int host_signum, siginfo_t *info,
|
||||
void *puc);
|
||||
|
||||
|
||||
/*
|
||||
* System includes define _NSIG as SIGRTMAX + 1,
|
||||
* but qemu (like the kernel) defines TARGET_NSIG as TARGET_SIGRTMAX
|
||||
* and the first signal is SIGHUP defined as 1
|
||||
* Signal number 0 is reserved for use as kill(pid, 0), to test whether
|
||||
* a process exists without sending it a signal.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
|
||||
static uint8_t host_to_target_signal_table[_NSIG] = {
|
||||
[SIGHUP] = TARGET_SIGHUP,
|
||||
[SIGINT] = TARGET_SIGINT,
|
||||
|
@ -66,26 +75,25 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
|
|||
[SIGPWR] = TARGET_SIGPWR,
|
||||
[SIGSYS] = TARGET_SIGSYS,
|
||||
/* next signals stay the same */
|
||||
/* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with
|
||||
host libpthread signals. This assumes no one actually uses SIGRTMAX :-/
|
||||
To fix this properly we need to do manual signal delivery multiplexed
|
||||
over a single host signal. */
|
||||
[__SIGRTMIN] = __SIGRTMAX,
|
||||
[__SIGRTMAX] = __SIGRTMIN,
|
||||
};
|
||||
static uint8_t target_to_host_signal_table[_NSIG];
|
||||
|
||||
static uint8_t target_to_host_signal_table[TARGET_NSIG + 1];
|
||||
|
||||
/* valid sig is between 1 and _NSIG - 1 */
|
||||
int host_to_target_signal(int sig)
|
||||
{
|
||||
if (sig < 0 || sig >= _NSIG)
|
||||
if (sig < 1 || sig >= _NSIG) {
|
||||
return sig;
|
||||
}
|
||||
return host_to_target_signal_table[sig];
|
||||
}
|
||||
|
||||
/* valid sig is between 1 and TARGET_NSIG */
|
||||
int target_to_host_signal(int sig)
|
||||
{
|
||||
if (sig < 0 || sig >= _NSIG)
|
||||
if (sig < 1 || sig > TARGET_NSIG) {
|
||||
return sig;
|
||||
}
|
||||
return target_to_host_signal_table[sig];
|
||||
}
|
||||
|
||||
|
@ -106,11 +114,15 @@ static inline int target_sigismember(const target_sigset_t *set, int signum)
|
|||
void host_to_target_sigset_internal(target_sigset_t *d,
|
||||
const sigset_t *s)
|
||||
{
|
||||
int i;
|
||||
int host_sig, target_sig;
|
||||
target_sigemptyset(d);
|
||||
for (i = 1; i <= TARGET_NSIG; i++) {
|
||||
if (sigismember(s, i)) {
|
||||
target_sigaddset(d, host_to_target_signal(i));
|
||||
for (host_sig = 1; host_sig < _NSIG; host_sig++) {
|
||||
target_sig = host_to_target_signal(host_sig);
|
||||
if (target_sig < 1 || target_sig > TARGET_NSIG) {
|
||||
continue;
|
||||
}
|
||||
if (sigismember(s, host_sig)) {
|
||||
target_sigaddset(d, target_sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,11 +140,15 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
|
|||
void target_to_host_sigset_internal(sigset_t *d,
|
||||
const target_sigset_t *s)
|
||||
{
|
||||
int i;
|
||||
int host_sig, target_sig;
|
||||
sigemptyset(d);
|
||||
for (i = 1; i <= TARGET_NSIG; i++) {
|
||||
if (target_sigismember(s, i)) {
|
||||
sigaddset(d, target_to_host_signal(i));
|
||||
for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) {
|
||||
host_sig = target_to_host_signal(target_sig);
|
||||
if (host_sig < 1 || host_sig >= _NSIG) {
|
||||
continue;
|
||||
}
|
||||
if (target_sigismember(s, target_sig)) {
|
||||
sigaddset(d, host_sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,37 +496,72 @@ static int core_dump_signal(int sig)
|
|||
}
|
||||
}
|
||||
|
||||
static void signal_table_init(void)
|
||||
{
|
||||
int host_sig, target_sig, count;
|
||||
|
||||
/*
|
||||
* Signals are supported starting from TARGET_SIGRTMIN and going up
|
||||
* until we run out of host realtime signals.
|
||||
* glibc at least uses only the lower 2 rt signals and probably
|
||||
* nobody's using the upper ones.
|
||||
* it's why SIGRTMIN (34) is generally greater than __SIGRTMIN (32)
|
||||
* To fix this properly we need to do manual signal delivery multiplexed
|
||||
* over a single host signal.
|
||||
* Attempts for configure "missing" signals via sigaction will be
|
||||
* silently ignored.
|
||||
*/
|
||||
for (host_sig = SIGRTMIN; host_sig <= SIGRTMAX; host_sig++) {
|
||||
target_sig = host_sig - SIGRTMIN + TARGET_SIGRTMIN;
|
||||
if (target_sig <= TARGET_NSIG) {
|
||||
host_to_target_signal_table[host_sig] = target_sig;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate signal conversion tables */
|
||||
for (target_sig = 1; target_sig <= TARGET_NSIG; target_sig++) {
|
||||
target_to_host_signal_table[target_sig] = _NSIG; /* poison */
|
||||
}
|
||||
for (host_sig = 1; host_sig < _NSIG; host_sig++) {
|
||||
if (host_to_target_signal_table[host_sig] == 0) {
|
||||
host_to_target_signal_table[host_sig] = host_sig;
|
||||
}
|
||||
target_sig = host_to_target_signal_table[host_sig];
|
||||
if (target_sig <= TARGET_NSIG) {
|
||||
target_to_host_signal_table[target_sig] = host_sig;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace_event_get_state_backends(TRACE_SIGNAL_TABLE_INIT)) {
|
||||
for (target_sig = 1, count = 0; target_sig <= TARGET_NSIG; target_sig++) {
|
||||
if (target_to_host_signal_table[target_sig] == _NSIG) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
trace_signal_table_init(count);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_init(void)
|
||||
{
|
||||
TaskState *ts = (TaskState *)thread_cpu->opaque;
|
||||
struct sigaction act;
|
||||
struct sigaction oact;
|
||||
int i, j;
|
||||
int i;
|
||||
int host_sig;
|
||||
|
||||
/* generate signal conversion tables */
|
||||
for(i = 1; i < _NSIG; i++) {
|
||||
if (host_to_target_signal_table[i] == 0)
|
||||
host_to_target_signal_table[i] = i;
|
||||
}
|
||||
for(i = 1; i < _NSIG; i++) {
|
||||
j = host_to_target_signal_table[i];
|
||||
target_to_host_signal_table[j] = i;
|
||||
}
|
||||
/* initialize signal conversion tables */
|
||||
signal_table_init();
|
||||
|
||||
/* Set the signal mask from the host mask. */
|
||||
sigprocmask(0, 0, &ts->signal_mask);
|
||||
|
||||
/* set all host signal handlers. ALL signals are blocked during
|
||||
the handlers to serialize them. */
|
||||
memset(sigact_table, 0, sizeof(sigact_table));
|
||||
|
||||
sigfillset(&act.sa_mask);
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = host_signal_handler;
|
||||
for(i = 1; i <= TARGET_NSIG; i++) {
|
||||
#ifdef CONFIG_GPROF
|
||||
if (i == SIGPROF) {
|
||||
if (i == TARGET_SIGPROF) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
@ -787,6 +838,8 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|
|||
int host_sig;
|
||||
int ret = 0;
|
||||
|
||||
trace_signal_do_sigaction_guest(sig, TARGET_NSIG);
|
||||
|
||||
if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
@ -817,6 +870,23 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|
|||
|
||||
/* we update the host linux signal state */
|
||||
host_sig = target_to_host_signal(sig);
|
||||
trace_signal_do_sigaction_host(host_sig, TARGET_NSIG);
|
||||
if (host_sig > SIGRTMAX) {
|
||||
/* we don't have enough host signals to map all target signals */
|
||||
qemu_log_mask(LOG_UNIMP, "Unsupported target signal #%d, ignored\n",
|
||||
sig);
|
||||
/*
|
||||
* we don't return an error here because some programs try to
|
||||
* register an handler for all possible rt signals even if they
|
||||
* don't need it.
|
||||
* An error here can abort them whereas there can be no problem
|
||||
* to not have the signal available later.
|
||||
* This is the case for golang,
|
||||
* See https://github.com/golang/go/issues/33746
|
||||
* So we silently ignore the error.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
|
||||
sigfillset(&act1.sa_mask);
|
||||
act1.sa_flags = SA_SIGINFO;
|
||||
|
|
|
@ -2344,6 +2344,28 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case TARGET_SO_PEERSEC: {
|
||||
char *name;
|
||||
|
||||
if (get_user_u32(len, optlen)) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
if (len < 0) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
|
||||
if (!name) {
|
||||
return -TARGET_EFAULT;
|
||||
}
|
||||
lv = len;
|
||||
ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
|
||||
name, &lv));
|
||||
if (put_user_u32(lv, optlen)) {
|
||||
ret = -TARGET_EFAULT;
|
||||
}
|
||||
unlock_user(name, optval_addr, lv);
|
||||
break;
|
||||
}
|
||||
case TARGET_SO_LINGER:
|
||||
{
|
||||
struct linger lg;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# signal.c
|
||||
signal_table_init(int i) "number of unavailable signals: %d"
|
||||
signal_do_sigaction_guest(int sig, int max) "target signal %d (MAX %d)"
|
||||
signal_do_sigaction_host(int sig, int max) "host signal %d (MAX %d)"
|
||||
# */signal.c
|
||||
user_setup_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||
user_setup_rt_frame(void *env, uint64_t frame_addr) "env=%p frame_addr=0x%"PRIx64
|
||||
|
|
Loading…
Reference in New Issue