2009-04-13 12 views
6

Sto eseguendo una sorta di "sandbox" in C su Ubuntu: prende un programma e lo esegue in modo sicuro sotto l'utente nobody (e intercetta segnali, ecc.). Inoltre, assegna memoria e limiti di tempo e misura il tempo e l'utilizzo della memoria.
(Nel caso foste curiosi, è per una sorta di "giudice online" per contrassegnare i programmi sui dati di test)Utilizzo memoria di un processo figlio?

Attualmente ho adattato il modulo safeexec da mooshak. Sebbene la maggior parte delle cose funzioni correttamente, l'utilizzo della memoria sembra essere un problema. (È molto impreciso)

Ora ho provato il consiglio here e analizzato VM da /proc/pid/stat, e ora il problema di precisione è stato risolto. Tuttavia, per i programmi che terminano molto rapidamente non funziona e solo restituisce 0.

Il safeexec programma sembra funzionare in questo modo:

  1. E fork() s
  2. Utilizza execv() nel processo figlio per eseguire il programma desiderato
  3. Monitora il programma dal processo padre fino al termine del processo figlio (utilizzando wait4, che si verifica per restituire l'utilizzo della CPU, ma non la memoria?)
    Quindi analizza /proc/../stat del processo figlio (che è stato sostituito dal execv)

Allora perché VM in /proc/child_pid/stat volte uguale a 0?
È perché execv() termina troppo rapidamente, e /proc/child_pid/stat non è disponibile?
Se è così, c'è una sorta di altro modo per ottenere l'utilizzo della memoria del bambino?
(Dal momento che questo è pensato per giudicare i programmi entro un limite di tempo, non posso permettermi qualcosa con una penalità di prestazioni come valgrind)

Grazie in anticipo.

risposta

3

È possibile concordare che il processo figlio utilizzi la propria versione di malloc() e che registri l'utilizzo della memoria HWM (magari utilizzando un gestore registrato con atexit())? Forse useresti LD_PRELOAD per caricare la tua libreria di gestione della memoria. Questo non aiuterà con enormi array statici o enormi array automatici.


Hmm, sembra interessante. Comunque, c'è un modo per tenere traccia degli array statici/automatici?

La memoria statica può essere analizzata con il comando "dimensione" - più o meno.

Gli array automatici sono un problema - non sono sicuro di come potresti gestirli. Il tuo codice di allocazione della memoria potrebbe vedere quanta pila è in uso quando viene chiamata (guarda l'indirizzo di una variabile locale). Ma non è garantito che la memoria verrà allocata quando è in uso la quantità massima di array locale, quindi fornisce al meglio una misura approssimativa.

Un altro pensiero: forse si potrebbe utilizzare la tecnologia debugger - la chiamata di sistema ptrace() - per controllare il processo figlio, e, in particolare, di tenere in su per un tempo sufficiente per essere in grado di raccogliere le statistiche di utilizzo della memoria da /proc/....

+0

Hmm, sembra interessante. Comunque, per rintracciare gli array statici/automatici? –

+0

Wow, ptrace è davvero pulito. Grazie! (Dato che ptrace fa in modo che il processo figlio si interrompa quando esegue execv() s, sono in grado di misurare l'utilizzo della memoria non appena inizia) –

2

È possibile impostare il limite delle risorse rigide (setrlimit per la risorsa RLIMIT_AS) prima di execve(). Il programma non sarà in grado di allocare più di quella quantità di memoria. Se si tenta di farlo, le chiamate di allocazione della memoria (brk, mmap, mremap) avranno esito negativo. Se il programma non gestisce la condizione di esaurimento della memoria, segfault, che si rifletterà nello stato di uscita restituito da wait4.

+0

Lo sto già facendo - mi piacerebbe sapere quanto stia effettivamente usando, comunque (per confrontare le soluzioni) –