"Linux Gazette...haciendo de Linux algo un poco más divertido!"


"Cannot execute /bin/bash: Permission denied" - ¡solucionado!

Por: Ben Okopnik

Traducido al Español por: Juan Manuel López Agudo
el día 16 de Julio de 2000, para La Gaceta de Linux.


Sólo unos minutos antes de sentarme a escribir este artículo, logré fijar un problema que ha sido la maldición de mi existencia durante las dos últimas semanas. Puesto que es un problema que he visto a menudo mencionado en la Linux Gazette, generalmente expresado de una manera que hace imaginar al escritor de pie en una silla con un lazo alrededor de su cuello y escribiendo con los dedos de los pies, he decidido compartirlo con otros lectores, con la esperanza de ahorrarles el desgaste de una buena soga. Esto puede también servir como una buena guía de solución de problemas de software en general. Sean conscientes, sin embargo, que un problema de inicio de sesión podría involucrar a cualquiera de las areas descritas - lo que arregló mi propia máquina puede no ser la solución para las vuestras.

Hace un par de semanas, decidí instalar un MUA (Agente de usuario de correo electrónico) en mi máquina. Algo extraño a realizar, teniendo en cuenta que vivo en un velero anclado bien lejos de líneas telefónicas o eléctricas - pero tenía mis razones. He hecho esto en sistemas "en tierra" antes; era simplemente un poco de experimentación lo que quería hacer.

Well, como la arrogancia de los lemmings viene antes de caer por un precipicio, así lo hace un MTA (Agente de tranferencia de correo electrónico) antes de un MUA - necesitas algo que entregue el correo, ¡de otra manera no hay razón para escribirlo!. Así que, una instalación de MTA/MUA. No hay problema - conservo la distribución Debian completa en la partición Linux de mi disco duro; esto acelera la instalación, así como hace la búsqueda de paquetes una tarea trivial.

La verdad sea dicha, no me gusta "su", al menos no para las tareas trascendentales: el hecho de que conserve las variables de entorno del usuario original, en vez de asumir aquellas de la cuenta que es accedida haciendo "su", me ha causado unos cuantos "momentos interesantes". Si, un rápido cambio de permisos, o una modificación de un fichero de "/etc", está bien; pero para el trabajo serio, como instalar y desinstalar varios paquetes trascendentales (no estaba seguro todavía de que MTA quería), inicié a sesión como "root".

Manos a la obra. El Midnight Commander logra hacer el trabajo, con sólo tocar pocas teclas, de zambullirse y explorar dentro de un arbol de directorios, así como dejarte mirar dentro - e instalar - cualquier paquete Debian o RedHat. Veamos... ¿"sendmail"? (leer la página "man" incluida en el paquete, mirar en los documentos, instalarlo...) No, demasiado grande y complejo. Necesito algo un poco más sencillo. (desinstalarlo). ¿"exim"?... ¿"exmh"?... ¿"mh"?... "nmh"? Todos tienen el mismo procedimiento de "instalación/desinstalación", con la excepción de las librerias necesarias: en el momento en que instalo una librería, permanece instalada. Después de hacer esto un poco en un nuevo sistema, no recibo ninguna queja sobre "Required libraries missing" (librerías necesarias ausentes) - si no fuera por el hecho de que un número de librerías en cualquier distribución son elecciones "una u otra" (entrarían en conflicto entre ellas), yo instalaría el directorio "libs" completo ¡y nunca me preocuparía de ello otra vez!.

Sin embargo, todavia tenía que elegir un MTA. ¡Ah, "smail"! Fácil de instalar, sencillo de configurar, - hecho. La elección es fácil para un MUA - me gusta realmente la configurabilidad de "mutt" - ¡y he terminado! (Palabras proféticas...).

A menos que... Ahora , me encuentro que no puedo acceder más como un usuario que no sea el root. El mensaje que obtenía era:

Cannot execute /bin/bash: Permission denied

¿Qué demonios era esto?

¿Era alguna esotérica ilusión?
¿Alguna loca intrusión?
Estas eran elecciones a las que Salomón
por sí mismo nunca se enfrentó...'

Yo sabía que no había hecho nada en "/etc/password" - de la misma manera, nada en /etc - pero no estaba cien por cien seguro de que aquellos paquetes, seguros como se suponía que eran, estuvieran haciendo algo bajo mi "amparo" como "root". Asi que, rápidamente hice algunos chequeos serios - si, el usuario "ben" todavía existía en "/etc/password"; lo mismo para el grupo "ben" en "/etc/group"; introduciendo una cadena equivocada como contraseña provocaba el usual mensaje de "Login incorrect" en vez de "Cannot execute". Hmm.

