La columna 80

El blog técnico-personal de Ángel J. Vico… en español

Corrupción de los permisos de las aplicaciones Android

Posted by Ángel J. Vico en 15 de May de 2011

El problema que voy a describir en este post es, afortunadamente, muy poco frecuente. De hecho, si le dedico un post es porque he tenido la mala suerte de toparme con él tras actualizar el firmware de mi Samsung Galaxy Spica (i5700). Después de muchas pruebas tratando de averiguar las causas, y tras encontrar una solución provisional primero y resolverlo definitivamente (o eso espero) después, lo menos que podía hacer es contarlo aquí, por si alguien más tuviera la misma mala suerte que yo.

El problema se suele manifestar tras arrancar el teléfono, ya sea tras un reinicio o después de haberlo apagado. La primera sorpresa (aunque no pasa todas las veces) es que el teléfono te muestra de nuevo el asistente de bienvenida de Android, pidiéndote que asocies tu cuenta de Google y demás.

Lo primero que piensas es que se han restablecido los datos de fábrica, o sea, que se ha borrado todo lo que tenías en el teléfono y ha quedado como recién instalado. Pero en seguida descubres que no es así, dado que las aplicaciones que instalaste siguen apareciendo en la lista. Lo malo es que, cuando tratas de ejecutarlas, la mayoría dan error y se cierran. De hecho, lo más probable es que las aplicaciones que se ejecutan al arrancar ya hayan mostrado sus respectivas pantallas de error antes incluso de que consigas cerrar el tutorial “Aprende a utilizar tu teléfono”.

Si, además, eres de los que odias el teclado predeterminado de Android y tienes instalado otro, es muy posible que te esté apareciendo su pantalla de error cada 4 o 5 segundos, haciendo aún más aterradora la situación. Lo digo por propia experiencia.

Lo único que parece funcionar son las aplicaciones que venían incluidas en el firmware. Sin embargo, al abrir cualquiera de ellas se muestra como si nunca la hubieras ejecutado, sin rastro de tu configuración o datos.

He de decir que no pasa con absolutamente todas las aplicaciones. A veces alguna de ellas sigue funcionando como si nada hubiera pasado. Pero son las menos y sirven de poco consuelo.

Ante este desolador panorama surgen muchas dudas: ¿por qué no funcionan las aplicaciones instaladas? ¿Qué ha provocado esta situación? Y sobre todo, ¿ahora cómo lo arreglo sin tener que reinstalar todo de nuevo? Y, finalmente, ¿cómo puedo evitar que me vuelva a pasar esto?

A todas estas preguntas voy a tratar de responder en este post.

¿Por qué fallan las aplicaciones?

Lo primero que se me pasó por la cabeza cuando me pasó por primera vez fue que había pasado algo con el Apps2SD. Pero lo cierto es que, pensándolo con cuidado, si se hubieran perdido los enlaces simbólicos o no se hubiera montado correctamente la partición Linux de la tarjeta SD, no aparecería como instalada ninguna de nuestras aplicaciones (sólo las que vienen de serie con el firmware). Y no era así.

De hecho, un rápido vistazo desde línea de comandos (con un emulador de terminal o con las herramientas del SDK) nos mostraba una aparente normalidad: los enlaces simbólicos existían, los paquetes de las aplicaciones (.apk) estaban en su sitio y las carpetas de datos también parecían estar bien.

Que todos los paquetes se hubieran corrompido a la vez no parecía muy probable y no explicaría que las aplicaciones del sistema se comportaran como si nunca se hubieran ejecutado. Todo apuntaba a que el problema estaba en los datos. Lo malo es que los datos también parecían estar bien. Incluso los datos de las aplicaciones del sistema estaban ahí.

Así que sólo cabía una explicación: las aplicaciones no podían acceder a los datos. Aunque no acababa de entender por qué.

Después de que me pasara una cuantas veces, todas ellas seguidas de reinstalaciones completas (algunas incluso volviendo temporalmente al firmware 2.1 oficial), acabé descubriendo un fichero que me dio la pista necesaria para encontrar en Internet la explicación a lo que pasaba. Se trata de /data/system/uiderrors.txt. Este fichero estaba lleno de mensajes de error como estos:

04/04/11 06:12: System package com.android.browser has changed from uid: 10044 to 10045; old data erased
04/04/11 06:12: Package com.helloexpense has mismatched uid: 10049 on disk, 10057 in settings

He ahí la explicación (o parte de ella). Aunque para entender el problema va a ser necesario que explique primero algunos detalles internos de Android.

Aunque Android no se diferencia mucho de un sistema operativo para equipos de escritorio, el entorno de movilidad al que se orienta le fuerza a tener algunas características que en otros ambientes pueden no ser tan imprescindibles. Y no sólo por las limitaciones de hardware que tienen (cada vez menos) los dispositivos móviles. También la percepción y las expectativas del usuario de estos dispositivos es diferente.

