Libseccomp: P: no se pueden tener diferentes filtros con SCMP_ACT_NOTIFY en diferentes subprocesos

Creado en 6 nov. 2020  ·  9Comentarios  ·  Fuente: seccomp/libseccomp

libseccomp almacena la notificación fd en una variable global: state.notify_fd . Esto hace que sea imposible usar libseccomp para una aplicación multiproceso con diferentes filtros en diferentes subprocesos (es decir, sin usar TSYNC).

libseccomp tiene seccomp_reset(NULL, ...) para restablecer la variable global state.notify_fd . Pero seccomp_reset() tiene la desafortunada consecuencia de restablecer state.nr_seccomp = -1 .

Este problema se notó al intentar resolver las pruebas unitarias en libseccomp-golang, consulte https://github.com/seccomp/libseccomp-golang/pull/59#issuecomment -723045033

cc @yvesf @rata

prioritlow question

Comentario más útil

Parece que todos estamos de acuerdo aquí, así que voy a cerrar este tema. @alban, si cree que nos falta algo importante, háganoslo saber y / o vuelva a abrir este problema para que podamos solucionarlo todo.

Gracias a todos.

Todos 9 comentarios

@drakenclimber espera las próximas versiones v2.5.1 hasta que obtengamos alguna aclaración sobre esto. No estoy seguro de haber entendido completamente el informe original todavía, pero como la v2.5.1 es la primera versión que implementa el concepto seccomp_reset(NULL, ...) , esperemos un minuto hasta que podamos verificar las cosas ...

Agregando esto al hito v2.5.1 simplemente como un bloqueador por ahora, esto puede cambiar a medida que investigamos las cosas.

@drakenclimber espera las próximas versiones v2.5.1 hasta que obtengamos alguna aclaración sobre esto. No estoy seguro de haber entendido completamente el informe original todavía, pero como la v2.5.1 es la primera versión que implementa el concepto seccomp_reset(NULL, ...) , esperemos un minuto hasta que podamos verificar las cosas ...

Acordado. Servirá.

libseccomp almacena la notificación fd en una variable global: state.notify_fd . Esto hace que sea imposible usar libseccomp para una aplicación multiproceso con diferentes filtros en diferentes subprocesos (es decir, sin usar TSYNC).

¿Puedes desarrollar un poco más esa última oración? No estoy seguro de entender lo que está tratando de transmitir.

FWIW, la notificación de seccomp FD es un objeto global de proceso, solo puede solicitarlo desde el kernel una vez. Puede leer https://github.com/seccomp/libseccomp/issues/273 para obtener más antecedentes sobre el problema.

libseccomp tiene seccomp_reset(NULL, ...) para restablecer la variable global state.notify_fd . Pero seccomp_reset() tiene la desafortunada consecuencia de restablecer state.nr_seccomp = -1 .

¿Por qué restablecer state.nr_seccomp = -1 un problema importante? Si el campo nr_seccomp se restablece a -1 la próxima vez que se solicite una operación que pueda hacer uso de seccomp(2) la biblioteca comprueba si se admite seccomp(2) y lo usa si está disponible. Sí, podría resultar en llamadas adicionales a seccomp(2) pero eso no debería ser un problema importante, ¿es una preocupación para su caso de uso?

@alban - Pregunta similar de mi parte. Pasé un poco de tiempo tratando de inventar un caso de uso sensible de múltiples subprocesos y múltiples filtros seccomp (en C) y realmente no pude encontrar nada.

Leí la documentación de Go de os.LockOSThread() y tiene sentido para mí. Pero estoy luchando por convertir este conocimiento en una solución de filtro multi-seccomp de subprocesos múltiples.

¿Podrías compartir algún pseudocódigo o algún diseño de alto nivel de lo que estás pensando? Con mucho gusto lo haría un prototipo en C entonces.

¿Puedes desarrollar un poco más esa última oración? No estoy seguro de entender lo que está tratando de transmitir.

Mientras trabajaba en las pruebas unitarias en libseccomp-golang, me di cuenta de que se estaba probando el siguiente escenario:

  1. En una primera ejecución de la prueba unitaria, se aplicó una política seccomp sin SECCOMP_FILTER_FLAG_TSYNC (lo que significa que se aplica a nivel de hilo y no a nivel de proceso) pero con SECCOMP_FILTER_FLAG_NEW_LISTENER (por lo que libseccomp almacenará el fd en state.notify_fd ).
  2. La misma prueba unitaria se ejecuta nuevamente en el mismo proceso pero en un hilo diferente (usando runtime.LockOSThread en Go para asegurarse de eso). Pero libseccomp reutiliza el fd del filtro seccomp anterior (de state.notify_fd ) en lugar de obtener un nuevo fd para el nuevo filtro. Entonces la prueba falla porque esperamos recibir los eventos en el seccomp fd incorrecto.

FWIW, la notificación de seccomp FD es un objeto global de proceso, solo puede solicitarlo desde el kernel una vez. Puede leer el número 273 para obtener más antecedentes sobre el tema.

Por lo que entendí, el kernel nos restringe para obtener solo un FD de notificación de seccomp en un árbol de filtros. Pero en el escenario anterior, los dos subprocesos del mismo proceso utilizan árboles de filtros diferentes, por lo que debería estar bien desde la perspectiva del kernel.

Este escenario para usar diferentes árboles de filtros con SECCOMP_FILTER_FLAG_NEW_LISTENER no se creó a propósito, simplemente surgió como consecuencia de las pruebas unitarias libseccomp-golang que se ejecutan en el mismo proceso. Pero dado que la causa raíz es libseccomp usando una variable global state.notify_fd que se comparte entre subprocesos, pensé que debería abrir este error aquí para abrir la discusión. Sin embargo, estaría bien si esto se cierra como "WONTFIX" (no sé si otros usuarios de libseccomp necesitarían tener soporte para este tipo de escenario). En ese caso, podemos simplemente escribir las pruebas unitarias libseccomp-golang de una manera diferente (es decir, usando un proceso separado para cada iteración de la prueba); tendríamos que hacer eso de todos modos (para evitar mezclar filtros de nivel de hilo y filtros de nivel de proceso, eso sería rechazado por el kernel).

