En primer lugar, debo admitir que estoy totalmente de acuerdo con su declaración "He encontrado esto sorprendentemente difícil de hacer" . Google ha diseñado Android principalmente desde la perspectiva del consumidor, y no para usuarios avanzados. El resultado es que, tan pronto como quieras hacer algo fuera de usar la última aplicación de Facebook o jugar con Candy Crush, te encontrarás rápidamente en el reino de Linux de principios de 2000, cuando se requería un conocimiento similar al de un desarrollador para cambiar cuáles deberían ser configuraciones simples. Creo que la situación evolucionará rápidamente a medida que el sistema Android se vuelva más maduro, pero por ahora tenemos que ver con lo que tenemos ...
Como dijiste, hay dos razones por las cuales es necesario compilar tu propio conjunto de herramientas SELinux:
- El conjunto de herramientas proporcionado por el sistema suele ser una versión posterior. Si bien SELinux de Android se basa en la política DB versión 30, los cuadros actuales de Linux generalmente solo manejan versiones de hasta 29.
- Incluso si fuera más reciente, no ayudaría, de hecho, la construcción de SELinux a partir del código ascendente (que se hace fácilmente, al menos en máquinas Fedora siguiendo las recomendaciones ascendentes) permite que el sistema maneje la política DB versión 30, sin embargo, el SELinux de Android ha sido muy modificado (la documentación de Google destaca algunas modificaciones), por lo que intentar manejar el SELinux de Android falla debido a errores de sintaxis y análisis.
Entonces, para continuar con la búsqueda de análisis SELinux de Android, tendremos que poner nuestras manos en la tierra ... de la manera más limpia posible:
- Primero configuraremos un entorno sano,
- Una vez hecho esto, compilaremos las bibliotecas SELinux de Android y las primeras herramientas,
- Además de ellos, crearemos herramientas SELinux,
- Terminaremos agregando algunas utilidades suplementarias.
Configurar un entorno adecuado
Propiedades del entorno
La forma más limpia recomendada, posiblemente una forma de trabajo confiable es dedicar un entorno a su trabajo con Android:
Una máquina virtual está perfectamente bien (si no es la mejor opción). Prefiere usar un VMware ya que tendrá que conectar su teléfono a través de USB al sistema invitado. La alternativa gratuita Qemu no parece manejar esa tarea muy bien. No probé con otro software de virualización.
Deberá ser un sistema de 64 bits, de lo contrario, el código simplemente no se compilará debido a que los enteros son del tamaño incorrecto.
Se recomienda encarecidamente , posiblemente obligatorio, utilizar un sistema Ubuntu. Siéntase libre de usar Xubuntu si prefiere el entorno de escritorio más ligero de XFCE, esto no cambia el núcleo y el paquete disponible del sistema y no tendrá ningún impacto en su trabajo relacionado con Android (todo lo que digo sobre Ubuntu en este procedimiento también se aplica a Xubuntu). Puede encontrar en el árbol de origen SELinux de Android algunos archivos Léame que recomiendan el uso de Fedora, estos archivos se heredan del proyecto SELinux de la NSA y su contenido no necesariamente coincide con el Android de Google.
La versión exacta de Unbuntu para usar depende de la versión de Android que desea construir. Para Android 6.0, se recomienda Ubuntu 14.04 (Trusty). Consulte la página de requisitos de Google para obtener más información.
Necesitará mucho espacio en el disco (al menos 50 GB si planea solo una investigación relacionada con SELinux, al menos 100 GB si planea una compilación completa de Android). La CPU y la memoria son menos relevantes, solo afectan el tiempo para una compilación completa y no tendrán un impacto real para las tareas relacionadas con SELinux.
Usar Ubuntu tiene dos ventajas principales:
Al utilizar el sistema recomendado, está trabajando en un entorno conocido y probado: las bibliotecas, herramientas y paquetes del sistema se encuentran en la versión y ubicación esperadas por el proyecto.
Y más específicamente en nuestro caso actual: Ubuntu mismo se basa en AppArmor, que es una alternativa de SELinux, no utiliza SELinux. La buena noticia es que, por lo tanto, podrá instalar las herramientas y binarios SELinux de Android en todo el sistema sin arriesgarse a alterar la confiabilidad del sistema.
Procedimiento de instalación del entorno
Puede instalar Ubuntu de la manera tradicional comenzando desde un DVD en vivo completo, pero una alternativa más rápida es usar una instalación de arranque de red (instalación en modo texto) y seleccionar el entorno de escritorio que prefiera al final. Hacerlo le ahorrará el tiempo de actualización inicial al instalar directamente la versión actualizada de los paquetes en lugar de instalar primero los obsoletos, luego solicitará aplicar 389 actualizaciones pendientes en el primer arranque.
El ISO para el instalador de arranque de red Ubuntu / Xubuntu 14.04 (mismo ISO) está disponible aquí .
Para omitir la problemática función de "Instalación fácil" de VMware, es un buen hábito comenzar seleccionando la opción "Instalaré el sistema operativo más adelante" .
Asegúrese de seleccionar Linux , luego Ubuntu 64 bits como SO huésped.
La VM necesitará los siguientes recursos:
- Obligatorio: el espacio en disco debe ser de al menos 40 GB (los 20 GB predeterminados no serán suficientes, el código fuente solo ocupa más espacio que eso), se recomienda una mayor. Una compilación completa requiere un mínimo de disco de 100 GB, este es el valor que suelo tomar. No olvide que esta configuración es solo un límite máximo: el tamaño real tomado por la VM crece dinámicamente con las solicitudes de los huéspedes.
- Facultativo: aumente la RAM de 1024 a al menos 2048 o más (depende de la capacidad de su host, uso 4096),
- Facultativo: aumente la cantidad de núcleos de procesador de 1 a 2 o más (depende de la capacidad de su host, uso 3).
- El CD-Rom debe apuntar al archivo ISO de instalación.
- Es posible que desee cambiar USB del predeterminado 1.1 a 2.0, ya que el primero puede dar advertencias cuando conecta su dispositivo. Dependiendo de su uso, también puede desmarcar de forma segura "Conectar automáticamente nuevos dispositivos USB" y "Compartir dispositivos Bluetooth con la máquina virtual" .
- Dependiendo de su entorno, también puede necesitar ajustar la configuración de la pantalla (deshabilitar 3D, aplicar un tamaño de pantalla).
Atención:
- Si eligió la instalación de arranque de red, no olvide seleccionar su entorno de escritorio ( escritorio Ubuntu o escritorio Xubuntu ) cuando llegue a la pantalla de selección de software , ¡o terminará con un entorno mínimo de solo texto!
- En el primer arranque, rechace actualizar a la última versión: ¡el punto principal aquí es quedarse en 14.04!
En el primer arranque, uno de los primeros que puede hacer es instalar las herramientas de invitado de Linux:
sudo apt-get install open-vm-tools
Este paquete activa los desencadenadores del tiempo de arranque, por lo tanto, su instalación se completará solo después de un reinicio de invitado.
Obtener el código fuente de Android
Si bien es similar, los detalles del procedimiento dependen de la ROM elegida:
- Para CyanogenMod, busque su dispositivo (seleccione primero el proveedor) y luego haga clic en el enlace "Cómo construir CyanogenMod" para obtener instrucciones adaptadas para su dispositivo.
- Para AOSP, siga el procedimiento que comienza aquí .
Vale la pena señalar que CyanogeMod incluye en su árbol de origen una herramienta que le permite descomprimir boot.img
archivos. Para decirlo de otra manera, CyanogenMod le proporciona una herramienta que le permitirá acceder al sepolicy
archivo almacenado en dispositivos y archivos ROM. El AOSP de Google no proporciona dicha herramienta, por lo que si no tiene otro imperativo, el árbol de origen de CyanogenMod puede ser la opción más conveniente, de lo contrario tendrá que instalarlo aparte (lo cual es rápido y fácil de hacer, así que no se preocupe aquí).
Aquí estoy siguiendo el procedimiento CyanogenMod 13.0 (Android 6.0). La explicación de los comandos utilizados está disponible en las páginas enlazadas anteriormente. Léalos, el mecanografiado a continuación se proporciona solo con fines de referencia.
Consejo: Si bien utilizoapt-get
en esta publicación para mantener el mínimo común denominador y mantener contentos a todos, es posible que prefiera usarlo,aptitude
ya que se encargará de las dependencias de una mejor manera (al eliminar un paquete que requirió la instalación de algunas dependencias) , estas dependencias también se eliminarán, dejando su sistema más limpio). AFAIK elaptitude
comando debe estar instalado en Ubuntu pero está disponible de forma predeterminada en Xubuntu.
sudo apt-get install bison build-essential curl flex git gnupg gperf \
libesd0-dev liblz4-tool libncurses5-dev libsdl1.2-dev libwxgtk2.8-dev libxml2 \
libxml2-utils lzop maven openjdk-7-jdk pngcrush schedtool squashfs-tools \
xsltproc zip zlib1g-dev g++-multilib gcc-multilib lib32ncurses5-dev \
lib32readline-gplv2-dev lib32z1-dev
mkdir -p ~/bin
mkdir -p ~/android/system
PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod u+x ~/bin/repo
cd ~/android/system/
git config --global user.name "Your Name"
git config --global user.email "you@example.com
repo init -u https://github.com/CyanogenMod/android.git -b cm-13.0
repo sync
# Coffee time: around 20GB are being downloaded, this may take several hours.
source ./build/envsetup.sh
breakfast
Ahora tiene un árbol fuente limpio y casi completo. Faltan los blobs propietarios, pero no los necesita para las tareas relacionadas con SELinux.
Consejo: Obtener las fuentes es un proceso tedioso, puede valer la pena hacer una instantánea o una copia de seguridad de su VM ahora.
Compile e instale el conjunto de herramientas y bibliotecas SELinux de Android
Ahora comienza la parte divertida del viaje;)!
Hasta ahora, el procedimiento debería haber sido bastante sencillo. El objetivo era principalmente garantizar que tengas el mismo entorno que yo. Si lo hace, la secuela también debería ser sencilla.
Bajo el capó de Google, no dude en aplicar cambios profundos al código fuente de Android entre versiones, por lo tanto, los pasos exactos de compilación dependerán de la versión (por ejemplo, el maestro AOSP muestra que el sepolicy/
directorio se moverá ).
Primero compartiré mi procedimiento exacto para compilar e instalar las bibliotecas y el conjunto de herramientas SElinux de Android, pero para mantener la relevancia de esta publicación con el tiempo, luego agregaré algunas notas sobre el enfoque genérico a seguir para resolver la mayoría de los problemas de compilación.
Procedimiento paso a paso
Las bibliotecas SELinux de Android proporcionan la capa de abstracción que permitirá que el software de la capa superior se ocupe de los archivos de política SELinux específicos de Android. Por lo tanto, tendremos que calcularlos e instalarlos primero (que, en sí mismo, en realidad representa el núcleo de las dificultades aquí, hasta que haya encontrado el camino).
Luego podremos construir e instalar las herramientas de SELinux. Como veremos, afortunadamente, estos no necesitan ser específicos de Android, solo deben coincidir con la versión de la biblioteca SELinux.
Este procedimiento se ha probado utilizando árboles de código fuente de CyanogenMod y AOSP.
Compile e instale bibliotecas y primeras herramientas de Android SELinux
Primeras dependencias de instalación:
sudo apt-get install libapol-dev libaudit-dev libdbus-glib-1-dev libgtk2.0-dev \
libustr-dev python-dev python-networkx swig xmlto
En esta publicación, la variable $ANDROID_BUILD_TOP
almacena su ubicación de origen (el directorio donde emitió el repo sync
comando). Siéntase libre de cambiar su nombre a su gusto.
ANDROID_BUILD_TOP=~/android/system
cd $ANDROID_BUILD_TOP
source ./build/envsetup.sh
De manera predeterminada, la compilación de las utilidades principales de la política falla debido a que restorecond
el Makefile no puede localizar algunas bibliotecas. Tiene que editar este Makefile para usar rutas generadas dinámicamente por en pkg-config
lugar de codificadas (¡no confunda los backticks con comillas simples!):
sed -i 's/^CFLAGS ?= -g -Werror -Wall -W$/& `pkg-config --cflags --libs dbus-1 gtk+-2.0`/' \
$ANDROID_BUILD_TOP/external/selinux/policycoreutils/restorecond/Makefile
Siéntase libre de abrir el Makefile con algún editor de texto para asegurarse de que la modificación se haya tenido en cuenta correctamente.
Y ahora compila e instala:
cd $ANDROID_BUILD_TOP/external/bzip2/
make -f Makefile-libbz2_so
sudo make install
cd $ANDROID_BUILD_TOP/external/libcap-ng/libcap-ng-0.7/
./configure
make
sudo make install
cd $ANDROID_BUILD_TOP/external/selinux/
make -C ./libsepol/
sudo make -C /libsepol/ install
EMFLAGS=-fPIC make -C ./libselinux/
sudo make -C ./libselinux/ install
make -C ./libsemanage/
sudo make -C ./libsemanage/ install
make
sudo make install
make swigify
sudo make install-pywrap
sudo cp ./checkpolicy/test/{dispol,dismod} /usr/bin/
Atención: no se pierda laEMFLAGS=-fPIC
configuración de la variable de entorno al construirlibselinux
. Todavía no generará ningún error, pero en el siguiente paso no podrá construir SETools. En caso de que se lo haya perdido o haya hecho algo mal, simplemente emitamake clean
ay reinicie su compilación.
Compile e instale las herramientas de SELinux
Las herramientas de SELinux se proporcionan en una forma preconstruida que incluye:
- Python scripts (y sus envoltorios de script de shell) dentro del
$ANDROID_BUILD_TOP/external/selinux/prebuilts/bin/
directorio
- Paquetes de Python (incluidos los
*.o
archivos compilados) a continuación $ANDROID_BUILD_TOP/prebuilts/python/linux-x86/2.7.5/lib/python2.7/site-packages/
.
Hubiera esperado que el código fuente de estas herramientas estuviera disponible a continuación $ANDROID_BUILD_TOP/external
, pero no lo está. En realidad, no encontré ningún lugar donde Google compartiera la versión exacta de SETools que usaron (FYI, la GPL solo exige compartir el código si se ha modificado), por lo que tendremos que adivinar e intentar hacer lo mejor que podamos .
Las herramientas en sí son scripts de Python, esta es una nueva evolución de SETools 4 (en SETools 3, comandos como sesearch
ejecutables binarios codificados en C). Sin embargo, las herramientas mismas todavía muestran una versión de 3.3.8:
$ $ANDROID_BUILD_TOP/external/selinux/prebuilts/bin/sesearch --version
3.3.8
Entonces, supongo que Google tomó una instantánea de desarrollo inicial de SETools 4. Hasta 4.0.0 beta SETools dependía de libsepol
versoin 2.4, con la versión 4.0.0 comenzaron a confiar en la versión 2.5 de la biblioteca que no es compatible con la versión de SELinux incluido en Android 6.0 (puede intentar compilar esto, simplemente fallará).
Entonces, la elección más sabia parece ir con SETools 4.0.0 Beta.
Instalar dependencias suplementarias:
sudo apt-get install python-setuptools
Descargue y extraiga el código fuente:
cd ~/android/
wget https://github.com/TresysTechnology/setools/archive/4.0.0-beta.tar.gz
tar xzf 4.0.0-beta.tar.gz
cd ./setools-4.0.0-beta/
Debido a un error que afecta a Flex 2.5, debemos eliminar las -Wredundant-decls
marcas del compilador:
sed -i '/-Wredundant-decls/d' ./setup.py
Y finalmente compilar e instalar:
python ./setup.py build
sudo python ./setup.py install
Procedimiento genérico (o "Cómo desacoplarse")
En caso de que el procedimiento anterior no funcionó en su caso, aquí hay una vista de nivel superior sobre cómo intentar progresar.
Lamentablemente, no hay magia (ni ayudante :() por aquí: la única forma de hacer que este código se compile es el enfoque cíclico clásico "temible de ver y ver".
Intente compilar por primera vez, lo más probable es que falle debido a *.h
que no se encuentra algún archivo:
Buscar en el external/
directorio de Android :
find $ANDROID_BUILD_TOP/external -name filename.h
Si encuentra el archivo solicitado, esto significa que se ha incluido una versión específica de la biblioteca o herramienta correspondiente dentro del código fuente de Android. Por lo tanto, no debe intentar instalarlo desde el sistema de paquetes de Ubuntu, sino compilar e instalar la versión incluida en el código fuente de Android.
Tenga en cuenta que esto va en contra de los consejos generales que puede encontrar en los foros: "¿Su compilación falla debido a la falta de esta biblioteca? ¡Instale este paquete, entonces estará bien!" , al hacer esto, lo más probable es que tenga un problema peor: si se incluye una versión específica, probablemente se deba a que se necesita una versión específica (debido a problemas de compatibilidad o porque esta versión contiene cambios específicos de Google).
Por cierto, si se está preguntando: por supuesto, esta biblioteca o herramienta también puede tener dependencias que generan errores debido a *.h
que no se encuentra algún archivo, y sí, debe aplicar este mismo enfoque cíclico de "prueba y ver".
Buscar en todo el sistema:
find / -name filename.h 2>/dev/null
Si encuentra que "falta" el archivo ya está presente en su sistema en alguna ubicación de biblioteca compartida estándar, esto significa que esta dependencia probablemente ya se haya cumplido en su entorno, pero el Makefile que generó el error es demasiado tonto para encontrarlo.
Si llama directamente a este Makefile de forma manual, es posible que pueda establecer alguna variable de entorno que lo solucione ( LIBDIR=/usr/lib make
por ejemplo), de lo contrario puede que necesite modificar el Makefile en sí (el pkg-config
comando puede ser de gran ayuda para generar automáticamente los parámetros de compilación faltantes) .
Buscar en el sistema de embalaje:
apt-cache search filename-dev
Donde filename-dev
representa el nombre del archivo que falta en minúsculas con la .h
extensión reemplazada por el -dev
sufijo (por ejemplo, si Python.h
no se encuentra, busque python-dev
). Es posible que se necesiten algunos ajustes en el nombre exacto para encontrar el paquete correcto.
Si permanece estancado y que incluso una búsqueda rápida en Internet no proporcionó una respuesta clara, entonces apt-file
será su mejor amigo. apt-file
no está instalado de forma predeterminada, debe instalarlo y generar su base de datos:
sudo apt-get apt-file
sudo apt-file update
apt-file
le permite buscar paquetes (incluso los desinstalados) que proporcionan un archivo en particular. Para evitar tener demasiado resultado, recomiendo asociarlo con grep
lo siguiente:
apt-file search filename.h | grep -w filename.h
Si hay un paquete en el repositorio de Ubuntu que proporciona este archivo, entonces apt-file
debería poder encontrarlo.
Una vez que haya encontrado el paquete adecuado, instalarlo utilizando apt-get install packagename
, donde packagename
es el nombre de su paquete.
Consejo: Si usted se estropeó algo en su sistema, el comando para volver a instalar un paquete es la siguiente:apt-get reinstall pkg_name
. Funcionará incluso cuando no sea posible una eliminación e instalación clásica debido a la ruptura de dependencias (lo que es más probable para las bibliotecas del sistema).
Herramientas suplementarias
En este paso, ahora debe tener un entorno limpio que le permita investigar las reglas SELinux de Android tanto en formato compilado como en formato fuente.
Sin embargo, la mayoría de las posibilidades son que al final de su investigación desee tomar alguna medida. En su forma actual, su entorno no le permitirá modificar el sepolicy
archivo de un dispositivo . De hecho, este archivo no se puede reemplazar fácilmente: es parte del directorio raíz del dispositivo, y el contenido del directorio raíz se extrae en el momento del arranque desde un archivo de disco RAM, que a su vez se almacena en la imagen de arranque del dispositivo.
Así que todavía te pierdes dos cosas antes de que tu entorno esté completo:
- Una forma de acceder y modificar la imagen de arranque del dispositivo,
- Una forma de modificar su
sepolicy
archivo.
Afortunadamente, estos son precisamente el tema de las dos últimas secciones de esta publicación. :)
Obtener y actualizar la imagen de arranque del dispositivo
Las herramientas para buscar y actualizar la imagen de arranque de los dispositivos se pueden usar para una amplia variedad de cosas además de la manipulación de las reglas de SELinux. Por lo tanto, he creado una respuesta dedicada , por favor refiérase a ella.
Modificar las reglas SELinux del dispositivo
Tienes dos posibilidades principales aquí:
- Cree un nuevo
sepolicy
archivo a partir de las reglas en su árbol de origen (busque .te
archivos para encontrarlos: find $ANDROID_BUILD_TOP -name \*.te
se distribuyen en varios directorios).
- Modifique el
sepolicy
archivo utilizado actualmente por el dispositivo.
A menos que realmente necesite construir sus reglas desde cero, que es más una tarea relacionada con el desarrollo y, por lo tanto, fuera de alcance aquí, la segunda opción parece, con mucho, la más segura, ya que está seguro de que los únicos cambios serán los que su hecho explícitamente
Ha habido un proyecto para crear una herramienta que le permita descompilar un sepolicy
archivo en una forma recompilable, lo que permite editar libremente las reglas intermedias. Sin embargo, este proyecto ha sido abandonado en estado de prueba de concepto. Encontrará toda la información al final de esta publicación de blog , el resto del artículo contiene suficientes detalles para permitir que cualquier otra persona interesada se haga cargo.
La forma actualmente recomendada de alterar las sepolicy
reglas es otra ruta: modificando directamente el sepolicy
archivo binario. La herramienta de inyección de sepolicy permite precisamente eso y se mantiene activamente.
Para completar, tenga en cuenta que existe una bifurcación de esta herramienta. Agrega algunas características, algunas de ellas en la lista de tareas del autor original (como la posibilidad de eliminar una regla), no me pregunte por qué eligieron bifurcar en lugar de contribuir ...
Para compilar e instalar sepolicy-inject
, simplemente proceda de la siguiente manera:
cd ~/android/
git clone https://bitbucket.org/joshua_brindle/sepolicy-inject.git
cd ./sepolicy-inject/
LIBDIR=/usr/lib make
sudo cp ./sepolicy-inject /usr/bin/
Ejemplo de caso de uso
Digamos, por ejemplo, que desea agregar la autorización que coincida con el siguiente mensaje de error:
avc: denied { read } for pid=128 comm="file-storage"
path="/data/media/0/path/to/some/file"
dev="mmcblk0p28" ino=811035 scontext=u:r:kernel:s0
tcontext=u:object_r:media_rw_data_file:s0 tclass=file permissive=0
Tendrá que buscar la imagen de arranque del dispositivo, luego descomprímalo para acceder a su sepolicy
archivo.
Una comprobación rápida usando sesearch
muestra que, de hecho, no hay una regla de permiso (¡todavía!):
$ sesearch -A -s kernel -t media_rw_data_file -c file -p read ./sepolicy
$
El comando no tiene salida.
A continuación, utilice el comando siguiente para añadir la regla requerida (nótese la similitud entre sesearch
y sepolicy-inject
parámetros):
sepolicy-inject -s kernel -t media_rw_data_file -c file -p read -P ./sepolicy
Ahora podemos volver a llamar a nuestro sesearch
comando:
$ sesearch -A -s kernel -t media_rw_data_file -c file -p read ./sepolicy
allow kernel media_rw_data_file:file read;
$
sesearch
La salida muestra que la política se ha actualizado correctamente.
Ahora puede volver a empaquetar el boot.img
archivo del dispositivo y volverlo a flashear. Verificar la última hora de modificación del /sepolicy
archivo es una manera fácil de asegurarse de que su dispositivo ahora esté ejecutando el sepolicy
archivo recién actualizado .
Conclusión
Ahora debe tener un entorno completo que le permita inspeccionar y modificar libremente las políticas SELinux de dispositivos Android. ¡Disfrutar! :)
Como nota al margen, también hay herramientas que permiten analizar y modificar la política de SELinux directamente desde el dispositivo .