Pourquoi un fichier avec 400 autorisations est-il accessible en écriture par root mais en lecture seule par l'utilisateur?

10

Si je crée un fichier en tant qu'utilisateur non privilégié et que je change le mode d'autorisation en 400, il est correctement vu en lecture seule par cet utilisateur:

$ touch somefile
$ chmod 400 somefile
$ [ -w somefile ] && echo rw || echo ro
ro

Tout est bien.

Mais la racine arrive:

# [ -w somefile ] && echo rw || echo ro
rw

Que diable? Bien sûr, root peut écrire dans des fichiers en lecture seule, mais il ne devrait pas en prendre l'habitude: les meilleures pratiques auraient tendance à dicter que je devrais pouvoir tester le bit de permission d'écriture, et si ce n'est pas le cas, il a été défini de cette façon pour une raison.

Je suppose que je veux comprendre à la fois pourquoi cela se produit et comment puis-je obtenir un faux code retour lors du test d'un fichier qui n'a pas le bit d'écriture défini?

Riches
la source
btw J'utilise à la fois RHEL6 ( 4.1.2(1)-release) et RHEL7 ( 4.2.46(2)-release).
Rich
16
"Les meilleures pratiques auraient tendance à dicter que je devrais être en mesure de tester le bit de permission d'écriture, et si ce n'est pas le cas, il a été défini de cette façon pour une raison." - En fait, la meilleure pratique est de «ne pas exécuter les choses en tant que root». Si vous exécutez en tant que root, vous avez déjà décidé de contourner les vérifications d'autorisation. Réimplémenter manuellement ces contrôles d'autorisation dans l'espace utilisateur est une recette pour un désastre .
Kevin
@Kevin Bon pour vous si vous pouvez exécuter des trucs sans privilège. C'est pour la manipulation /etc/dhcp/dhcpd.conf, qui appartient à root. J'utilise le fournisseur fourni dhcpd. Catastrophe totale, hein? Le fichier est archivé dans RCS, j'automatise l'utilisation de rcsdiff, ciet coparce que nous avons des opérateurs qui doivent ... fonctionner. La vérification des bits d'autorisation ( -w, comme détaillé par test(1)) allait être une première ligne d'échec, fonctionnant sur la base d' ci -uun fichier en lecture seule. J'abandonne cela, je vais directement rcsdiff -qet je vérifie $?. Pas désastreux dhcpd? Il appartiendrait à dhcpd.
Rich
1
C'est un désastre potentiel car vous avez maintenant deux implémentations différentes de vérifications des autorisations: une dans le noyau et une dans l'espace utilisateur. Pire, ces implémentations ne sont même pas destinées à produire des résultats identiques, vous ne pouvez donc pas simplement les tester les uns par rapport aux autres. Alors maintenant, vous avez deux chemins d'accès qui doivent être verrouillés et sécurisés indépendamment l'un de l'autre.
Kevin
@Kevin Bien sûr, ils ne produisent pas de résultats identiques et n'étaient pas destinés à (malgré le peu de détails dans les pages de manuel), mais je veux explicitement vérifier le bit d'autorisation d'écriture ; et les pages de manuel pour bashet testm'ont amené à croire que c'était pour ça [ -w.
Rich

Réponses:

26

