signal.c (ef6a778ea2af4ebcf08a84cc9314cfe7cf2a2299) | signal.c (a70dadc7f1a3e96a7179c6c3a6ccd1a0ea65760a) |
---|---|
1/* 2 * Emulation of Linux signals 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19#include "qemu/osdep.h" | 1/* 2 * Emulation of Linux signals 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19#include "qemu/osdep.h" |
20#include "qemu/bitops.h" |
|
20#include <sys/ucontext.h> 21#include <sys/resource.h> 22 23#include "qemu.h" 24#include "qemu-common.h" 25#include "target_signal.h" 26#include "trace.h" 27 --- 241 unchanged lines hidden (view full) --- 269#endif 270 271/* siginfo conversion */ 272 273static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, 274 const siginfo_t *info) 275{ 276 int sig = host_to_target_signal(info->si_signo); | 21#include <sys/ucontext.h> 22#include <sys/resource.h> 23 24#include "qemu.h" 25#include "qemu-common.h" 26#include "target_signal.h" 27#include "trace.h" 28 --- 241 unchanged lines hidden (view full) --- 270#endif 271 272/* siginfo conversion */ 273 274static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, 275 const siginfo_t *info) 276{ 277 int sig = host_to_target_signal(info->si_signo); |
278 int si_code = info->si_code; 279 int si_type; |
|
277 tinfo->si_signo = sig; 278 tinfo->si_errno = 0; 279 tinfo->si_code = info->si_code; 280 | 280 tinfo->si_signo = sig; 281 tinfo->si_errno = 0; 282 tinfo->si_code = info->si_code; 283 |
281 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV 282 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { 283 /* Should never come here, but who knows. The information for 284 the target is irrelevant. */ 285 tinfo->_sifields._sigfault._addr = 0; 286 } else if (sig == TARGET_SIGIO) { 287 tinfo->_sifields._sigpoll._band = info->si_band; 288 tinfo->_sifields._sigpoll._fd = info->si_fd; 289 } else if (sig == TARGET_SIGCHLD) { 290 tinfo->_sifields._sigchld._pid = info->si_pid; 291 tinfo->_sifields._sigchld._uid = info->si_uid; 292 tinfo->_sifields._sigchld._status | 284 /* This is awkward, because we have to use a combination of 285 * the si_code and si_signo to figure out which of the union's 286 * members are valid. (Within the host kernel it is always possible 287 * to tell, but the kernel carefully avoids giving userspace the 288 * high 16 bits of si_code, so we don't have the information to 289 * do this the easy way...) We therefore make our best guess, 290 * bearing in mind that a guest can spoof most of the si_codes 291 * via rt_sigqueueinfo() if it likes. 292 * 293 * Once we have made our guess, we record it in the top 16 bits of 294 * the si_code, so that tswap_siginfo() later can use it. 295 * tswap_siginfo() will strip these top bits out before writing 296 * si_code to the guest (sign-extending the lower bits). 297 */ 298 299 switch (si_code) { 300 case SI_USER: 301 case SI_TKILL: 302 case SI_KERNEL: 303 /* Sent via kill(), tkill() or tgkill(), or direct from the kernel. 304 * These are the only unspoofable si_code values. 305 */ 306 tinfo->_sifields._kill._pid = info->si_pid; 307 tinfo->_sifields._kill._uid = info->si_uid; 308 si_type = QEMU_SI_KILL; 309 break; 310 default: 311 /* Everything else is spoofable. Make best guess based on signal */ 312 switch (sig) { 313 case TARGET_SIGCHLD: 314 tinfo->_sifields._sigchld._pid = info->si_pid; 315 tinfo->_sifields._sigchld._uid = info->si_uid; 316 tinfo->_sifields._sigchld._status |
293 = host_to_target_waitstatus(info->si_status); | 317 = host_to_target_waitstatus(info->si_status); |
294 tinfo->_sifields._sigchld._utime = info->si_utime; 295 tinfo->_sifields._sigchld._stime = info->si_stime; 296 } else if (sig >= TARGET_SIGRTMIN) { 297 tinfo->_sifields._rt._pid = info->si_pid; 298 tinfo->_sifields._rt._uid = info->si_uid; 299 /* XXX: potential problem if 64 bit */ 300 tinfo->_sifields._rt._sigval.sival_ptr | 318 tinfo->_sifields._sigchld._utime = info->si_utime; 319 tinfo->_sifields._sigchld._stime = info->si_stime; 320 si_type = QEMU_SI_CHLD; 321 break; 322 case TARGET_SIGIO: 323 tinfo->_sifields._sigpoll._band = info->si_band; 324 tinfo->_sifields._sigpoll._fd = info->si_fd; 325 si_type = QEMU_SI_POLL; 326 break; 327 default: 328 /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */ 329 tinfo->_sifields._rt._pid = info->si_pid; 330 tinfo->_sifields._rt._uid = info->si_uid; 331 /* XXX: potential problem if 64 bit */ 332 tinfo->_sifields._rt._sigval.sival_ptr |
301 = (abi_ulong)(unsigned long)info->si_value.sival_ptr; | 333 = (abi_ulong)(unsigned long)info->si_value.sival_ptr; |
334 si_type = QEMU_SI_RT; 335 break; 336 } 337 break; |
|
302 } | 338 } |
339 340 tinfo->si_code = deposit32(si_code, 16, 16, si_type); |
|
303} 304 305static void tswap_siginfo(target_siginfo_t *tinfo, 306 const target_siginfo_t *info) 307{ | 341} 342 343static void tswap_siginfo(target_siginfo_t *tinfo, 344 const target_siginfo_t *info) 345{ |
308 int sig = info->si_signo; 309 tinfo->si_signo = tswap32(sig); 310 tinfo->si_errno = tswap32(info->si_errno); 311 tinfo->si_code = tswap32(info->si_code); | 346 int si_type = extract32(info->si_code, 16, 16); 347 int si_code = sextract32(info->si_code, 0, 16); |
312 | 348 |
313 if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV 314 || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { 315 tinfo->_sifields._sigfault._addr 316 = tswapal(info->_sifields._sigfault._addr); 317 } else if (sig == TARGET_SIGIO) { 318 tinfo->_sifields._sigpoll._band 319 = tswap32(info->_sifields._sigpoll._band); 320 tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); 321 } else if (sig == TARGET_SIGCHLD) { 322 tinfo->_sifields._sigchld._pid 323 = tswap32(info->_sifields._sigchld._pid); 324 tinfo->_sifields._sigchld._uid 325 = tswap32(info->_sifields._sigchld._uid); 326 tinfo->_sifields._sigchld._status 327 = tswap32(info->_sifields._sigchld._status); 328 tinfo->_sifields._sigchld._utime 329 = tswapal(info->_sifields._sigchld._utime); 330 tinfo->_sifields._sigchld._stime 331 = tswapal(info->_sifields._sigchld._stime); 332 } else if (sig >= TARGET_SIGRTMIN) { 333 tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid); 334 tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid); 335 tinfo->_sifields._rt._sigval.sival_ptr 336 = tswapal(info->_sifields._rt._sigval.sival_ptr); | 349 __put_user(info->si_signo, &tinfo->si_signo); 350 __put_user(info->si_errno, &tinfo->si_errno); 351 __put_user(si_code, &tinfo->si_code); 352 353 /* We can use our internal marker of which fields in the structure 354 * are valid, rather than duplicating the guesswork of 355 * host_to_target_siginfo_noswap() here. 356 */ 357 switch (si_type) { 358 case QEMU_SI_KILL: 359 __put_user(info->_sifields._kill._pid, &tinfo->_sifields._kill._pid); 360 __put_user(info->_sifields._kill._uid, &tinfo->_sifields._kill._uid); 361 break; 362 case QEMU_SI_TIMER: 363 __put_user(info->_sifields._timer._timer1, 364 &tinfo->_sifields._timer._timer1); 365 __put_user(info->_sifields._timer._timer2, 366 &tinfo->_sifields._timer._timer2); 367 break; 368 case QEMU_SI_POLL: 369 __put_user(info->_sifields._sigpoll._band, 370 &tinfo->_sifields._sigpoll._band); 371 __put_user(info->_sifields._sigpoll._fd, 372 &tinfo->_sifields._sigpoll._fd); 373 break; 374 case QEMU_SI_FAULT: 375 __put_user(info->_sifields._sigfault._addr, 376 &tinfo->_sifields._sigfault._addr); 377 break; 378 case QEMU_SI_CHLD: 379 __put_user(info->_sifields._sigchld._pid, 380 &tinfo->_sifields._sigchld._pid); 381 __put_user(info->_sifields._sigchld._uid, 382 &tinfo->_sifields._sigchld._uid); 383 __put_user(info->_sifields._sigchld._status, 384 &tinfo->_sifields._sigchld._status); 385 __put_user(info->_sifields._sigchld._utime, 386 &tinfo->_sifields._sigchld._utime); 387 __put_user(info->_sifields._sigchld._stime, 388 &tinfo->_sifields._sigchld._stime); 389 break; 390 case QEMU_SI_RT: 391 __put_user(info->_sifields._rt._pid, &tinfo->_sifields._rt._pid); 392 __put_user(info->_sifields._rt._uid, &tinfo->_sifields._rt._uid); 393 __put_user(info->_sifields._rt._sigval.sival_ptr, 394 &tinfo->_sifields._rt._sigval.sival_ptr); 395 break; 396 default: 397 g_assert_not_reached(); |
337 } 338} 339 | 398 } 399} 400 |
340 | |
341void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) 342{ 343 host_to_target_siginfo_noswap(tinfo, info); 344 tswap_siginfo(tinfo, tinfo); 345} 346 347/* XXX: we support only POSIX RT signals are used. */ 348/* XXX: find a solution for 64 bit (additional malloced data is needed) */ --- 151 unchanged lines hidden (view full) --- 500 as possible */ 501int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) 502{ 503 CPUState *cpu = ENV_GET_CPU(env); 504 TaskState *ts = cpu->opaque; 505 506 trace_user_queue_signal(env, sig); 507 | 401void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) 402{ 403 host_to_target_siginfo_noswap(tinfo, info); 404 tswap_siginfo(tinfo, tinfo); 405} 406 407/* XXX: we support only POSIX RT signals are used. */ 408/* XXX: find a solution for 64 bit (additional malloced data is needed) */ --- 151 unchanged lines hidden (view full) --- 560 as possible */ 561int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) 562{ 563 CPUState *cpu = ENV_GET_CPU(env); 564 TaskState *ts = cpu->opaque; 565 566 trace_user_queue_signal(env, sig); 567 |
568 /* Currently all callers define siginfo structures which 569 * use the _sifields._sigfault union member, so we can 570 * set the type here. If that changes we should push this 571 * out so the si_type is passed in by callers. 572 */ 573 info->si_code = deposit32(info->si_code, 16, 16, QEMU_SI_FAULT); 574 |
|
508 ts->sync_signal.info = *info; 509 ts->sync_signal.pending = sig; 510 /* signal that a new signal is pending */ 511 atomic_set(&ts->signal_pending, 1); 512 return 1; /* indicates that the signal was queued */ 513} 514 515#ifndef HAVE_SAFE_SYSCALL --- 5371 unchanged lines hidden --- | 575 ts->sync_signal.info = *info; 576 ts->sync_signal.pending = sig; 577 /* signal that a new signal is pending */ 578 atomic_set(&ts->signal_pending, 1); 579 return 1; /* indicates that the signal was queued */ 580} 581 582#ifndef HAVE_SAFE_SYSCALL --- 5371 unchanged lines hidden --- |