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.[ -w
generalmente 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í.chgrp
en 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, alstat
que 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 unstat
comando en Linux mucho antes de questat
se escribiera GNU (elstat
zsh 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/foo
y/foo/file.txt
son enlaces simbólicos)?El necesita:
/
(no es necesarioread
)/foo
(no es necesarioread
)/foo/file.txt
Ya puede ver que los enfoques (como @ lcd047 o @ apaul's ) que verifican solo el permiso de
file.txt
no funcionarán porque podrían decir quefile.txt
se 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
find
que$user
no 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
find
sintaxis, 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
$user
membresía arbitraria y de grupo recuperada de la base de datos de usuarios:(que es 3 procesos en total:
id
,sed
yfind
)Lo mejor aquí sería descender el árbol como raíz y verificar los permisos como usuario para cada archivo.
(ese es un
find
proceso más unosudo
ysh
procesa cada pocos miles de archivos,[
yprintf
generalmente se construyen en el shell).O con
perl
:(3 procesos en total:
find
,sudo
yperl
).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/777
pero nou1g2/677/u1g1/777
por 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/file
pero 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 delfile
y otorgarse acceso./a/b
pero no tiene acceso de búsqueda./a/b/file
porque no tiene acceso a la búsqueda/a
o/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/file
abriéndolo a través de su/b/c/file
trayectoria./a
, pero/a/b
puede estar montado en un enlace/c
, por lo que podría abrirfile
para escribir a través de su/c/file
otra ruta./a/b/file
, pero si tiene acceso de escritura/a/b
puede eliminar o cambiar el nombrefile
allí y reemplazarlo con su propia versión. Cambiaría el contenido del archivo/a/b/file
incluso si fuera un archivo diferente./a
(que podría cambiar el nombre/a/b
a/a/c
, crear un nuevo/a/b
directorio y un nuevofile
en ella.Para encontrar las rutas que
$user
podrían modificarse. Para abordar 1 o 2, ya no podemos confiar en laaccess(2)
llamada al sistema. Podríamos ajustar nuestrofind -perm
enfoque 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
t
poco 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/b
de/a/c
, y volver a crear un/a/b
directorio y un nuevofile
allí. Pero si elt
bit está activado/a
y usted no posee/a
, entonces solo puede hacerlo si posee/a/b
. Eso da:t
bit 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
t
bit) excepto:-print0
es una extensión de GNU que ahora también es compatible con algunas otras implementaciones. Confind
implementaciones 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 {} +
.perl
no es un comando especificado por POSIX pero está ampliamente disponible. Necesitasperl-5.6.0
o más para-Mfiletest=access
.zsh
no es un comando especificado por POSIX. Esezsh
código anterior debería funcionar con zsh-3 (1995) y superior.sudo
no 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ónperl
del usuario dado.fuente
x
permiso 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
find
comando, 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
su
encontrar todas las entradas que se pueden escribir:fuente
r-xrwxrwx yourusername:anygroup
or-xr-xrwx anyone:staff
es grabable.yourusername
no 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
find
archivos normales como:En resumen,
tee
imprimirá 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 -w
que ...Ambos verifican el EACCESS .
fuente
tee
se bloqueará a menos que se interrumpa explícitamente una vez por ejecución. Sin[ -w
embargo, 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íapax
con las-o
opciones de formato y / o-t
para verificarEACCESS
, pero cada vez que sugiero que lapax
gente parece ignorarlo. Y, de todos modos, lo únicopax
que he encontrado que cumple con los estándares son los AST, en cuyo caso también podrías usarlosls
.