2012-07-13 12 views
5

Me gustaría ejecutar binarios arbitrarios (potencialmente peligrosos) en mi servidor. Por lo tanto, he usado objcopy para cambiar el nombre del símbolo "principal" a "other_main" para poder enlazar en mi propia función principal pequeña que establece un valor apropiado para RLIMIT_CPU y alterna el indicador SECCOMP antes de llamar a other_main. Estoy muy contento con esta solución hasta ahora.SECCOMP: ¿Cómo emular malloc, realloc y gratis?

El problema ahora es que el código del programa de terceros podría contener algunas llamadas a malloc que podrían matar el programa al instante (sbrk no está permitido). Por lo tanto, me gustaría asignar previamente una matriz de tamaño razonable (por ejemplo, 20 MB) antes de configurar SECCOMP que debería ser utilizada por malloc/realloc/calloc/free. Lamentablemente, no sé cómo archivar el último paso. ¿Tengo que implementar todas esas 4 funciones por mi cuenta? ¿Cómo puedo inyectar mis propias funciones a stdlib (por ejemplo, qué ocurre cuando printf llama internamente a malloc?).

+0

¿Realmente funciona el cambio de nombre de símbolos? Realmente me pregunto qué hará OS con unos binarios despojados. –

+0

Cambiar el nombre de símbolos funciona bien aquí. objcopy parece ser realmente poderoso. Aparentemente no se te permite quitar los binarios, pero eso no es un problema para mí, porque compilo los binarios por mi cuenta. Es solo el código C que no es confiable. – tux21b

+0

¿Puede proporcionar a sus usuarios una biblioteca C diferente (por ejemplo, Newlib) que la biblioteca de su sistema operativo? Si es así, sería muy fácil escribir su propio 'sbrk' (que no puede salir de su caja de arena) y luego malloc/realloc/calloc/free y todos los amigos trabajarán. –

Respuesta

3

No todas las implementaciones malloc se basan en sbrk(), por ejemplo, GNU mmalloc. This doc también puede ser útil si se necesita una implementación personalizada.

+ dos implementaciones sencillas malloc here

+0

Las únicas llamadas al sistema que están permitidas son leer, escribir, firmar y salir. Así que no puedo usar mmap tampoco, a menos que preasigne suficiente memoria al inicio del programa (una matriz estática de tamaño razonable parece estar bien para mi caso de uso). Sin embargo, el enlace parece útil, suponiendo que realmente tengo que implementar mi propio malloc. Pero todavía no sé cómo puedo reemplazar las llamadas malloc internas utilizadas en printf y otros lugares en el stdlib. – tux21b

+0

He corregido la respuesta: dlmalloc realmente usa sbrk(). Sin embargo, allí encontré GNU mmaloc que está basado en mmap(). En su caso, podría considerar usar el conjunto estático [] en lugar de la funcionalidad de manejo de montón + simple en su base. Por ejemplo, puede mantener N referencias también en matriz estática. Esa sería una memoria pseudodinámica, por supuesto. – pmod

1

seccompsandbox:

  • permite Seccomp en un hilo, que realiza RPC (a través de read/write sobre un pre-asignado socketpair) a otro (no Seccomp) enhebrar en el mismo proceso que es capaz de realizar operaciones privilegiadas como mmap
  • funciones de parcheo como malloc (en memoria, en tiempo de ejecución) para redirigir al Ir seccomp-safe wrappers

Chromium's seccomp Sandbox tiene más detalles sobre cómo funciona.

2

Para malloc y gratis, su programa solo necesita definir sus propias versiones. La mayoría de las implementaciones de libc que he visto (incluidas glibc, klibc y dietlibc) utilizarán felizmente sus rutinas de asignación de memoria. Entonces, antes de ingresar al modo seccomp, asigne un gran trozo de memoria usando mmap o sbrk y luego haga que su malloc/asignación libre de este fragmento. memmgr es un asignador de montón simple que se puede adaptar fácilmente para la asignación de un búfer fijo.

El verdadero problema con Seccomp es que el conjunto de llamadas al sistema que permite (leer, escribir, salida, y sigreturn) no es más que suficiente para ejecutar programas vinculados contra más o menos cualquier libc por ahí. Por ejemplo:

  • en glibc, salida y _exit llamar exit_group
  • en glibc, printf puede llamar mmap
  • en dietlibc, scanf puede llamar ioctl
  • etc., etc.

Normalmente hay buenas razones por las cuales estas llamadas son necesarias. Por ejemplo, dietlibc usa ioctl para verificar si stdin es un tty cuando se lee la entrada de stdin, para eliminar el stdout. Este es un comportamiento estándar para garantizar que las solicitudes estén visibles antes de leer la entrada interactiva si la salida está almacenada en línea.

Por lo tanto, he llegado a la conclusión de que el modo seccomp original es más o menos inútil. Sin embargo, el modo 2 (a.k.a. "modo de filtro") es mucho más útil, ya que le permite incluir en la lista blanca llamadas al sistema específicas. Tengo un proof of concept en mi página github que ejecuta programas en el modo seccomp 2, pero les permite usar printf y scanf, así como asignar memoria usando malloc/free.