Soy root Me gustaría saber si un usuario no root tiene acceso de escritura a algunos archivos, miles de ellos. ¿Cómo hacerlo de manera eficiente mientras se evita la creación de procesos?
                    
                        shell
                                files
                                permissions
                                users
                                
                    
                    
                        Howard
fuente
                
                fuente

access(2)con un UID real configurado adecuadamente (por ejemplo, a través desetresuid(2)o el equivalente portátil)? Quiero decir, sería difícil hacer eso desde bash, pero estoy seguro de que Perl / Python puede manejarlo.[ -wgeneralmente usan acceso (2) o equivalente. También debe configurar los gids además de uid (como lo hacen su o sudo). bash no tiene soporte incorporado para eso, pero zsh sí.chgrpen cualquier shell.Respuestas:
Quizás así:
Lo anterior ejecuta un solo programa externo para cada archivo, a saber
stat(1).Nota: Esto supone
bash(1), y la encarnación de Linuxstat(1).Nota 2: Lea los comentarios de Stéphane Chazelas a continuación para conocer los peligros y limitaciones pasados, presentes, futuros y potenciales de este enfoque.
fuente
-. En su lugar, puede modificarlo para aceptar una lista delimitada por NUL conread -d ''util-linux) que están específicamente escritos para Linux, alstatque te refieres no lo es, es un comando GNU que se ha portado a la mayoría de los sistemas, no solo Linux. También tenga en cuenta que tenía unstatcomando en Linux mucho antes de questatse escribiera GNU (elstatzsh incorporado).stat(1)". Me refiero a unastat(1)que acepta la-c <format>sintaxis, en oposición a, por ejemplo, la sintaxis BSD-f <format>. También creo que estaba bastante claro a que no me referíastat(2). Sin embargo, estoy seguro de que una página wiki sobre la historia de los comandos comunes sería bastante interesante.TL; DR
Debe preguntar al sistema si el usuario tiene permiso de escritura. La única forma confiable es cambiar el uid efectivo, el gid efectivo y los gids de suplementación a los del usuario y usar la
access(W_OK)llamada al sistema (incluso eso tiene algunas limitaciones en algunos sistemas / configuraciones).Y tenga en cuenta que no tener permiso de escritura en un archivo no garantiza necesariamente que no pueda modificar el contenido del archivo en esa ruta.
La historia mas larga
Vamos a considerar lo que se necesita, por ejemplo, para un usuario $ a tener acceso de escritura
/foo/file.txt(suponiendo que ninguno de/fooy/foo/file.txtson enlaces simbólicos)?El necesita:
/(no es necesarioread)/foo(no es necesarioread)/foo/file.txtYa puede ver que los enfoques (como @ lcd047 o @ apaul's ) que verifican solo el permiso de
file.txtno funcionarán porque podrían decir quefile.txtse puede escribir incluso si el usuario no tiene permiso de búsqueda para/o/foo.Y un enfoque como:
Tampoco funcionará porque no informará los archivos en directorios en los que el usuario no tiene acceso de lectura (ya
findque$userno puede enumerar su contenido) incluso si puede escribir en ellos.Si nos olvidamos de las ACL, los sistemas de archivos de solo lectura, los indicadores FS (como inmutables), otras medidas de seguridad (apparmor, SELinux, que incluso pueden distinguir entre diferentes tipos de escritura) y solo se centran en los permisos tradicionales y los atributos de propiedad, para obtener un dado (buscar o escribir) permiso, eso ya es bastante complicado y difícil de expresar
find.Necesitas:
En
findsintaxis, aquí como ejemplo con un usuario de uid 1 y gids 1 y 2, eso sería:Que uno ciruelas los directorios que usuario no tiene derecho a buscar y para otros tipos de archivos (enlaces simbólicos excluidos ya que no son relevantes), controles para el acceso de escritura.
Si también desea considerar el acceso de escritura a directorios:
O para una
$usermembresía arbitraria y de grupo recuperada de la base de datos de usuarios:(que es 3 procesos en total:
id,sedyfind)Lo mejor aquí sería descender el árbol como raíz y verificar los permisos como usuario para cada archivo.
(ese es un
findproceso más unosudoyshprocesa cada pocos miles de archivos,[yprintfgeneralmente se construyen en el shell).O con
perl:(3 procesos en total:
find,sudoyperl).O con
zsh:(0 procesos en total, pero almacena la lista completa de archivos en la memoria)
Esas soluciones se basan en la
access(2)llamada al sistema. Es decir, en lugar de reproducir el algoritmo que usa el sistema para verificar el permiso de acceso, le pedimos al sistema que haga esa verificación con el mismo algoritmo (que tiene en cuenta los permisos, las ACL, los indicadores inmutables, los sistemas de archivos de solo lectura ... ) lo usaría si intentas abrir el archivo para escribir, por lo que es lo más cercano a una solución confiable.Para probar las soluciones dadas aquí, con las diversas combinaciones de usuario, grupo y permisos, puede hacer:
Variar el usuario entre 1 y 2 y el grupo entre 1, 2 y 3 y limitarnos a los 9 bits inferiores de los permisos, ya que son 9458694 archivos creados. Eso para directorios y luego nuevamente para archivos.
Eso crea todas las combinaciones posibles de
u<x>g<y>/<mode1>/u<z>g<w>/<mode2>. El usuario con uid 1 y gid 1 y 2 tendría acceso de escritura,u2g1/010/u2g3/777pero nou1g2/677/u1g1/777por ejemplo.Ahora, todas esas soluciones intentan identificar las rutas de los archivos que el usuario puede abrir para escribir, eso es diferente de las rutas en las que el usuario puede modificar el contenido. Para responder a esa pregunta más genérica, hay varias cosas a tener en cuenta:
/a/b/filepero si es el propietariofile(y tiene acceso de búsqueda/a/b, y el sistema de archivos no es de solo lectura, y el archivo no tiene el indicador inmutable, y tiene acceso de shell al sistema), entonces él podría cambiar los permisos delfiley otorgarse acceso./a/bpero no tiene acceso de búsqueda./a/b/fileporque no tiene acceso a la búsqueda/ao/a/b, pero ese archivo puede tener un enlace duro en/b/c/file, por ejemplo, en cuyo caso puede ser capaz de modificar el contenido de/a/b/fileabriéndolo a través de su/b/c/filetrayectoria./a, pero/a/bpuede estar montado en un enlace/c, por lo que podría abrirfilepara escribir a través de su/c/fileotra ruta./a/b/file, pero si tiene acceso de escritura/a/bpuede eliminar o cambiar el nombrefileallí y reemplazarlo con su propia versión. Cambiaría el contenido del archivo/a/b/fileincluso si fuera un archivo diferente./a(que podría cambiar el nombre/a/ba/a/c, crear un nuevo/a/bdirectorio y un nuevofileen ella.Para encontrar las rutas que
$userpodrían modificarse. Para abordar 1 o 2, ya no podemos confiar en laaccess(2)llamada al sistema. Podríamos ajustar nuestrofind -permenfoque para asumir el acceso de búsqueda a los directorios, o escribir el acceso a los archivos tan pronto como usted sea el propietario:Podríamos abordar 3 y 4, registrando el dispositivo y los números de inodo o todos los archivos que $ user tiene permiso para escribir e informar todas las rutas de archivos que tienen esos números dev + inode. Esta vez, podemos usar los
access(2)enfoques basados en más confiables :Algo como:
5 y 6 son a primera vista complicados por el
tpoco de los permisos. Cuando se aplica en los directorios, ese es el bit de eliminación restringido que impide que los usuarios (que no sean el propietario del directorio) eliminen o renombren los archivos que no poseen (aunque tengan acceso de escritura al directorio).Por ejemplo, si volvemos a nuestro ejemplo anterior, si tiene acceso de escritura
/a, entonces usted debería ser capaz de cambiar el nombre/a/bde/a/c, y volver a crear un/a/bdirectorio y un nuevofileallí. Pero si eltbit está activado/ay usted no posee/a, entonces solo puede hacerlo si posee/a/b. Eso da:tbit no está configurado, y usted está en el mismo caso que el anterior (todas las rutas de archivos son suyas).Entonces podemos abordar todos los 1, 2, 5 y 6 con:
Eso y la solución para 3 y 4 son independientes, puede fusionar su salida para obtener una lista completa:
Como debe quedar claro si ha leído todo hasta ahora, parte de él al menos solo trata con los permisos y la propiedad, no con las otras características que pueden otorgar o restringir el acceso de escritura (FS de solo lectura, ACL, indicador inmutable, otras características de seguridad ...) Y a medida que lo procesamos en varias etapas, parte de esa información puede ser incorrecta si los archivos / directorios se crean / eliminan / cambian de nombre o se modifican sus permisos / propiedad mientras se ejecuta ese script, como en un servidor de archivos ocupado con millones de archivos .
Notas de portabilidad
Todo ese código es estándar (POSIX, Unix para
tbit) excepto:-print0es una extensión de GNU que ahora también es compatible con algunas otras implementaciones. Confindimplementaciones que carecen de soporte para ello, puede usar-exec printf '%s\0' {} +en su lugar y reemplazar-exec sh -c 'exec find "$@" -print0' sh {} +con-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +.perlno es un comando especificado por POSIX pero está ampliamente disponible. Necesitasperl-5.6.0o más para-Mfiletest=access.zshno es un comando especificado por POSIX. Esezshcódigo anterior debería funcionar con zsh-3 (1995) y superior.sudono es un comando especificado por POSIX. El código debería funcionar con cualquier versión siempre que la configuración del sistema permita la ejecuciónperldel usuario dado.fuente
xpermiso de búsqueda ( bit) en el directorio. También puede tener permisos de búsqueda pero no leer , lo que significa que los archivos están ocultos para usted, pero si conoce su nombre, puede acceder a ellos. Un ejemplo típico es el directorio del archivo de sesión php (algo así como / var / lib / php).Puede combinar opciones con el
findcomando, para que descubra los archivos con el modo y el propietario especificados. Por ejemplo:El comando anterior enumerará todas las entradas que pertenecen al grupo "personal" o "usuarios" y tienen permiso de escritura para ese grupo.
También debe verificar las entradas que son propiedad de su usuario y los archivos que se pueden escribir en todo el mundo, por lo tanto:
Sin embargo, este comando no coincidirá con entradas con ACL extendida. Entonces puede
suencontrar todas las entradas que se pueden escribir:fuente
r-xrwxrwx yourusername:anygroupor-xr-xrwx anyone:staffes grabable.yourusernameno tienen acceso.El enfoque depende de lo que realmente esté probando.
Esto se debe a que hay muchas maneras de llegar a 2) y la respuesta de Stéphane los cubre bien (es inmutable recordarlo), y recuerde que también hay medios físicos, como desmontar el disco o hacerlo de solo lectura en un nivel de hardware (pestañas de disquete). Supongo que sus miles de archivos están en directorios diferentes y desea un informe o está comprobando una lista maestra. (Otro abuso de Puppet a la espera de suceder).
Es probable que desee el recorrido del árbol perl de Stéphane y "unir" la salida con una lista si es necesario (¿su también detectará la ejecución faltante en los directorios principales?). Si la subrogación es un problema de rendimiento, ¿está haciendo esto para un "gran número" de usuarios? ¿O es una consulta en línea? Si este es un requisito permanente permanente, puede ser hora de considerar un producto de terceros.
fuente
Tu puedes hacer...
... para obtener una lista de todos los archivos en los que el usuario no puede escribir como se escribió en stderr en el formulario ...
...o similar.
Consulte los comentarios a continuación para obtener notas sobre los problemas que podría tener este enfoque y la explicación a continuación de por qué podría funcionar. Sin embargo, de manera más sensata, probablemente solo debería tener
findarchivos normales como:En resumen,
teeimprimirá errores cuando intenteopen()un archivo con cualquiera de los dos indicadores ...... y encuentros ...
... como se especifica aquí :
Porque tiene que verificar de la misma manera
test -wque ...Ambos verifican el EACCESS .
fuente
teese bloqueará a menos que se interrumpa explícitamente una vez por ejecución. Sin[ -wembargo, fue lo más parecido a lo que se me ocurrió ... sus efectos deberían ser cercanos, ya que garantiza que el usuario pueda APAGAR el archivo. Mucho más fácil que cualquiera de las opciones seríapaxcon las-oopciones de formato y / o-tpara verificarEACCESS, pero cada vez que sugiero que lapaxgente parece ignorarlo. Y, de todos modos, lo únicopaxque he encontrado que cumple con los estándares son los AST, en cuyo caso también podrías usarlosls.