From nobody Tue Feb 10 03:44:59 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1494594702040266.14106727771104; Fri, 12 May 2017 06:11:42 -0700 (PDT) Received: from localhost ([::1]:53736 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d9AM7-0004Or-Lh for importer@patchew.org; Fri, 12 May 2017 09:11:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50048) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1d98LL-00043w-43 for qemu-devel@nongnu.org; Fri, 12 May 2017 07:02:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1d98LI-0006Se-C1 for qemu-devel@nongnu.org; Fri, 12 May 2017 07:02:43 -0400 Received: from mx2.rt-rk.com ([89.216.37.149]:46760 helo=mail.rt-rk.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1d98LI-0006Ri-0z for qemu-devel@nongnu.org; Fri, 12 May 2017 07:02:40 -0400 Received: from localhost (localhost [127.0.0.1]) by mail.rt-rk.com (Postfix) with ESMTP id 9616C1A49ED; Fri, 12 May 2017 13:02:12 +0200 (CEST) Received: from rtrkw488-lin.domain.local (unknown [10.10.14.90]) by mail.rt-rk.com (Postfix) with ESMTPSA id 41A591A49EC; Fri, 12 May 2017 13:02:12 +0200 (CEST) X-Virus-Scanned: amavisd-new at rt-rk.com From: =?UTF-8?q?Milo=C5=A1=20Stojanovi=C4=87?= To: qemu-devel@nongnu.org, riku.voipio@iki.fi Date: Fri, 12 May 2017 13:02:24 +0200 Message-Id: <1494586944-7253-17-git-send-email-Milos.Stojanovic@rt-rk.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1494586944-7253-1-git-send-email-Milos.Stojanovic@rt-rk.com> References: <1494586944-7253-1-git-send-email-Milos.Stojanovic@rt-rk.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 89.216.37.149 X-Mailman-Approved-At: Fri, 12 May 2017 09:02:56 -0400 Subject: [Qemu-devel] [PATCH 16/16] [RFC] linux-user: add support for multiplexing signals in rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill() syscalls. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Milos.Stojanovic@rt-rk.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add support for multiplexing in the host_signal_handler() function and in system calls rt_sigqueueinfo()/rt_tgsigqueueinfo(), tgkill(), kill() for the case when pid > 0. The rt_sigqueueinfo()/rt_tgsigqueueinfo() system calls multiplex target signals which are out of the host range by setting the si_errno value to the actual value of the signal and sending the signal to the MUX_SIG signal number. The host_signal_handler() will pull out the multiplexed signals and set their signal number to the correct value. That value should be in the si_errno field of the siginfo_t structure. The si_errno field is used here but this implementation can be replaced with any other unused field in the uinfo structure. The emulation of larger target signal range is done by spoofing the system call info, adding the signal number to the si_errno field, and sending it to the host multiplex queue via rt_sigqueueinfo()/rt_tgsigqueueinfo(). In order to send a signal using rt_sigqueueinfo()/rt_tgsigqueueinfo() with si_code SI_USER or SI_TKILL to another thread or process, we need to disguise it as some other signal from the kernel range because the host kernel doesn't allow direct impersonations of those signals. This is done with SIG_SPOOF which moves the si_code to the nearest unused kernel si_code value. After the signal is successfully sent the host_signal_handler() of the receiving thread/process will turn it back into the proper kill/tgkill signal, before it gets processed. The tkill() system call as well as kill() with the argument pid <=3D 0 couldn't be implemented simply using this method because it requires acquiring information about, and sending simultaneous signals to multiple threads or processes. These functionalities are out of the scope of rt_sigqueueinfo()/rt_tgsigqueueinfo(). Signed-off-by: Milo=C5=A1 Stojanovi=C4=87 --- linux-user/signal.c | 22 +++++++++++++ linux-user/syscall.c | 81 +++++++++++++++++++++++++++++++++++++++++++= ++++ linux-user/syscall_defs.h | 8 +++++ 3 files changed, 111 insertions(+) diff --git a/linux-user/signal.c b/linux-user/signal.c index 3d51424..eaa6643 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -787,6 +787,28 @@ static void host_signal_handler(int host_signum, sigin= fo_t *info, sig =3D host_to_target_signal(host_signum); if (sig < 1 || sig > TARGET_NSIG) return; + +#ifdef MUX_SIG + if (sig =3D=3D MUX_SIG) { + /* return the spoofed kill/tgkill signals into standard form */ + if (info->si_code =3D=3D SIG_SPOOF(SI_USER)) { + info->si_code =3D SI_USER; + } else if (info->si_code =3D=3D SIG_SPOOF(SI_TKILL)) { + info->si_code =3D SI_TKILL; + } + + /* + * We assume that si_errno field will remain intact during signal + * processing on the host. If it changes, the signal will be sent = to + * the wrong number (most likely to MUX_SIG). + */ + /* get the actual target signal number */ + int target_sig =3D info->si_errno; + if (target_sig >=3D _NSIG && target_sig < TARGET_NSIG) { + sig =3D target_sig; + } + } +#endif trace_user_host_signal(env, host_signum, sig); =20 rewind_if_in_safe_syscall(puc); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f4ce6a8..8190575 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7123,6 +7123,24 @@ static inline abi_long host_to_target_stat64(void *c= pu_env, return 0; } =20 +#ifdef MUX_SIG +static inline int multiplex(abi_long *arg, siginfo_t *uinfo) +{ + if (*arg >=3D _NSIG && *arg < TARGET_NSIG) { + /* + * Using si_errno to transfer the signal number assumes that the f= ield + * doesn't change its value before it gets handled in the + * host_signal_handler(). + */ + uinfo->si_errno =3D *arg; + *arg =3D MUX_SIG; + uinfo->si_signo =3D MUX_SIG; + } + + return 0; +} +#endif + /* ??? Using host futex calls even when target atomic operations are not really atomic probably breaks things. However implementing futexes locally would make futexes shared between multiple processes @@ -8258,7 +8276,42 @@ abi_long do_syscall(void *cpu_env, int num, abi_long= arg1, break; #endif case TARGET_NR_kill: +#ifdef MUX_SIG + if (arg2 >=3D _NSIG && arg2 < TARGET_NSIG) { + siginfo_t info; + + info.si_errno =3D arg2; + info.si_signo =3D MUX_SIG; + info.si_code =3D SIG_SPOOF(SI_USER); + info.si_pid =3D getpid(); + info.si_uid =3D getuid(); + + /* pid > 0 */ + if (arg1 > 0) { + ret =3D get_errno(sys_rt_sigqueueinfo(arg1, MUX_SIG, &info= )); + } else { + ret =3D -TARGET_EINVAL; + } + /* + * TODO: In order to implement kill with rt_tgsigqueueinfo() f= or + * cases where pid <=3D 0 one needs to get a list of all the r= elevant + * processes and simultaniously send the signal to them. + * Missing: + * (pid =3D 0): + * send to every process in the process group of + * the calling process + * (pid =3D -1): + * send to every process for which the calling process + * has permission to send signals, except for process 1 (i= nit) + * (pid < -1): + * send to every process in the process group whose ID is = -pid + */ + } else { + ret =3D get_errno(safe_kill(arg1, target_to_host_signal(arg2))= ); + } +#else ret =3D get_errno(safe_kill(arg1, target_to_host_signal(arg2))); +#endif break; #ifdef TARGET_NR_rename case TARGET_NR_rename: @@ -8929,6 +8982,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long = arg1, } target_to_host_siginfo(&uinfo, p); unlock_user(p, arg3, 0); +#ifdef MUX_SIG + multiplex(&arg2, &uinfo); +#endif ret =3D get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); } break; @@ -8942,6 +8998,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long = arg1, } target_to_host_siginfo(&uinfo, p); unlock_user(p, arg4, 0); +#ifdef MUX_SIG + multiplex(&arg3, &uinfo); +#endif ret =3D get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uin= fo)); } break; @@ -11743,12 +11802,34 @@ abi_long do_syscall(void *cpu_env, int num, abi_l= ong arg1, #endif =20 case TARGET_NR_tkill: + /* + * TODO: In order to implement tkill with rt_sigqueueinfo() one ne= eds + * to get a list of all the threads with the specifiend tid and + * simultaniously send the signal to them. + */ ret =3D get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2= ))); break; =20 case TARGET_NR_tgkill: +#ifdef MUX_SIG + if (arg3 >=3D _NSIG && arg3 < TARGET_NSIG) { + siginfo_t info; + + info.si_errno =3D arg3; + info.si_signo =3D MUX_SIG; + info.si_code =3D SIG_SPOOF(SI_TKILL); + info.si_pid =3D getpid(); + info.si_uid =3D getuid(); + + ret =3D get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, MUX_SIG, &= info)); + } else { + ret =3D get_errno(safe_tgkill((int)arg1, (int)arg2, + target_to_host_signal(arg3))); + } +#else ret =3D get_errno(safe_tgkill((int)arg1, (int)arg2, target_to_host_signal(arg3))); +#endif break; =20 #ifdef TARGET_NR_set_robust_list diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 42089fc..16cab53 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -412,6 +412,14 @@ struct target_dirent64 { * the host signal masks. */ #define TRACK_TARGET_SIGMASK + +/* + * This macro is used to change a kill/tgkill signal so it can be sent thr= ough + * rt_sigqueueinfo()/rt_tgsigqueueinfo(), since the host kernel doesn't al= low + * direct impersonations of those signals. Subtracting 8 from the code mov= es + * it to the nearest unused kernel si_code value. + */ +#define SIG_SPOOF(code) ((code) - 8) #endif =20 typedef struct { --=20 1.9.1