test -waka [ -wne vérifie pas le mode de fichier. Il vérifie s'il est accessible en écriture. Pour root, ça l'est.

$ help test | grep '\-w'
  -w FILE        True if the file is writable by you.

La façon dont je testerais serait de faire une comparaison au niveau du bit par rapport à la sortie de stat(1)(" %a Droits d'accès en octal").

(( 0$(stat -c %a somefile) & 0200 )) && echo rw || echo ro

Notez que le sous-shell a $(...)besoin d'un 0préfixe pour que la sortie de statsoit interprétée comme octal par (( ... )).

Patrick
la source
Merci d'être concis. Bon usage de (( ... & ... )). Une faute de frappe corrigée :-)
Rich
Make that 3 ... No ifrequired, octal permissions output is %anot %d, and (( ... ))needs a prefixed 0to interpret the output of statas octal.
Rich
@Patrick my man statdit "% d numéro d'appareil en décimal", mais ce que nous voulons, ce sont les "droits d'accès", non? Votre point sur le besoin du préfixe 0 est bien fait, mais je suppose que nous devons simplement le mettre dedans :).
sourcejedi
2
stat -c 0%a...
sourcejedi
@sourcejedi ack, vous avez raison. Pour une raison quelconque, je pensais que% d était des droits d'accès en décimal. Restauration de l'édition. merci :-)
Patrick
30

Je pense que vous avez mal compris ce qui se -wpasse. Il ne vérifie pas si le fichier a des "autorisations d'écriture", il vérifie si le fichier est accessible en écriture par l' utilisateur appelant .

Plus précisément, il appelle access(2)ou similaire.

par exemple, si un script a if [ -w /etc/shadow ]alors si vous exécutez stracesur le script, vous pouvez voir une ligne similaire à

faccessat(AT_FDCWD, "/etc/shadow", W_OK)

Puisque rootpeut écrire dans le fichier, il renvoie 0.

par exemple en tant qu'utilisateur normal:

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = -1 EACCES (Permission denied)

En tant que root

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = 0

Ceci, malgré le fait qu'il /etc/shadowait l'autorisation 000sur ma machine.

---------- 1 root root 4599 Jan 29 20:08 /etc/shadow

Maintenant, ce que vous voulez faire devient intéressant et n'est pas si simple.

Si vous souhaitez vérifier les autorisations simples, vérifiez la lssortie, ou appelez statou similaire. Mais sachez que les ACL peuvent outrepasser ces autorisations. Le simple fait qu'un fichier ait la permission 400 ne l'empêche pas d'être accessible en écriture ...

Stephen Harris
la source
Non, « malentendu » serait en train de lire le manpages mal pour -w: test(1)est explicite: « FILE existe et l' autorisation d'écriture est accordée », et non « fichier peut être écrit par l' utilisateur en cours ». Rien sur la substitution des autorisations, ni des ACL. bash(1)est cagey: "Vrai si le fichier existe et est accessible en écriture ." ksh(1)fait un subtil indice vers les manigances: "-w fichier // Vrai, si le fichier existe et est accessible en écriture par le processus actuel ." zsh(1)diffère de test(1), zshmisc(1)est libellé comme suit ksh(1)et zshexpn(1)détaille certains regroupements basés sur des autorisations intéressants. csh(1)est hilarantement bref: "Accès en écriture".
btw: J'ai accepté la réponse de Patrick, 1. parce que vous n'avez pas répondu adéquatement à la question principale: comment puis-je obtenir un faux code retour lors du test d'un fichier qui n'a pas le bit d'écriture défini? et 2. en raison de la présomption sournoise présumant que j'ai mal compris les pages de manuel.
Rich
3
@ Rich La façon dont je lis cela, je pense que vos commentaires sont également un peu sarcastique. Je ne dis pas que tout ce que vous avez écrit était faux, juste que cela irait probablement mieux s'il était exprimé de manière plus polie.
David Z
3
"Je pense que vous avez mal compris ..." n'est pas sarcastique. Votre réponse cependant, 100% snarky.
barbecue
@Rich En outre, bien que les pages de manuel n'aient pas été très claires, Stephen a déclaré que vous aviez peut-être "mal compris ce que -w fait ", et non ce que disent les pages de manuel , là où le premier semble être le cas, d'où la question
Sebi
1

L'utilisateur root peut faire ce qu'il veut, les autorisations de fichiers "normales" ne sont pas une limitation. Il n'exécutera pas directement un fichier ordinaire sans aucune autorisation eXecute, juste pour un peu d'assurance contre la pratique de la cible de pied.

vonbrand
la source