2010-10-06 13 views
12

Sto provando a mantenere il codice studente in esecuzione con allocazioni e il trascinamento della mia macchina di prova. Ho provatoCome posso limitare la memoria acquisita con `malloc()` senza limitare anche lo stack?

setrlimit(RLIMIT_DATA, r); 

dove r è una struct tenendo i limiti. Ma sfortunatamente, sebbene questo limite si fermi a brk e sbrk dall'allocazione, la libreria C fallisce a mmap e continua a essere assegnata.

Ho anche provato

setrlimit(RLIMIT_AS, r) 

e questo arresta il processo nei suoi brani, ma questo rimedio è troppo grave — è impossibile per il processo per recuperare l'errore ENOMEM perché non c'è spazio dello stack per le chiamate effettuate dal codice quando si incontra un valore NULL restituito da malloc().

Ho controlli limitati sui binari, quindi se è possibile fare con una chiamata di sistema, preferirei che. Ma ho bisogno di alcuni mezzi per limitare l'allocazione senza distruggere la capacità del processo di recuperare. Qualcuno ha suggerimenti?

UPDATE: ho trovato qualcosa chiamato failmalloc, ma non è molto sofisticato, e anche se posso causare un errore con esso, ho sempre arrivare un segfault che gdb non può diagnosticare.

ULTERIORI UPDATE: ho scoperto che setrlimit(RLIMIT_AS, r)fa sembrano fare il lavoro che voglio, almeno in alcuni casi, le — segfault che si stavano verificando in seguito sono stati causati da un guasto in un modulo non correlato. A meno che qualcuno non presenti qualcosa di interessante (o una ragione per mantenere la domanda), probabilmente eliminerò la domanda.

+0

Se si sta solo tentando di impedire che programmi abusivi/inceppati eliminino il sistema, non preoccuparsi di consentire il ripristino da malloc 'non riuscito. Lascia che il sistema operativo li uccida e sii fatto. Un programma corretto presumibilmente non dovrebbe mai raggiungere il limite in ogni caso. –

+0

Molti studenti inviano programmi errati. Se eseguono il dump core, ottengono zero. Se recuperano e abortiscono, ottengono il credito parziale. –

risposta

3

È possibile forzare una macro sugli studenti ignari? :-)

#define malloc(bytes) limited_malloc(bytes) 

e anche una definizione per limited_malloc che limita cosa si può fare.

4

costruzione sull'idea usato da failmalloc, è possibile utilizzare la variabile e la funzione LD_PRELOAD* ambiente interposizione di costruire un wrapper malloc() e di imporre eventuali limitazioni lì.

È necessario caricare dinamicamente un puntatore all'originale malloc() utilizzando dlsym(). Non è possibile chiamare direttamente l'originale malloc() dal wrapper perché verrà interpretato come una chiamata ricorsiva al wrapper stesso.

#define _GNU_SOURCE 
#include <stdio.h> 
#include <stdint.h> 
#include <dlfcn.h> 

void * malloc(size_t size) 
{ 
    static void * (*func)(size_t) = NULL; 
    void * ret; 

    if (!func) 
    { 
     /* get reference to original (libc provided) malloc */ 
     func = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc"); 
    } 

    /* impose any necessary restrictions before calling malloc */ 
    ... 

    /* call original malloc */ 
    ret = func(size); 

    /* impose any necessary restrictions after calling malloc */ 
    ... 

    return ret; 
}

* Si noti che LD_PRELOAD deve specificare il percorso completo alla libreria di interposizione, e che interposizione biblioteca è disattivata per i programmi setuid al fine di evitare problemi di sicurezza.


Un alternative all'utilizzo dlsym() sarebbe quella di utilizzare l'opzione GNU linker --wrap symbol.

+1

I sorgenti valgrind dovrebbero contenere qualcosa di simile a quell'approccio, immagino. –