Domande frequenti (FAQ)

Posso utilizzare i thread?

Sì, i thread sono supportati in Sandbox2.

Tutti i thread devono essere limitati alla sandbox

Per via del funzionamento di Linux, il criterio seccomp-bpf viene applicato solo al thread corrente: ciò significa che il criterio non viene applicato ad altri thread esistenti, ma i thread futuri erediteranno il criterio:

  • Se utilizzi Sandbox2 nella prima modalità in cui il sandboxing è attivato prima del giorno execve(), tutti i thread erediteranno il criterio e non ci sono problemi. Questa è la modalità di sandboxing preferita.
  • Se utilizzi la seconda modalità in cui l'esecutore ha set_enable_sandbox_before_exec(false) e Sandboxee indica all'esecutore quando vuole essere limitato tramite sandbox con SandboxMeHere(), assicurati che il filtro venga applicato a tutti i thread. In caso contrario, c'è il rischio di un'uscita nella sandbox: il codice dannoso potrebbe essere migrato da un thread con sandbox a un thread senza sandbox.

Come devo compilare il mio Sandboxee?

Se non fai attenzione, è facile ereditare molte dipendenze ed effetti collaterali (chiamate di sistema supplementari, accessi ai file o persino connessioni di rete) che rendono più difficile il sandboxing (rilevamento di tutti gli effetti collaterali) e meno sicuro (perché i criteri relativi alle chiamate di sistema e ai file sono più ampi). Alcune opzioni di compilazione possono contribuire a ridurre questi problemi:

  • Compila in modo statico il programma binario Sandboxee per evitare collegamenti dinamici che utilizzano molte chiamate di sistema (open/openat, mmap e così via).
  • Poiché Bazel aggiunge pie per impostazione predefinita, ma il valore statico non è compatibile con questo criterio, puoi utilizzare il flag delle funzionalità per forzarla tramite le seguenti opzioni delle regole cc_binary:

    linkstatic = 1,
    features = [
        "fully_static_link",  # link libc statically
        "-pie",
    ],
    

Tuttavia, l'utilizzo dell'statico ha lo svantaggio di ridurre l'entropia heap ASLR (da 30 bit a 8 bit), semplificando gli exploit. Decidi con attenzione cosa è preferibile in base all'implementazione e ai criteri della sandbox:

  • non statico: una buona ASLR heap, potenzialmente più difficile da ottenere l'esecuzione iniziale del codice, ma a scapito di un criterio della sandbox meno efficace, potenzialmente più facile da eliminare.
  • statico: ASLR heap non valido, potenzialmente più facile da ottenere l'esecuzione iniziale del codice, ma un criterio della sandbox più efficace, potenzialmente più difficile da eliminare.

È una scelta sfortunata da fare, perché il compilatore non supporta gli elementi PIE (Position Independent Executable) statici. La funzionalità PIE viene implementata perché il programma binario è un oggetto dinamico e il caricatore dinamico lo mappa in una posizione casuale prima dell'esecuzione. Poi, poiché l'heap viene tradizionalmente posizionato con un offset casuale dopo l'indirizzo di base del programma binario (ed espanso con brk syscall), ciò significa che per i programmi binari statici l'entropia ASLR dell'heap è solo questo offset perché non esiste un PIE.

Per un esempio di queste opzioni di compilazione, guarda l'esempio statico BUILD.bazel: static_bin.cc è compilato in modo statico, il che ci permette di avere un criterio di syscall molto rigido. Questo approccio funziona bene anche per la limitazione tramite sandbox dei programmi binari di terze parti.

Posso utilizzare il sandbox per i file binari x86 a 32 bit?

Sandbox2 può utilizzare il sandbox per la stessa architettura con cui è stata compilata.

Inoltre, il supporto per x86 a 32 bit è stato rimosso da Sandbox2. Se si prova a usare un esecutore x86 a 64 bit per la sandbox di un file binario x86 a 32 bit o un file binario x86 a 64 bit che effettua chiamate di sistema a 32 bit (tramite int 0x80), entrambi generano una violazione della sandbox che può essere identificata dall'etichetta dell'architettura [X86-32].

Il motivo alla base di questo comportamento è che i numeri di chiamata di sistema sono diversi da un'architettura all'altra e, poiché il criterio di chiamata di sistema è scritto nell'architettura dell'esecutore, sarebbe pericoloso consentire un'architettura diversa per Sandboxee. In effetti, ciò potrebbe portare a consentire una chiamata di sistema apparentemente innocua che, di fatto, significa che un'altra chiamata di sistema più dannosa potrebbe aprire la sandbox a un'uscita.

Esistono limiti al numero di sandbox che un processo esecutore può richiedere?

Per ogni istanza Sandboxee (nuovo processo generato dal forkserver), viene creato un nuovo thread, ed è qui che si trova il limite.

Un esecutore può richiedere la creazione di più sandbox?

No. Esiste una relazione 1:1: un'istanza di esecutore archivia il PID di Sandboxee, gestisce l'istanza di Comms nell'istanza della sandbox e così via.

Perché viene visualizzato il messaggio "Funzione non implementata" all'interno di forkserver.cc?

Sandbox2 supporta solo l'esecuzione su kernel ragionevolmente nuovi. Il nostro attuale taglio è il kernel 3.19, anche se potrebbe cambiare in futuro. La ragione è che stiamo usando funzionalità relativamente nuove del kernel, inclusi gli spazi dei nomi utente e seccomp con il flag TSYNC.

Se esegui l'esecuzione in produzione, questo non dovrebbe essere in discussione, dato che quasi l'intero parco risorse esegue un kernel abbastanza nuovo. In caso di problemi, contattaci.

Se utilizzi Debian o Ubuntu, l'aggiornamento del kernel è semplice quanto l'esecuzione:

sudo apt-get install linux-image-<RECENT_VERSION>