Est-ce que linux autorise tout appel système à partir de gestionnaires de signaux?

D’après ce que je comprends, en général, le comportement n’est pas défini si vous appelez une fonction de sécurité de signal non asynchrone à partir d’un gestionnaire de signal, mais j’ai entendu que Linux vous permet d’appeler n’importe quel appel système en toute sécurité. Est-ce vrai? En outre, le seul comportement portable pour un gestionnaire SIGSEGV est d’abandonner ou de quitter, mais je comprends que Linux va effectivement reprendre l’exécution si vous revenez, vrai?

Je pense que tout appel système réel peut être appelé par un gestionnaire de signal. Un vrai appel système a un numéro dans (ou ).

certaines fonctions posix de la section 2 des pages de manuel sont implémentées par un appel système “multiplexage”, elles ne sont donc pas de “vrais appels système”

Un appel système est une opération atomique du sharepoint vue de l’application; c’est presque comme une seule instruction machine (de l’intérieur de l’application). Voir cette réponse .

Si votre question est la suivante: un gestionnaire SIGSEGV peut-il modifier le mappage d’adresse défectueux via mprotect ou mmap ? alors je crois que la réponse est oui (au moins sur les architectures x86-64 et x86-32), comme dit ici dans une question que vous avez citée, mais je n’ai pas essayé. J’ai lu que faire cela est assez inefficace (la gestion de SIGSEGV n’est pas très rapide, et mprotect ou mmap est également un peu lent). En particulier, imiter ainsi les pagers externes Hurd / Mach pourrait être inefficace.

Selon la section 2 signal manuel de signal :

Voir le signal (7) pour une liste des fonctions async-signal-safe qui peuvent être appelées en toute sécurité depuis un gestionnaire de signal.

Et le manuel des signals section 7 répertorie les fonctions suivantes et / ou les appels système avec une description assez claire:

Fonctions asynchrones-signal-sûres

  A signal handler function must be very careful, since processing elsewhere may be interrupted at some arbitrary point in the execution of the program. POSIX has the concept of "safe function". If a signal interrupts the execution of an unsafe function, and handler calls an unsafe function, then the behavior of the program is undefined. POSIX.1-2004 (also known as POSIX.1-2001 Technical Corrigendum 2) requires an implementation to guarantee that the following functions can be safely called inside a signal handler: _Exit() _exit() abort() accept() access() aio_error() aio_return() aio_suspend() alarm() bind() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect() creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdatasync() fork() fpathconf() fstat() fsync() ftruncate() getegid() geteuid() getgid() getgroups() getpeername() getpgrp() getpid() getppid() getsockname() getsockopt() getuid() kill() link() listen() lseek() lstat() mkdir() mkfifo() open() pathconf() pause() pipe() poll() posix_trace_event() pselect() raise() read() readlink() recv() recvfrom() recvmsg() rename() rmdir() select() sem_post() send() sendmsg() sendto() setgid() setpgid() setsid() setsockopt() setuid() shutdown() sigaction() sigaddset() sigdelset() sigemptyset() sigfillset() sigismember() signal() sigpause() sigpending() sigprocmask() sigqueue() sigset() sigsuspend() sleep() sockatmark() socket() socketpair() stat() symlink() sysconf() tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak() tcsetattr() tcsetpgrp() time() timer_getoverrun() timer_gettime() timer_settime() times() umask() uname() unlink() utime() wait() waitpid() write() POSIX.1-2008 removes fpathconf(), pathconf(), and sysconf() from the above list, and adds the following functions: execl() execv() faccessat() fchmodat() fchownat() fexecve() fstatat() futimens() linkat() mkdirat() mkfifoat() mknod() mknodat() openat() readlinkat() renameat() symlinkat() unlinkat() utimensat() utimes() 

Je crois que cette information est plus fiable que quelque chose que nous entendons parfois quelque part. Ainsi, Linux n’autorise que certains appels système, mais pas tous. Donc, la réponse à votre question est simple – non.

Oui et non

Oui:

Vous pouvez appeler n’importe quel appel système réel / brut dans un gestionnaire de signal. Le kernel a la responsabilité de s’assurer de la sécurité (du sharepoint vue du kernel).

1) Le kernel ne connaît pas le contexte de l’espace utilisateur ou dit que le kernel l’oublie volontairement après avoir sauvegardé l’état dans l’espace utilisateur lorsqu’il reçoit le signal. (NOTE: l’exécution de la reprise est faite par l’utilisateur via un appel système avec l’aide des états enregistrés, pas vraiment par le kernel, le kernel a déjà oublié)

2) certaines librairies de threads sont implémentées via des singles, donc les threads sont déjà dans le “gestionnaire de signaux”, mais ces threads peuvent appeler n’importe quel appel syscall.

NON:

Mais les fonctions de l’espace utilisateur ont leur propre objective et effet secondaire. Certains ne sont pas ré-entrées en sécurité , ces fonctions ne peuvent pas être appelées par le gestionnaire de signaux. man 7 signal vous aidera à trouver ceux qui sont à nouveau en sécurité.

Par exemple, vous pouvez appeler sys_futex() n’importe où, y compris le gestionnaire de signaux, mais si vous utilisez sys_futex() pour implémenter un mutex, le gestionnaire de signaux sys_futex() peut être bloqué lorsque le signal interrompt la section critique du mutex.

En outre, le seul comportement portable pour un gestionnaire SIGSEGV est d’abandonner ou de quitter, mais je comprends que Linux va effectivement reprendre l’exécution si vous revenez, vrai?

Oui, si vous ne pouvez pas trouver la raison. Certains utilisateurs peuvent utiliser SIGSEGV pour leur propre usage à la demande de carte (exemple, dans JIT, vous pouvez traduire le code dans le gestionnaire de signaux SIGSEGV et mapper le code traduit dans la mémoire puis retourner), ils peuvent appeler mmap () ou mprotect () …etc.