Uno de esos aspectos críticos es la estabilidad general del sistema. Mientras que un usuario de PC suele asumir (con resignación) que su equipo puede dejar de responder completamente en un momento dado (lo que viene a ser quedarse colgado), el que utiliza un teléfono móvil no tolerará algo así, por muy inteligente que sea su teléfono. Un teléfono no se puede colgar. Una aplicación que no funcione bien no puede paralizar o corromper todo el sistema.

Pare evitar esto, Android, además de ejecutar cada aplicación en su propio espacio de memoria y con su propia instancia de la máquina virtual Dalvik, también juega con los permisos del sistema de archivos. Para ello crea un usuario para cada aplicación y lo convierte en el propietario tanto del paquete de dicha aplicación como de su directorio de datos. Luego ajusta los permisos de forma que sólo ese usuario pueda modificar el paquete de la aplicación y acceder a la carpeta de los datos. El resto de los usuarios sólo tienen acceso de lectura al paquete de la aplicación, pero no pueden ni leer ni escribir los datos de otra aplicación que no sea la suya.

Esta configuración permite que una aplicación pueda, por ejemplo, mostrar los nombres e iconos de las aplicaciones instaladas; pero lo que no podrá hacer nunca es acceder a los datos de otra (incluso aunque sea del mismo desarrollador).

Toda esta información se recopila en el archivo /data/system/packages.list. En este archivo se incluye una línea por cada aplicación instalada similar a esta:

com.android.browser 10045 0 /data/data/com.android.browser

Ahí se relaciona cada aplicación (identificada por el nombre de su paquete) con el identificador del usuario que se le ha asignado y su directorio de datos. El 0 del ejemplo indica que la aplicación se ejecutará en modo normal y no en modo de depuración (en ese caso sería un 1).

Relacionado con ese archivo hay otro, /data/system/packages.xml, que también contiene información sobre las aplicaciones instaladas. En concreto, datos extraídos del manifiesto, como la versión o los permisos requeridos. Todo ello asociado también al usuario asignado.

Resulta que lo que provoca el problema que tenemos entre manos es la corrupción de uno de estos archivos. ¿Qué hace Android si al arrancar detecta que le ha pasado algo a estos archivos? Los reconstruye. El problema, por lo que parece deducirse de los errores, es que no se toma la molestia de averiguar qué usuario se asoció a cada aplicación, sino que asigna los usuarios según se va encontrando los paquetes instalados.

No sé por qué lo hace así. De hecho, puede que sea bastante más complejo de lo que expongo aquí, e incluso que haya una explicación lógica para ese comportamiento (quizás algún tema de seguridad). Lo cierto es que me cansé de seguir investigando los motivos. Si algún día estoy muy aburrido, a lo mejor retomo el tema y completo el post (aunque si algún lector conoce la respuesta, espero que no dude en compartirla en los comentarios).

Sea como sea, el resultado es que, desde el momento en que Android soluciona la corrupción, intenta ejecutar cada aplicación con un usuario diferente al que tiene los permisos. Como el paquete es de lectura para todos los usuarios, la aplicación inicia su ejecución. Pero en cuanto intenta acceder a los datos no puede y se produce el error.

La explicación al comportamiento de las aplicaciones del sistema está también en los mensajes de error mostrados más arriba: cuando Android detecta que el usuario es diferente, asume que ha cambiado, borra su directorio de datos y lo crea de nuevo. Por eso esas aplicaciones no dan errores pero se comportan como si nunca se hubieran ejecutado.

Y ahora, ¿cómo lo arreglo?

Si has llegado a este post motivado por el hecho de estar sufriendo este mismo problema en tu teléfono, estarás deseando que explique de una vez cómo puedes conseguir que todo vuelva a la normalidad sin reinstalar todo de nuevo. Bien, pues ha llegado el momento.

La solución al problema es relativamente sencilla. Si las aplicaciones no pertenecen a los usuarios asignados, o cambiamos la asignación o cambiamos los propietarios para que coincidan. Dado que el problema se origina al corromperse los archivos que registran las asignaciones, lo mejor va a ser que no los toquemos. Es más seguro cambiar el propietario de cada aplicación para que se corresponda con el asignado.

Afortunadamente, no tenemos que hacerlo a mano. Hay un script (creado con la colaboración de unos cuantos desarrolladores) que hace esta tarea automáticamente. Algunos firmwares lo incluyen de serie e incluso ciertos menús de recuperación incorporan una opción para ejecutarlo directamente. En cualquier caso, podemos obtener la versión más actual del script aquí.

Hay que descargarlo con el nombre fix_permissions.sh. Lo más sencillo es copiar el texto y pegarlo en un editor que soporte formato Unix como Notepad++. Una vez guardado (repito, en formato Unix) lo copiamos a la raíz de la tarjeta SD del teléfono, algo que podemos hacer con las utilidades del SDK:

