1. Introducción a seandroid
SEAndroid es un conjunto de mecanismos de seguridad del sistema con SELinux como núcleo lanzado oficialmente por Google en Android4.4. En el código fuente de Android, la configuración de seandroid predeterminada del sistema se almacena en la siguiente ruta:
/home/qiang/lineageOs/system/sepolicy
El directorio almacena los archivos de configuración como adbd, system_server, aplicación del sistema y aplicación de terceros.
Como el sistema Android introdujo la estrategia seandroid. Refuerce las restricciones de acceso de la aplicación a los recursos. La seguridad se mejora enormemente. Por ejemplo, tome un ejemplo de cómo obtener wifi mac como ejemplo:
Muchas aplicaciones en la aplicación de Android obtienen la dirección mac wifi del teléfono móvil leyendo / sys / class / net / wlan0 / address. Los permisos para ver el archivo a través del comando adb son los siguientes:
C:\Users\Qiang>adb shell ls -la /sys/class/net/wlan0/address
-r--r--r-- 1 root root 4096 2021-01-12 14:57 /sys/class/net/wlan0/address
Lo anterior muestra que la aplicación móvil puede leer y acceder al archivo. Pero en Android 10, el sistema está configurado con el permiso de la política seandroid que la aplicación normal no puede leer / sys / class / net / wlan0 / address. Causó un error de lectura en Android 10, lo que provocó que se denegara el permiso. Dado que seandroid refuerza la seguridad del sistema, si desea que una aplicación acceda a un determinado directorio o ruta del sistema, debe configurar específicamente la estrategia de archivos te. Es un poco difícil de configurar para los desarrolladores que no están familiarizados con la configuración de seandroid. ¿Hay alguna forma de acceder al archivo o directorio sin configurar el archivo de política de seandroid y establecer el permiso de lectura del archivo o directorio? La respuesta es cerrar Seandroid a nivel mundial .
2. Discusión sobre la forma de cerrar Seandroid en Android
1. Utilice el comando setenforce para cerrar temporalmente
El comando es el siguiente
adb shell setenforce 0
El comando setenforce solo puede apagar temporalmente seandroid, y si el teléfono se reinicia, se restaurará a su estado normal.
La ruta de setenforce en el código fuente de Android es la siguiente:
external/toybox/toys/android/setenforce.c
El código de implementación de setenforce es el siguiente:
#define FOR_setenforce
#include "toys.h"
void setenforce_main(void)
{
char *new = *toys.optargs;
int state, ret;
if (!is_selinux_enabled()) error_exit("SELinux is disabled");
else if (!strcmp(new, "1") || !strcasecmp(new, "enforcing")) state = 1;
else if (!strcmp(new, "0") || !strcasecmp(new, "permissive")) state = 0;
else error_exit("Invalid state: %s", new);
ret = security_setenforce(state);
if (ret == -1) perror_msg("Couldn't set enforcing status to '%s'", new);
}
A partir del código anterior, podemos ver que setenforce finalmente llama a la función security_setenforce para completar el control de selinux.
2. Cierre selinux en el kernel
Configure SECURITY_SELINUX en falso en el kernel, recompile el kernel y actualice la máquina. Seandroid se puede cerrar de forma permanente.
La siguiente es la información de configuración después de que selinux se desactive en el archivo .config de la compilación del kernel probada:
CONFIG_SECURITY_SELINUX=n
3. Cierre selinux cuando comience el proceso de inicio.
Durante el inicio del sistema Android, el proceso init inicializará selinux. Al leer el archivo / proc / cmdline, determine si el valor de androidboot.selinux necesita habilitar selinux. Por lo tanto, podemos forzar la operación de apagado cuando el proceso init inicializa selinux.
A continuación, se discutirá la tercera opción para lograr el cierre global de selinux.
3. Cierre globalmente selinux en el proceso de inicio
1. Análisis del proceso de inicialización de Selinux en el proceso de inicio
Las rutas de archivo relacionadas con la inicialización de selinux en el proceso init son las siguientes:
system/core/init/selinux.cpp
system/core/init/main.cpp
El proceso de inicialización aproximado es el siguiente:
a. La función principal en main.cpp llama a SetupSelinux en selinux.cpp:
int main (int argc, char ** argv) {
...省略
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
...省略
}
b. La función SetupSelinux en selinux.cpp se implementa de la siguiente manera:
int SetupSelinux (char ** argv) {
...省略
SelinuxInitialize();
...省略
return 1;
}
c. SetupSelinux llama al método SelinuxInitialize. El código del método SelinuxInitialize es el siguiente:
// SelinuxInitialize puede ver que se llama al método IsEnforcing para determinar
void SelinuxInitialize() {
...省略
bool kernel_enforcing = (security_getenforce() == 1);
//判断是否强制模式
bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) {
//调用security_setenforce函数,和setenforce原理一样
if (security_setenforce(is_enforcing)) {
PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
}
}
...省略
}
d. El método IsEnforcing se implementa de la siguiente manera:
// Determine si se requiere el modo obligatorio
bool IsEnforcing() {
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
Se puede saber por IsEnforcing que si sigue devolviendo false, selinux se cerrará.
2. Cerrar globalmente la modificación de Selinux por la fuerza
El proceso de inicialización de selinux desde el proceso de inicialización anterior puede proporcionar dos esquemas de modificación para cerrar globalmente.
-
La primera es modificar la función IsEnforcing para que siempre devuelva falso. Modifique de la siguiente manera:
bool IsEnforcing() {
///ADD START
if(1>0)
{
//一直返回false
return false;
}
///ADD END
if (ALLOW_PERMISSIVE_SELINUX) {
return StatusFromCmdline() == SELINUX_ENFORCING;
}
return true;
}
-
El segundo es modificar el método SelinuxInitialize para llamar activamente a security_setenforce (false) en la función. Después de la modificación de la siguiente manera:
void SelinuxInitialize() {
Timer t;
LOG(INFO) << "Loading SELinux policy";
if (!LoadPolicy()) {
LOG(FATAL) << "Unable to load SELinux policy";
}
bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) {
PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
}
}
//直接调用security_setenforce方法来关闭
///ADD START
security_setenforce(false);
///ADD END
if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
}
// init's first stage can't set properties, so pass the time to the second stage.
setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
}
Después de la modificación, compile el código fuente y actualice la máquina, y tendrá efecto después del arranque.
Divertido desarrollo y personalización del código fuente del sistema Android10 Más artículos:
Divertido desarrollo y personalización del código fuente de Android10 (2) operación de flasheo
Siga la cuenta pública para conocer los artículos más recientes.