Je veux écrire un gestionnaire de signal pour attraper SIGSEGV. Tout d'abord, je protège un bloc de mémoire pour la lecture ou l'écriture en utilisant la fonction
char *buffer;
char *p;
char a;
int pagesize = 4096;
" mprotect(buffer,pagesize,PROT_NONE) "
Ce que cela va faire, c'est protéger la mémoire à partir du tampon jusqu'à la taille de la page pour toute lecture ou écriture.
Ensuite, je vais essayer de lire la mémoire en faisant quelque chose du genre
p = buffer;
a = *p
Cela va générer un SIGSEGV et j'ai initialisé un gestionnaire pour cela. Le gestionnaire sera appelé. Jusqu'ici tout va bien. Maintenant, le problème auquel je suis confronté est qu'une fois que le gestionnaire est appelé, je veux changer l'accès en écriture de la mémoire en faisant
mprotect(buffer, pagesize,PROT_READ);
et continuer mon fonctionnement normal du code. Je ne veux pas quitter la fonction. Lors de futures écritures dans la même mémoire, je veux à nouveau capter le signal et modifier les droits d'écriture, puis tenir compte de cet événement.
Voici le code que j'essaie d'utiliser :
#include <signal.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/mman.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
char *buffer;
int flag=0;
static void handler(int sig, siginfo_t *si, void *unused)
{
printf("Got SIGSEGV at address: 0x%lx\n",(long) si->si_addr);
printf("Implements the handler only\n");
flag=1;
//exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
char *p; char a;
int pagesize;
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
handle_error("sigaction");
pagesize=4096;
/* Allocate a buffer aligned on a page boundary;
initial protection is PROT_READ | PROT_WRITE */
buffer = memalign(pagesize, 4 * pagesize);
if (buffer == NULL)
handle_error("memalign");
printf("Start of region: 0x%lx\n", (long) buffer);
printf("Start of region: 0x%lx\n", (long) buffer+pagesize);
printf("Start of region: 0x%lx\n", (long) buffer+2*pagesize);
printf("Start of region: 0x%lx\n", (long) buffer+3*pagesize);
//if (mprotect(buffer + pagesize * 0, pagesize,PROT_NONE) == -1)
if (mprotect(buffer + pagesize * 0, pagesize,PROT_NONE) == -1)
handle_error("mprotect");
//for (p = buffer ; ; )
if(flag==0)
{
p = buffer+pagesize/2;
printf("It comes here before reading memory\n");
a = *p; //trying to read the memory
printf("It comes here after reading memory\n");
}
else
{
if (mprotect(buffer + pagesize * 0, pagesize,PROT_READ) == -1)
handle_error("mprotect");
a = *p;
printf("Now i can read the memory\n");
}
/* for (p = buffer;p<=buffer+4*pagesize ;p++ )
{
//a = *(p);
*(p) = 'a';
printf("Writing at address %p\n",p);
}*/
printf("Loop completed\n"); /* Should never happen */
exit(EXIT_SUCCESS);
}
Le problème auquel je suis confronté est que seul le gestionnaire de signal est en cours d'exécution et je ne suis pas en mesure de revenir à la fonction principale après avoir attrapé le signal .
Toute aide dans ce domaine sera grandement appréciée.
Merci d'avance Aditya
2 votes
Merci Nos pour l'édition. J'apprécie. J'ai besoin de passer un peu de temps pour apprendre à éditer mes questions
1 votes
Lors de la compilation, activez toujours tous les avertissements, puis corrigez ces avertissements. (pour
gcc
au moins l'utiliser :-Wall -Wextra -pedantic
J'utilise aussi :-Wconversion -std=gnu99
) Le compilateur vous le dira : 1) le paramètreargc
inutilisé 2) paramètreargv
inutilisé (suggérer d'utiliser la signature main() de :int main( void )
3) variable localep
utilisé dans leelse
sans être initialisé. 4) paramètreunused
inutilisés, suggérer : ajouter une déclaration :(void)unused;
comme première ligne de cette fonction. 5) variable localea
fixé mais non utilisé.1 votes
N'utilisez JAMAIS
printf()
dans un gestionnaire de signaux ! La fonctionwrite()
peut être utilisé, mais le mieux est de ne pas faire d'entrées/sorties dans un gestionnaire de signaux, il suffit de définir un drapeau et de laisser la ligne de code principale vérifier ce drapeau.0 votes
La variable
pagesize
est déclaré comme unint
mais il doit être déclaré comme unsize_t
0 votes
Le site
sig
doit être comparé à SIGSEGV, car il existe d'autres signaux, et une telle comparaison supprimerait le message du compilateur concernant un signal inutilisésig
paramètre0 votes
La fonction :
memalign()
est obsolète. Le code devrait utiliser :posix_memalign()
qui exige également la définition de_POSIX_C_SOURCE
dont la valeur est supérieure/égale à 200112L0 votes
Que le code devrait (probablement) utiliser :
getpagesize()
plutôt que de coder en dur la valeur4096
.