Otro comprobación seria: creé un nuevo usuario ("joe"), con nueva contraseña y todo ("joe"), e intente entrar al sistema como ese usuario. Ningún avance, el mismo error. Algo en la secuencia de la entrada habia muerto, por razones desconocidas. (Adios, "joe"...)

En este punto, me asaltó un silencioso "¡eep!" de pequeño pánico, rápidamente cambié a otro terminal, e intenté entrar como root. ¡Fiuu!; sin problemas. Por lo menos, podía todavía tener acceso a la máquina cuando seguidamente la arrancara de nuevo... ¡Habría odiado hacer una copia de seguridad inmediata y una reinstalación!

Abramos "/bin". ¿Como están los permisos? Uh-uh...todos están puestos como 755 (-rwxr-xr-x); además, "login", "mount", "umount", "ping" and "su" están como SETUID (-rwsr-xr-x). Hasta ahora, todo va bien; ¿y los permisos en "/etc"? Todos parecen bien tambien - la mayoría 644 (-rw-r--r--), con algún casual 600 (-rw-------) aquí y allá, para los ficheros prohibidos para otros que no sean "root". Esta bien, intentemos algo tonto; sobreescribí "login" y "bash" con copias recientes, directamente de sus paquetes originales, para estar seguros de que no estaban corrompidos. No; todavía no hay suerte.

Espera, ¿y qué hay de "/home"? Si los permisos allí se hubieran cambiado y el usuario no pudiera entrar... Vaya, estaban bien también - 6775 (drwxrwsr-s). Al comprobar ".bashrc" y ".bash_profile" no se veía nada raro - y sus permisos eran correctos. Sólo por mirar, comprobé todos los otros subdirectorios en "/"; todos excepto "/root" eran accesibles para lectura por todos, lo que era correcto.

Hay un par de ficheros en "/var" que mantienen un registro de quién está en el sistema, cuando salen, etc.; si estos "chicos" están corruptos, *toda* clase de cosas extrañas e impredecibles pueden ocurrir. Así que - ¡tiempo de medidas de emergencia! - Tecleé

cat >/var/log/wtmpcat >var/run/utmp
lo que borraría sus contenidos y los dejaría como archivos vacíos. [Él realmente escribió esto sin el "cat", pero he puesto "cat" para dejar claro que el ">" era parte de la línea de comandos y no el prompt del shell. -Ed.] Me salí de todos los terminales ( así "utmp" and "wtmp" obtendrían algun dato), y... el resultado acostumbrado.

¿Los permisos de "/dev/ttyX" y "/dev/vcsX" (terminales y consolas virtuales)? Todos parecían bien también; estaba empezando a perder la esperanza.

Espera, ¿y que hay de una estrategia sistemática? Obtengamos una idea de lo que exactamente está ocurriendo antes de ir en todas direcciones. Una mirada rápida a la Guía del Administrador del Sistema (SAG) para refrescar mi memoria - ah, ahí está el proceso de entrada al sistema:


De la "Guía del Administrador del Sistema", por Lars Wirzenius

Primero, "init" se asegura de que hay un programa "getty" para la conexión del terminal (o consola). "getty" escucha al terminal y espera que el usuario notifique que esta listo para entrar al sistema (esto normalmente significa que el usuario debe teclear algo). Cuando advierte un usuario, "getty" produce un mensaje de bienvenida (almacenado en "/etc/issue"), y pide el nombre de usuario, y por último, ejecuta el programa "login". "login" obtiene el nombre de usuario como parámetro, y pide la contraseña. Si estas son correctas, "login" inicia el shell establecido para el usuario; de otra manera, sólo sale y termina el proceso (tal vez después de dar al usuario otra oportunidad de introducir el nombre de usuario y la contraseña). "init" advierte que el proceso ha terminado e inicia un nuevo "getty" para el terminal.

                                                           ' ' ' ' ' ' ' ' '
                           ------------                    '  Conversión   '
                          |   Start    |                   ' GIF2ASCII por '
                           ------------                    ' "fastfingers" '
                                V                          '    Programa   '
                        -------------------                ' Copyleft 2000 '
           ______ | init: se bifurca + ejecuta |__         ' ' ' ' ' ' ' ' '
          |       |       "/sbin/getty"        |  |
          |            -------------------        |
          ^                     V                 ^
          |          ------------------------     |
          |         | getty:espera al usuario |   |
          |          ------------------------     |
          ^                     V                 ^
          |          -------------------------    |
          |         | getty: lee  el usuario, |   |
          |         | ejecuta "/bin/login"    |   |
          |          -------------------------    |
          ^                     V                 ^
          |          -------------------------    |
          |         | login: lee la contraseña|   |
          |          -------------------------    |
          ^    	                V                 ^
    	  |    	               / \                |
          |                   /   \               |
     -------------           /     \              |
    | Login: sale |--<--No--/¿casan?\             |
     -------------          \       /             ^
                             \     /              |
                              \   /               |
                               \ /                |
                                | Yes             ^
                                V                 |
                    --------------------------    |
                   | login:ejecuta("/bin/sh") |   |
                    --------------------------    ^
                                V                 |
                     ----------------------       |
                    |  sh: lee y ejecuta   |      |
                    |      comandos        |      ^
                     ----------------------       |
                                V                 |
                            ----------            |
                           | sh: sale |----------- 
                            ----------
