Question

Je suis la construction d'un programme qui utilise mprotect () pour limiter un bloc de mémoire d'accès. Lorsque la mémoire est demandée, un SIGSEGV est jeté que j'écoute pour l'utilisation d'un signal () appel.

Une fois que le SIGSEGV a été détectée, je dois accéder en quelque sorte le pointeur vers la mémoire qui a été demandé (qui a jeté la faute) et la taille du segment demandé. Est-ce possible?

void fifoSigHandler(){

    // Needs to only remove protection from requested block of virtual memory
    mprotect(fifoVm,(size_t)fifoVm_size,PROT_WRITE);
    printf("Caught Seg Fault");
}

void fifo_init(void* vm, int vm_size, int n_frames, int page_size)
{
    fifoVm = vm;
    fifoVm_size = vm_size;
    fifoFrames = n_frames;
    fifoPageSize = page_size;

    mprotect(fifoVm,(size_t)fifoVm_size,PROT_NONE);

    signal(SIGSEGV, fifoSigHandler);
}

De plus, est-il un moyen de déterminer le niveau de mprotect () un bloc de mémoire est actuellement affecté (PROT_NONE, PROT_READ, etc ..)?

Était-ce utile?

La solution

Vous devez utiliser sigaction avec SA_SIGINFO au lieu de signal pour établir votre gestionnaire, et vous obtiendrez rappelé des informations utiles dans un siginfo_t, y compris si_addr.

si_addr, comme expliqué dans sigaction (2), contiendra l'adresse. Quant à la longueur, eh bien, vous êtes hors de la chance à moins que vous êtes prêt à analyser les instructions. Mieux que vous pouvez faire est de prendre des mesures pour la page signalé dans si_addr, et si cela ne suffit pas, vous obtiendrez un autre signal assez tôt. Au moins, voilà comment nous avons fait les choses dans ObjectStore.

Autres conseils

Vous cherchez libsigsegv http://libsigsegv.sourceforge.net/

Mais méfiez-vous que l'appel mprotect est uniquement le signal de sécurité sous Linux, les systèmes POSIX ne supportent pas cela.

Je crains que dans Linux la seule façon d'obtenir des bits de protection de la mémoire est à lire dans /proc/$pid/meminfo

Sur une note latérale (Linux uniquement): Si vous êtes inquiet au sujet de la consommation de mémoire et l'intention de permettre aux pages d'une cartographie plus d'un, je puis conseille de créer votre mappage à l'aide mmap avec MAP_NORESERVE dans ce cas, vous obtiendrez un la cartographie des pages de copie en écriture rempli de zéros qui allouera RAM physique sur la première écriture. MAP_NORESERVE indique au noyau de ne pas sauvegarder votre mémoire avec l'espace d'échange permettant d'allouer jusqu'à 64 To d'espace d'adressage virtuel. Seul inconvénient est que si vous ne manquez de mémoire des choses terribles peuvent se produire (oom-killer).

Étape 1 : Init un sigaction:

struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = handler;
act.sa_flags = SA_SIGINFO | SA_ONSTACK;

Étape 2 : Faire de cette poignée sigaction SIGSEGV:

sigaction(SIGSEGV, &act, NULL);

(Facultatif) Étape 3 : Faites-traiter d'autres signaux de mémoire trop:

sigaction(SIGBUS, &act, NULL);
sigaction(SIGTRAP, &act, NULL);

Ajouter la gestion des erreurs au besoin

Étape 4 : Définir la fonction de gestionnaire:

void handler(int signal, siginfo_t* siginfo, void* uap) {
    printf("Attempt to access memory at address %p\n", 
           siginfo->si_addr);
    #ifdef LINUX_64BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[16]));
    #elif LINUX_32BIT
    printf("Instruction pointer: %p\n",
           (((ucontext_t*)uap)->uc_mcontext.gregs[14]));
    #endif
}

Vous pouvez consulter les pages de manuel pour ucontext_t et siginfo_t pour des données plus intéressant votre gestionnaire peut extraire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top