Mientras trabajaba en las pruebas unitarias en libseccomp-golang, me di cuenta de que se estaba probando el siguiente escenario:

  1. En una primera ejecución de la prueba unitaria, se aplicó una política seccomp sin SECCOMP_FILTER_FLAG_TSYNC (lo que significa que se aplica a nivel de hilo y no a nivel de proceso) pero con SECCOMP_FILTER_FLAG_NEW_LISTENER (por lo que libseccomp almacenará el fd en state.notify_fd ).
  2. La misma prueba unitaria se ejecuta nuevamente en el mismo proceso pero en un hilo diferente (usando runtime.LockOSThread en Go para asegurarse de eso). Pero libseccomp reutiliza el fd del filtro seccomp anterior (de state.notify_fd ) en lugar de obtener un nuevo fd para el nuevo filtro. Entonces la prueba falla porque esperamos recibir los eventos en el seccomp fd incorrecto.

Ah, ja, eso tiene más sentido ahora. A menudo me he preguntado si deberíamos hacer que TSYNC sea el predeterminado para los enlaces libseccomp-golang; dada la ambigüedad del hilo en Go, parece una opción mucho más segura.

Por lo que entendí, el kernel nos restringe para obtener solo un FD de notificación de seccomp en un árbol de filtros. Pero en el escenario anterior, los dos subprocesos del mismo proceso utilizan árboles de filtros diferentes, por lo que debería estar bien desde la perspectiva del kernel.

Este escenario para usar diferentes árboles de filtros con SECCOMP_FILTER_FLAG_NEW_LISTENER no se creó a propósito, simplemente surgió como consecuencia de las pruebas unitarias libseccomp-golang que se ejecutan en el mismo proceso. Pero dado que la causa raíz es libseccomp usando una variable global state.notify_fd que se comparte entre subprocesos, pensé que debería abrir este error aquí para abrir la discusión. Sin embargo, estaría bien si esto se cierra como "WONTFIX" (no sé si otros usuarios de libseccomp necesitarían tener soporte para este tipo de escenario). En ese caso, podemos simplemente escribir las pruebas unitarias libseccomp-golang de una manera diferente (es decir, usando un proceso separado para cada iteración de la prueba); tendríamos que hacer eso de todos modos (para evitar mezclar filtros de nivel de hilo y filtros de nivel de proceso, eso sería rechazado por el kernel).

Me interesaría conocer la opinión de @drakenclimber sobre esto, pero sí, lo que pienso ahora es que se trata de un "WONTFIX" debido a que es un caso de esquina bastante extraño. Si una aplicación quisiera hacer algo como esto, podría guardar la notificación fd del árbol de filtros "A", restablecer libseccomp, luego recuperar y guardar la notificación fd del árbol de filtros "B".

Para "arreglar" esto en libseccomp, necesitaríamos hacer que libseccomp sea consciente del hilo, lo cual viene con una serie de desafíos y trampas, de modo que actualmente soy de la opinión de que esto sería una mala idea. Sin embargo, por el bien del argumento, si hiciéramos que libseccomp sea consciente del hilo, también podríamos hacer que el estado global interno sea un estado específico del hilo y / o posiblemente un estado específico del árbol de filtros; en cualquiera de estos casos, creo que la API actual (incluido el seccomp_reset(NULL, ...) ) aún sería razonable, así que estoy tentado a dejar las cosas como están con la API. Si alguien tiene alguna inquietud al respecto, háganoslo saber pronto.

@drakenclimber? Salvo cualquier objeción a lo anterior, creo que estamos de vuelta para la versión v2.5.1.

Me interesaría conocer la opinión de @drakenclimber sobre esto, pero sí, lo que pienso ahora es que se trata de un "WONTFIX" debido a que es un caso de esquina bastante extraño. Si una aplicación quisiera hacer algo como esto, podría guardar la notificación fd del árbol de filtros "A", restablecer libseccomp, luego recuperar y guardar la notificación fd del árbol de filtros "B".

Estoy de acuerdo. Pasé algún tiempo investigando el conjunto de parches y comentarios originales de

Dicho esto, traté de crear un caso de uso de un solo proceso y de múltiples subprocesos que tenga múltiples invocadores y controladores de notificaciones. Honestamente, no podría inventar coherentemente tal escenario. Dado que este es un caso de uso bastante artificial, y no puedo encontrar un caso de uso realista, deberíamos marcar este WONTFIX.

Aparte de uno, pude hacer que el kernel devolviera múltiples fds de notificación a un proceso. Al crear múltiples pthreads y hacer que todos carguen inmediatamente un filtro seccomp con una acción de notificación, ocasionalmente pude obtener dos o tres fds de notificación diferentes devueltos al proceso de espacio de usuario. Dado que esto es tan poco realista, me inclinaría por marcar este problema del kernel como WONTFIX también.

@drakenclimber? Salvo cualquier objeción a lo anterior, creo que estamos de vuelta para la versión v2.5.1.

Genial. Debería poder empezar a trabajar en ello a principios de la semana que viene.

Parece que todos estamos de acuerdo aquí, así que voy a cerrar este tema. @alban, si cree que nos falta algo importante, háganoslo saber y / o vuelva a abrir este problema para que podamos solucionarlo todo.

Gracias a todos.

¿Fue útil esta página
0 / 5 - 0 calificaciones