Figura 8.1: Entradas via terminales: la interacción de "init", "getty", "login", y el shell.

Advierte que el único nuevo proceso es el creado por init (usando la llamada de sistema "fork"); "getty" y "login" solo reemplazan el programa que corre en el proceso (usando la llamada de sistema "exec").


Siguiendo el proceso, podemos ver que todo se encuentra levantado hasta la última parte - el 'exec("/bin/sh")', es decir - parece OK. Es durante o después de ese punto cuando las cosas se descontrolan. El problema era ahora descender a las llamadas de sistema, algo que no estaba seguro de poder abordar... y con todo, esa parte de información contenía todo lo que necesitaba saber; sólo que yo no sabía como aplicarla. Más tarde, esto se volvería por sí mismo evidente.

Alrededor de los siguientes diez días más o menos, cada vez que entraba al sistema intentaría algo nuevo; algunas cosas totalmente estrambóticas y que improbablemente funcionaran; otras, brillantes ideas que producían una gran decepción cuando el endiablado mensaje otra vez mostraba su cabeza. Nada funcionaba. Reemplace "getty"; probé una pareja de shells distintos de "/bin/bash"; probé hacer un "su" al usuario "ben"; comprobé los archivos de registro (ellos mostraban que "ben" había entrado satisfactoriamente (!), lo que me decía que "login" estaba bién; el fallo se producía cuando pasaba el proceso a "bash" - (¡yo lo sabía!)...

Después de encontrar sólo unas pocas referencias a esto en la Red - la mayoría en japonés, sueco y alemán (me las arregle para descifrar los dos últimos - uno de los cuales sugería chequear los permisos de "/"; excelente idea... que no funcionó en mi caso), envié un resumen del problema a The Answer Guy - ¡Hola! <grin> Desafortunadamente debe haber sido abrumado por todas esas cuestiones sobre Windows 2000 que a el le encanta contestar... de cualquier modo, me abandonaron a mis propios recursos.

¡Ah - "strace"! Recuerda "strace"; "strace" es tu amigo... Una pieza de software verdaderamente fantástica que rastrea la ejecución de un programa y la describe, paso a paso. ¡Vamos allá!

Puesto que tienes que haber entrado en el sistema para ejecutar un programa, yo ejecuté

strace -s 10000 -vfo login.ben login ben

desde mi actual VT; esto significa "Ejecuta "strace" al entrar como "ben"; graba todas las líneas hasta 10000 caracteres como mucho (no quería perder ningún mensaje, no importaba lo largos que fueran); haz la salida prolija; rastrea cualquier proceso bifurcado; lleva el resultado a un fichero llamado "login.ben"". Entonces, como baseline, ejecuté

strace -s 10000 -vfo login.root login root
- y ahora, tenía dos ficheros para comparar. El del "root" era sobre dos veces mas largo que el de "ben" - eso tenía sentido, ya que un login satisfactorio va a ejecutar todo lo que contienen los ficheros "~/.bash*".

"strace login" se dirige a una muy informativa lectura. Si no hubiera leído la Guía del Administrador del Sistema, me habría dado la información exacta - mucho más detallada. Muestra todas las librerías que son leídas, cada fichero examinado por "login", el procedimiento de comparación para "group" y "password"... la única cosa que NO muestra era la razón del fallo; el hecho en sí mismo, exactamente en el punto del proceso en el que esperaba que estára:

(300+ lines elided)
execve("/bin/bash", ["-bash"], ["TERM=linux", "HZ=100", "HOME=/home/ben",
     "SHELL=/bin/bash", "PATH=/bin:/usr/bin", "USER=ben", "LOGNAME=ben",
     "MAIL=/var/spool/mail/ben", "LANG=C", "HUSHLOGIN=FALSE"]) = -1 EACCES
     (Permission denied)
write(2, "Cannot execute /bin/bash: Permission denied\n", 44) = 44

Vaya. La última cosa que el pobre "login" intentó hacer, antes de tropezar consigo mismo, era "execve bash" con las variables definidas recogidas de "/etc/password", "/etc/login.defs", y demás - todos ellas parecían estar bien - y escribir aquellos 44 odiosos caracteres a "stderr" (descriptor de salida 2). Básicamente, lo que ya me había imaginado.

Advertí, sin embargo, que "login" estaba abriendo un número de librerías en "/lib" que eran necesitadas por el fichero de configuración del "Name Service Switch" (/etc/nsswitch.conf). ¿Y si una de las mencionadas librerías estaba corrompida? Esto estaría en consonancia con la teoría de las llamadas de sistema - puesto que ¡de las librerías es de donde vienen las llamadas al sistema! Comprobemos la librería que maneja las entradas al sistema para NSS (ver `man nsswitch'):

dpkg -S libnss_compat-2.0.7.so
("Dime, Oh Poderoso Debian Package Manager, ¿de donde viene dicho programa?"), y el Oráculo Debian, en su sabiduría, respondió -
libc6: /lib/libnss_compat-2.0.7.so

Humm. El verdadero corazón de las librerías de Linux. Bien... una rápida sustitución de todas las "/lib/libnss*" ... y ningún cambio. Siguiente idea.

Este proceso me hacía pensar, sin embargo. Algo estaba seguro "oliendo a podrido" - ¿tal vez necesitaba comprobar los permisos de los ficheros en "/lib"?

El único problema era que no sabía como se suponía que tendrían que estar. Como veis, la mayoría de las librerías estan establecidas como "root.root 644" - propietario "root", grupo "root", usuario - leer/escribir, grupo - sólo lectura, otros - sólo lectura. Hay unas pocas, sin embargo, que deberían estar establecidas como "root.root 755" - como más arriba, pero con permisos de ejecución para cualquiera... y sin mirar una instalación de Linux recien hecha, no tenía ni idea de como era correcto.

¡ESPERA un minuto! Como había mencionado en un "2-cent tip" que envié a LG, me gustaba mantener una copia de un conjunto de ficheros de la "instalación basica" de Debian (7 ficheros, sobre 15MB) en mi partición DOS como una utilidad de rescate - ¡debería tener todo lo que necesitaba!


Y así era. El Midnight Commander, vía su "Sistema de Fichero Virtual", te permite explorar ficheros comprimidos como si fueran directorios; una mirada dentro de "base2_1.tgz#utar/lib" (la sintaxis VFS usada por MC) me mostró que una de las primeras librerías - ld-2.0.7.so - se suponía que debía estar establecida como 755. Diez segundos después, era el propietario de un flamante Terminal Virtual - como el usuario "ben".

Si, comprobé los permisos en todas las demás librerías; "ld-2.0.7.so" era la única que fué afectada. El único "enigma" restante era como cambiaron los permisos al principio... pero sospecho que esa cuestión nunca será respondida.


Para no variar, las lecciones que Linux enseña son duras - pero apreciables. Hay *siempre* una manera de resolver un problema; de forma reconocida, a menudo el camino más fácil es reinstalar el sistema, pero esto no te enseña las "entrañas" de un sistema operativo de la forma en la que localizar un problema lo haría. En mi caso, la reinstalación hubiera sido relativamente sencilla: tengo un par de discos de repuesto, fácilmente lo bastante grandes para mantener mis datos "hasta el último minuto" de tal manera que incluso no necesitara tocar mis copias de seguridad, y una instalación básica de Debian me tomaría menos de 10 minutos. No estaba interesado en eso. El principal pensamiento en mi mente era: "¿Qué sucedería si esto ocurriera en la casa de un cliente?". Necesitaría saber cual era la solución correcta... y gracias a la persistencia - no, a la pura obstinación - tuve éxito.

No sugiero que cada uno de vosotros machaqueis vuestro cerebros contra algun difícil problema una vez a la semana sólo para "mantenerlo en forma" - pero si sugiero que useis una estrategia metódica, basada en el conocimiento logrado de la lectura de los adecuados COMOs y otra documentación disponible antes de echar mano ese CD de instalación otra vez más. Habrá momentos en que no te apetecerá nada mejor que reir de forma maníaca viendo como tu equipo se va reduciando al tamaño de un alfiler, dejándolo caer de lo más alto del Edificio Empire State... y habrá otros en los que la satisfacción de haber solucionado un complejo problema de esta clase te haga golpearte el pecho y hacer imitaciones de Tarzán.

Ahora, si me perdonais, tengo un chimpancé y un elefante con los que se supone que debo encontrarme...

Feliz "Linuxeo" a todos,
Ben Okopnik


Copyright © 2000, Ben Okopnik
Publicado en el número 52 de Linux Gazette, Abril 2000