2013-03-30 17 views
8

Sto facendo un confronto tra diversi meccanismi IPC disponibili su Mac OS X (pipe, socket, IPv System V, ecc.) E vorrei vedere come confrontare le porte Mach con quelle superiori alternative di livello. Tuttavia, ho riscontrato un problema di base: ottenere i diritti di invio alle porte attraverso i processi (in particolare, attraverso un processo principale e un processo figlio).Condivisione di porte Mach con processi figlio

A differenza dei descrittori di file, ports are generally not carried over to forked processes. Ciò significa che deve essere stabilito un altro modo per trasferirli. Quasi l'unica pagina pertinente che ho trovato su questo era this one, e in un aggiornamento affermano che il loro metodo non funziona più e non è mai stato garantito, anche se quel metodo era suggested by an Apple engineer in 2009. (Implica la sostituzione della porta di bootstrap, e ora la interruzione di XPC.) La sostituzione che suggeriscono utilizza funzioni deprecate, quindi non è una soluzione molto interessante.

Inoltre, una cosa che mi è piaciuta della vecchia soluzione è che le porte sono rimaste praticamente private tra i processi che l'hanno utilizzata. Non è stato necessario trasmettere l'esistenza della porta, proprio come le pipe (dalla chiamata pipe) una volta biforcute. (Probabilmente vivrò con esso se c'è un'altra soluzione, ma è un po 'fastidioso.)

Quindi, come si passa un diritto di invio a una porta Mach da un processo padre a un processo figlio?

risposta

0

Una cosa che si potrebbe provare (anche se si tratta di un errore grossolano) è il dirottamento delle porte delle eccezioni come meccanismo di ereditarietà. Imposta una porta personalizzata come porta di eccezione nel genitore, imposta il figlio, fa in modo che il figlio ottenga la porta personalizzata dalla sua porta di eccezione, invii la porta di attività al genitore, il genitore reimposta la sua porta di eccezione, reimposta la porta di eccezione del bambino, e poi i due procedono da lì con un canale di comunicazione. Vedi task_set_exception_ports().

+0

Sì, quello era un attacco "decente" con la porta di bootstrap, ma preferirei non farlo con nessun'altra porta speciale. – zneak

2

bootstrap_register è deprecato ma bootstrap_check_in non è, e può essere utilizzato per registrare la porta che può essere successivamente recuperata dal processo figlio utilizzando bootstrap_look_up. (Questo ancora non fornisce la privacy che stai cercando, sfortunatamente).

+0

Cosa intendi con "non è sicuro"? – Mecki

+0

In riferimento all'OP: "una cosa che mi è piaciuta della vecchia soluzione è che le porte sono rimaste praticamente private tra i processi che l'hanno utilizzato. Non c'era bisogno di trasmettere l'esistenza del porto" – Danra

+0

Ahhh, vedo ... bene "privato" e "sicuro" sono significati completamente diversi in quasi ogni aspetto, quindi non ho capito che ti riferivi a questa affermazione. Grazie per il chiarimento. – Mecki

0

La soluzione consigliata è non utilizzare direttamente Mach IPC ma implementare il processo figlio come servizio XPC, nel qual caso è possibile utilizzare l'API XPC che utilizzerà Mach IPC dietro la scena, ma non si dispone trattare con qualsiasi dettaglio. Hai un'API semplice per inviare messaggi XPC nel genitore e un'API facile per ricevere messaggi XPC nel client, che può anche facilmente rispedire le risposte. Il sistema gestirà tutte le parti difficili per te.

https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html

Se non è possibile utilizzare l'API XPC, tenere a mente che quando si registra il servizio con bootstrap_check_in() (che non è deprecato), non sarà privato, ma se lo fate in un utente processo spaziale, sarà privato per la sessione di accesso: i processi di root non lo vedranno, né i processi di altri utenti. Se lo fai in un processo di root, sarà comunque visibile a tutte le sessioni.

Si noti tuttavia che è possibile controllare chi può inviare messaggi IPC e chi no. È possibile richiedere un mach_msg_audit_trailer_t quando si riceve un messaggio mach. In questo modo si ottiene l'accesso allo audit_token_t del mittente. E usando audit_token_to_pid() puoi ottenere il pid_t del mittente. Come sai il PID di tuo figlio, puoi semplicemente ignorare tutti i messaggi (passandolo a mach_msg_destroy() per evitare perdite di risorse), a meno che il messaggio non sia stato inviato dal tuo processo figlio. Pertanto, non è possibile evitare che la porta sia rilevabile, ma è possibile evitare che qualsiasi processo diverso dal processo figlio possa utilizzare questa porta.

E, ultimo ma non meno importante, si può semplicemente dare alla porta un nome casuale, dopotutto solo il processo figlio ha bisogno di conoscerlo, così è possibile dinamicalizzare un nome nel processo genitore e passarlo al proprio processo figlio, in questo modo la porta può essere vista se il software esegue la scansione delle porte, ma la maggior parte del software utilizza solo nomi con hardcoded.