adb push fix_permissions.sh /mnt/sdcard/

Supongo que ya lo sospecharás, pero este script no funcionará si no tenemos acceso root al teléfono. Aunque si se ha producido el problema, lo más seguro es que ya lo tengamos, dado que prácticamente todos los firmwares no oficiales lo incluyen y en los oficiales no debería ocurrir.

Para ejecutar el script tendremos que acceder al terminal con adb shell (conectándolo a un PC) o con un emulador de terminal (desde el propio teléfono) y ejecutar los siguientes comandos:

su
sh /sdcard/fix_permissions.sh

Si el enlace sdcard no existiera, podríamos sustituirlo por /mnt/sdcard en el segundo comando. Si se produce algún error al ejecutarlo, podemos probar a reiniciar en el menú de recuperación y ejecutar de nuevo el script usando adb shell (aunque tendremos que montar la SD antes, desde el propio menú de recuperación). Al terminar conviene reiniciar el teléfono.

Esto debería asociar correctamente los usuarios, aunque puede que alguna aplicación siga dando problemas. En ese caso, lo mejor es desinstalar y volver a instalar la aplicación problemática.

¿Y cómo evitamos que vuelva a pasar?

Lo cierto es que he explicado por qué pasa lo que pasa y como resolver la situación, pero aún no he dicho nada sobre qué provoca esa corrupción que desencadena el desastre. La solución de corregir la asignación de usuarios hace que todo vuelva a funcionar, pero no evita que los archivos se vuelvan a corromper de nuevo. Si no modificamos lo que provoca las corrupciones, el problema se volverá a reproducir… más tarde o más temprano.

Pero, claro, ¿qué provoca las corrupciones?

No es una pregunta sencilla de responder. Mis primeras sospechas, como ya he comentado, fueron para el Apps2SD. Sobre todo porque alguna vez la corrupción se manifestó justo al reiniciar tras activarlo. Pero, aunque todo el trasiego de información entre la SD y la memoria interna que se produce al mover las aplicaciones y crear los enlaces puede aumentar las probabilidades de que surja el problema, lo cierto es que también obtuve corrupciones sin llegar a activar el Apps2SD. Así que tuve que descartarlo.

Después mis sospechas fueron pasando de una aplicación a otra, pero sin llegar a conseguir pruebas irrefutables contra ninguna de ellas. Durante cerca de un mes el problema fue surgiendo una y otra vez de forma esporádica sin que pudiera asociarlo a ningún elemento o acción en concreto. De hecho, podía estar varios días funcionando bien y, sin realizar cambio alguno en el sistema, arrancar un día con todas las aplicaciones sin funcionar. Y me temo que, a día de hoy, sigo sin saber con total exactitud cuál es el causante.

Pero, si estás sufriendo este problema, y antes de que la desesperación se apodere de ti, debes saber que no estaría escribiendo esto si no creyera haberlo resuelto. Porque… sí, en el momento de escribir estas líneas hace cerca de un mes que no he vuelto a tener problemas de corrupción. Y, aunque eso no es una garantía absoluta, es bastante más que la semana que, como mucho, me duraba el sistema estable después de cada reinstalación (o reparación cuando averigüé como hacerlo).

Lo malo es que, la última vez que me pasó, hice dos cambios simultáneamente y ahora no sé exactamente cuál de ellos solucionó el problema (o, al menos, disminuyó notablemente su probabilidad). Lo que hice fue cambiar el sistema de archivos de la partición de datos de ext4 a ext2 y cambiar el kernel que traía el firmware por otro. Desde entonces, todo ha ido bien.

He de decir que el kernel lo reemplacé por la versión anterior del mismo (porque en algunos foros lo consideraban mucho más estable), por lo que, seguramente, fue mucho más efectivo el usar ext2 en lugar de ext4.

Eso no quiere decir que ext4 sea el problema. Mucha gente lo usa y lo recomienda para la partición de datos. Mi opinión personal es que el problema lo provocaba la combinación de ambas cosas. O sea, que el kernel que tenía instalado (y que a otros les funciona sin problemas) no se terminaba de llevar bien con ext4. O, al menos, no en mi teléfono.

Así que, aparte de explicar por qué fallan las aplicaciones y cómo arreglar las asignaciones de usuarios erróneas, lo único que puedo aportar en este post de cara a ayudarte a resolver este problema, si también lo estás teniendo, es un consejo: prueba a usar ext2 si estás usando ext4 en la partición de datos (se puede cambiar en el menú de recuperación, como ya expliqué en el post sobre la instalación del firmware 2.2) y/o prueba con otro kernel.

Y si tienes más información sobre el problema o sobre cómo solucionarlo, no dudes en dejar un comentario.

Recuerda que en esta página dispones de enlaces a todos los artículos sobre Android que he publicado en La columna 80.

Deja un comentario