SELinux está configurado para denegar de forma predeterminada, lo que significa que la política debe permitir explícitamente cada acceso para el que tiene un hook en el kernel. Esto significa que un archivo de directiva consta de una gran cantidad de información sobre reglas, tipos, clases, permisos y mucho más. Una consideración completa de SELinux está fuera del alcance de este documento, pero comprender cómo escribir reglas de políticas ahora es esencial cuando se inician nuevos dispositivos Android. Ya hay una gran cantidad de información disponible sobre SELinux. Consulta la documentación de asistencia para ver los recursos sugeridos.
Archivos de claves
Para habilitar SELinux, integra el kernel de Android más reciente y, luego, incorpora los archivos que se encuentran en el directorio system/sepolicy. Cuando se compilan, esos archivos comprenden la política de seguridad del kernel de SELinux y abarcan el sistema operativo Android upstream.
En general, no debes modificar los archivos system/sepolicy
directamente. En su lugar, agrega o edita tus propios archivos de políticas específicos del dispositivo en el directorio /device/manufacturer/device-name/sepolicy
. En Android 8.0 y versiones posteriores, los cambios que realices en estos archivos solo deberían afectar la política en tu directorio de proveedores. Para obtener más detalles sobre la separación de la política de SE pública en Android 8.0 y versiones posteriores, consulta Cómo personalizar SEPolicy en Android 8.0 y versiones posteriores. Independientemente de la versión de Android, seguirás modificando estos archivos:
Archivos de políticas
Los archivos que terminan en *.te
son archivos de origen de la política de SELinux, que definen los dominios y sus etiquetas. Es posible que debas crear archivos de políticas nuevos en /device/manufacturer/device-name/sepolicy
, pero debes intentar actualizar los archivos existentes siempre que sea posible.
Archivos de contexto
En los archivos de contexto, especificas etiquetas para tus objetos.
file_contexts
asigna etiquetas a los archivos y es usado por varios componentes del espacio de usuario. A medida que crees políticas nuevas, crea o actualiza este archivo para asignar etiquetas nuevas a los archivos. Para aplicar un nuevofile_contexts
, vuelve a compilar la imagen del sistema de archivos o ejecutarestorecon
en el archivo que se volverá a etiquetar. En las actualizaciones, los cambios enfile_contexts
se aplican automáticamente al sistema y a las particiones de datos del usuario como parte de la actualización. Los cambios también se pueden aplicar automáticamente cuando se actualizan a otras particiones. Para ello, agrega llamadasrestorecon_recursive
a tu archivo init.board.rc después de que la partición se haya activado en modo de lectura y escritura.genfs_contexts
asigna etiquetas a sistemas de archivos, comoproc
ovfat
, que no admiten atributos extendidos. Esta configuración se carga como parte de la política del kernel, pero es posible que los cambios no se apliquen a los inodo en el kernel, lo que requiere un reinicio o la desactivación y activación del sistema de archivos para aplicar el cambio por completo. También se pueden asignar etiquetas específicas a puntos de activación específicos, comovfat
, con la opcióncontext=mount
.property_contexts
asigna etiquetas a las propiedades del sistema Android para controlar qué procesos pueden establecerlas. El procesoinit
lee esta configuración durante el inicio.service_contexts
asigna etiquetas a los servicios de Binder de Android para controlar qué procesos pueden agregar (registrar) y encontrar (buscar) una referencia de Binder para el servicio. El procesoservicemanager
lee esta configuración durante el inicio.seapp_contexts
asigna etiquetas a los procesos de la app y a los directorios/data/data
. El procesozygote
lee esta configuración en cada inicio de la app yinstalld
durante el inicio.mac_permissions.xml
asigna una etiquetaseinfo
a las apps según su firma y, de manera opcional, su nombre de paquete. Luego, la etiquetaseinfo
se puede usar como clave en el archivoseapp_contexts
para asignar una etiqueta específica a todas las apps con esa etiquetaseinfo
.system_server
lee esta configuración durante el inicio.keystore2_key_contexts
asigna etiquetas a los espacios de nombres de Keystore 2.0. El daemon keystore2 aplica estos espacios de nombres. El almacén de claves siempre proporcionó espacios de nombres basados en UID/AID. Keystore 2.0 también aplica espacios de nombres definidos por la política de seguridad. Aquí encontrarás una descripción detallada del formato y las convenciones de este archivo.
Archivo de configuración de make BoardConfig.mk
Después de editar o agregar archivos de política y contexto, actualiza tu archivo de compilación /device/manufacturer/device-name/BoardConfig.mk
para hacer referencia al subdirectorio sepolicy
y a cada archivo de política nuevo.
Para obtener más información sobre las variables BOARD_SEPOLICY
, consulta el
archivo system/sepolicy/README
.
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
Después de la compilación, el dispositivo se habilita con SELinux. Ahora puedes personalizar tus políticas de SELinux para admitir tus propias incorporaciones al sistema operativo Android, como se describe en Personalización, o verificar tu configuración existente, como se explica en Validación.
Cuando se implementan los nuevos archivos de políticas y las actualizaciones de BoardConfig.mk, la nueva configuración de políticas se compila automáticamente en el archivo de políticas del kernel final. Para obtener más información sobre cómo se compila sepolicy en el dispositivo, consulta Cómo compilar sepolicy.
Implementación
Para comenzar a usar SELinux, sigue estos pasos:
- Habilita SELinux en el kernel:
CONFIG_SECURITY_SELINUX=y
- Cambia el parámetro kernel_cmdline o bootconfig para que se cumpla lo siguiente:
oBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Esto es solo para el desarrollo inicial de la política del dispositivo. Después de tener una política de inicio inicial, quita este parámetro para que el dispositivo aplique CTS o falle.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Inicia el sistema en modo permisivo y observa qué rechazos se producen durante el inicio:
En Ubuntu 14.04 o versiones posteriores: En Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Evalúa el resultado en busca de advertencias que se parezcan a
init: Warning! Service name needs a SELinux domain defined; please fix!
. Consulta Validación para obtener instrucciones y herramientas. - Identifica los dispositivos y otros archivos nuevos que necesitan etiquetado.
- Usa etiquetas existentes o nuevas para tus objetos. Consulta los archivos
*_contexts
para ver cómo se etiquetaron los elementos anteriormente y usa el conocimiento de los significados de las etiquetas para asignar una nueva. Idealmente, esta es una etiqueta existente que se ajusta a la política, pero, a veces, se necesita una etiqueta nueva y reglas para acceder a ella. Agrega tus etiquetas a los archivos de contexto adecuados. - Identifica los dominios o procesos que deberían tener sus propios dominios de seguridad.
Es probable que debas escribir una política completamente nueva para cada una. Por ejemplo, todos los servicios generados a partir de
init
deben tener su propio servicio. Los siguientes comandos ayudan a revelar los que permanecen en ejecución (pero TODOS los servicios necesitan ese tratamiento):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- Revisa
init.device.rc
para identificar los dominios que no tengan un tipo de dominio. Otórgales un dominio al principio del proceso de desarrollo para evitar agregar reglas ainit
o confundir los accesos deinit
con los que se encuentran en su propia política. - Configura
BOARD_CONFIG.mk
para usar variablesBOARD_SEPOLICY_*
. Consulta el archivo README ensystem/sepolicy
para obtener detalles sobre la configuración. - Examina los archivos init.device.rc y fstab.device y asegúrate de que cada uso de
mount
corresponda a un sistema de archivos etiquetado correctamente o de que se especifique una opcióncontext= mount
. - Revisa cada denegación y crea una política de SELinux para controlar cada una de ellas correctamente. Consulta los ejemplos en Personalización.
Debes comenzar con las políticas del AOSP y, luego, basarte en ellas para realizar tus propias personalizaciones. Para obtener más información sobre la estrategia de políticas y un análisis más detallado de algunos de estos pasos, consulta Cómo escribir una política de SELinux.
Casos de uso
Estos son ejemplos específicos de exploits que debes tener en cuenta cuando crees tu propio software y las políticas de SELinux asociadas:
Vínculos simbólicos: Debido a que los vínculos simbólicos aparecen como archivos, a menudo se leen como archivos, lo que puede generar exploits. Por ejemplo, algunos componentes con privilegios, como init
, cambian los permisos de ciertos archivos, a veces para que sean demasiado abiertos.
Luego, los atacantes pueden reemplazar esos archivos por symlinks al código que controlan, lo que les permite reemplazar archivos arbitrarios. Sin embargo, si sabes que tu app nunca atraviesa un symlink, puedes prohibir que lo haga con SELinux.
Archivos del sistema: Considera la clase de archivos del sistema que solo debe modificar el servidor del sistema. Sin embargo, como netd
, init
y vold
se ejecutan como root, pueden acceder a esos archivos del sistema. Por lo tanto, si netd
se viera comprometido, podría comprometer esos archivos y, potencialmente, el servidor del sistema.
Con SELinux, puedes identificar esos archivos como archivos de datos del servidor del sistema.
Por lo tanto, el único dominio que tiene acceso de lectura y escritura a ellos es el servidor del sistema.
Incluso si netd
se viera comprometido, no podría cambiar de dominio al dominio del servidor del sistema ni acceder a esos archivos del sistema, aunque se ejecute como root.
Datos de apps: Otro ejemplo es la clase de funciones que deben ejecutarse como root, pero que no deben acceder a los datos de la app. Esto es muy útil, ya que se pueden realizar afirmaciones de amplio alcance, como que ciertos dominios no relacionados con los datos de la app no pueden acceder a Internet.
setattr: Para comandos como chmod
y chown
, puedes identificar el conjunto de archivos en los que el dominio asociado puede realizar setattr
. Cualquier cosa fuera de eso podría estar prohibida en estos cambios, incluso por root. Por lo tanto, una app podría ejecutar chmod
y chown
en los elementos etiquetados como app_data_files
, pero no en shell_data_files
ni system_data_files
.