Fichier binaire d'un daemon writable ssi le damon est stoppé
Aucune réponse
Francois Lafont
Bonjour Í tous,
Attention, je préfère prévenir, je connais très mal le système BSD alors
désolé par avance si je passe Í cÍ´té de choses basiques.
Voici le résumé de ma demande : j'ai un serveur FreeBSD 12.2-RC3 (plus
précisément c'est un serveur TrueNAS) sur lequel j'ai installé manuellement
un daemon correspondant Í un fichier binaire qu'on appellera "b". Je suis
root sur la machine et, si j'en crois la sortie de « ls -l "b" », en tant que
root le fichier m'est parfaitement accessible en écriture. Pourtant, si je fais
un simple
if [ -w "$b" ]; then echo WRITABLE; else echo NOT-WRITABLE; fi
cela m'affichera :
1. NOT-WRITABLE si le daemon est en cours d'exécution.
2. WRITABLE si le daemon est stoppé.
Pourtant, dans les deux cas (que le daemon soit stoppé ou non), les permissions
Unix du fichier "b" restent totalement inchangées. De plus, dans les deux cas,
je suis parfaitement en mesure de faire un touch sur le fichier. Quel mécanisme
système de l'OS entraÍ®ne cette différence entre les deux cas (daemon stoppé ou
démarré) ?
---
Maintenant, voici les détails. Le fichier s'appelle
~# b=/usr/local/capsdrv/filer/bin/capsdrv
Voici les permissions :
~# ls -ld /usr /usr/local /usr/local/capsdrv /usr/local/capsdrv/filer /usr/local/capsdrv/filer/bin "$b"
drwxr-xr-x 13 root wheel 13 Dec 2 11:27 /usr
drwxr-xr-x 17 root wheel 18 Dec 2 14:05 /usr/local
drwxr-x--- 3 root wheel 3 Dec 2 14:05 /usr/local/capsdrv
drwxr-xr-x 5 root wheel 6 Jan 11 15:14 /usr/local/capsdrv/filer
drwxr-xr-x 2 root wheel 6 Jan 11 16:46 /usr/local/capsdrv/filer/bin
-rwxrw---- 1 root wheel 11057232 Jan 11 20:11 /usr/local/capsdrv/filer/bin/capsdrv
Voici le fichier qui m'a permis de faire de ce binaire un daemon :
DéjÍ , Í ce stade, je suis surpris car les tests me disent que le fichier
n'est pas writable alors que je suis root et que les permissions Unix semblent
me donner un accès en écriture Í ce fichier. Mais ce qui suit me surprend
encore plus, si je stoppe le daemon, alors les choses changent ;
~# service capsdrv_filer stop
Stopping capsdrv_filer.
Waiting for PIDS: 16351.
~# ls -ld /usr /usr/local /usr/local/capsdrv /usr/local/capsdrv/filer /usr/local/capsdrv/filer/bin "$b"
drwxr-xr-x 13 root wheel 13 Dec 2 11:27 /usr
drwxr-xr-x 17 root wheel 18 Dec 2 14:05 /usr/local
drwxr-x--- 3 root wheel 3 Dec 2 14:05 /usr/local/capsdrv
drwxr-xr-x 5 root wheel 6 Jan 11 15:14 /usr/local/capsdrv/filer
drwxr-xr-x 2 root wheel 6 Jan 11 16:46 /usr/local/capsdrv/filer/bin
-rwxrw---- 1 root wheel 11057232 Jan 11 20:11 /usr/local/capsdrv/filer/bin/capsdrv
Absolument rien n'a changé au niveau des permissions Unix et pourtant :
~# if [ -w "$b" ]; then echo WRITABLE; else echo NOT-WRITABLE; fi
WRITABLE
~# echo "import os; x = os.access('$b', os.W_OK); print(x)" | python
True
Force est de constater qu'il y a un mécanisme système qui protège le
fichier en écriture lorsque le daemon est en cours d'exécution mais ce
mécanisme ne correspond pas aux permissions Unix classiques que je connais.
Mais quel est ce mécanisme ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Christian Weisgerber
On 2021-01-11, Francois Lafont wrote:
if [ -w "$b" ]; then echo WRITABLE; else echo NOT-WRITABLE; fi 1. NOT-WRITABLE si le daemon est en cours d'exécution. 2. WRITABLE si le daemon est stoppé.
La commande test(1), alias « [ », invoque l'appel système access(2), qui retourne l'erreur ETXTBSY si le fichier exécutable est en état d'utilisation. C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux nécessaires d'un fichier exécutable sont transferés en mémoire vive lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait mal si on surécrivait le fichier et après chargeait un autre morceau. C'est comme ça depuis l'introduction de la mémoire virtuelle paginée au monde Unix, il y a environ une quarantaine d'années. -- Christian "naddy" Weisgerber
On 2021-01-11, Francois Lafont <francois.lafont@nospam.invalid> wrote:
if [ -w "$b" ]; then echo WRITABLE; else echo NOT-WRITABLE; fi
1. NOT-WRITABLE si le daemon est en cours d'exécution.
2. WRITABLE si le daemon est stoppé.
La commande test(1), alias « [ », invoque l'appel système access(2),
qui retourne l'erreur ETXTBSY si le fichier exécutable est en état
d'utilisation.
C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux
nécessaires d'un fichier exécutable sont transferés en mémoire vive
lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait
mal si on surécrivait le fichier et après chargeait un autre morceau.
C'est comme ça depuis l'introduction de la mémoire virtuelle paginée
au monde Unix, il y a environ une quarantaine d'années.
--
Christian "naddy" Weisgerber naddy@mips.inka.de
if [ -w "$b" ]; then echo WRITABLE; else echo NOT-WRITABLE; fi 1. NOT-WRITABLE si le daemon est en cours d'exécution. 2. WRITABLE si le daemon est stoppé.
La commande test(1), alias « [ », invoque l'appel système access(2), qui retourne l'erreur ETXTBSY si le fichier exécutable est en état d'utilisation. C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux nécessaires d'un fichier exécutable sont transferés en mémoire vive lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait mal si on surécrivait le fichier et après chargeait un autre morceau. C'est comme ça depuis l'introduction de la mémoire virtuelle paginée au monde Unix, il y a environ une quarantaine d'années. -- Christian "naddy" Weisgerber
Francois Lafont
Bonsoir, On 1/11/21 10:55 PM, Christian Weisgerber wrote:
La commande test(1), alias « [ », invoque l'appel système access(2), qui retourne l'erreur ETXTBSY si le fichier exécutable est en état d'utilisation. C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux nécessaires d'un fichier exécutable sont transferés en mémoire vive lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait mal si on surécrivait le fichier et après chargeait un autre morceau. C'est comme ça depuis l'introduction de la mémoire virtuelle paginée au monde Unix, il y a environ une quarantaine d'années.
Merci beaucoup pour ta réponse Christian. Et ben... j'ai appris quelque chose. Ok, manifestement ce n'est pas récent mais pour moi qui vient du monde Linux, c'est la première fois que je rencontre ça. Par exemple sur une Ubuntu 18.04, un noyau Linux 4.15 donc, je n'ai pas le même comportement. Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD : ------------------------------------------------------------- ~# whoami root ~# b=/usr/sbin/apache2 ~# namei -mox "$b" f: /usr/sbin/apache2 Drwxr-xr-x root root / drwxr-xr-x root root usr drwxr-xr-x root root sbin -rwxr-xr-x root root apache2 ~# echo "import os; x = os.access('$b', os.W_OK); print(x)" | python True ~# [ -w "$b" ] && echo WRITABLE WRITABLE ------------------------------------------------------------- Du coup, le comportement que j'ai décrit dans mon premier message n'est-il pas spécifique Í (Free)BSD ? Ou alors, inversement, le comportement ci-dessus n'est-il pas spécifique Í Linux ? Pourquoi les deux OS se comportent-ils différemment sur ce point ? -- François Lafont
Bonsoir,
On 1/11/21 10:55 PM, Christian Weisgerber wrote:
La commande test(1), alias « [ », invoque l'appel système access(2),
qui retourne l'erreur ETXTBSY si le fichier exécutable est en état
d'utilisation.
C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux
nécessaires d'un fichier exécutable sont transferés en mémoire vive
lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait
mal si on surécrivait le fichier et après chargeait un autre morceau.
C'est comme ça depuis l'introduction de la mémoire virtuelle paginée
au monde Unix, il y a environ une quarantaine d'années.
Merci beaucoup pour ta réponse Christian. Et ben... j'ai appris quelque
chose.
Ok, manifestement ce n'est pas récent mais pour moi qui vient du monde
Linux, c'est la première fois que je rencontre ça. Par exemple sur une
Ubuntu 18.04, un noyau Linux 4.15 donc, je n'ai pas le même comportement.
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire
/usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même
comportement qu'avec FreeBSD :
Du coup, le comportement que j'ai décrit dans mon premier message n'est-il
pas spécifique Í (Free)BSD ? Ou alors, inversement, le comportement ci-dessus
n'est-il pas spécifique Í Linux ? Pourquoi les deux OS se comportent-ils
différemment sur ce point ?
Bonsoir, On 1/11/21 10:55 PM, Christian Weisgerber wrote:
La commande test(1), alias « [ », invoque l'appel système access(2), qui retourne l'erreur ETXTBSY si le fichier exécutable est en état d'utilisation. C'est Í cause de la mémoire virtuelle paginée. Seulement les morceaux nécessaires d'un fichier exécutable sont transferés en mémoire vive lorsque c'est exigé (« on-demand paging »). Évidemment, ça finirait mal si on surécrivait le fichier et après chargeait un autre morceau. C'est comme ça depuis l'introduction de la mémoire virtuelle paginée au monde Unix, il y a environ une quarantaine d'années.
Merci beaucoup pour ta réponse Christian. Et ben... j'ai appris quelque chose. Ok, manifestement ce n'est pas récent mais pour moi qui vient du monde Linux, c'est la première fois que je rencontre ça. Par exemple sur une Ubuntu 18.04, un noyau Linux 4.15 donc, je n'ai pas le même comportement. Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD : ------------------------------------------------------------- ~# whoami root ~# b=/usr/sbin/apache2 ~# namei -mox "$b" f: /usr/sbin/apache2 Drwxr-xr-x root root / drwxr-xr-x root root usr drwxr-xr-x root root sbin -rwxr-xr-x root root apache2 ~# echo "import os; x = os.access('$b', os.W_OK); print(x)" | python True ~# [ -w "$b" ] && echo WRITABLE WRITABLE ------------------------------------------------------------- Du coup, le comportement que j'ai décrit dans mon premier message n'est-il pas spécifique Í (Free)BSD ? Ou alors, inversement, le comportement ci-dessus n'est-il pas spécifique Í Linux ? Pourquoi les deux OS se comportent-ils différemment sur ce point ? -- François Lafont
Je précise que, lorsque je lis la page man access(2) de ma Ubuntu, j'ai bien ETXTBSY considéré comme une erreur. Du coup, sur Linux, le comportement ne me paraÍ®t effectivement pas en cohérence avec ce que je lis dans la page man. -- François Lafont
Je précise que, lorsque je lis la page man access(2) de ma Ubuntu, j'ai
bien ETXTBSY considéré comme une erreur. Du coup, sur Linux, le comportement
ne me paraÍ®t effectivement pas en cohérence avec ce que je lis dans la
page man.
Je précise que, lorsque je lis la page man access(2) de ma Ubuntu, j'ai bien ETXTBSY considéré comme une erreur. Du coup, sur Linux, le comportement ne me paraÍ®t effectivement pas en cohérence avec ce que je lis dans la page man. -- François Lafont
Christian Weisgerber
On 2021-01-12, Francois Lafont wrote:
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD : ~# b=/usr/sbin/apache2 ~# [ -w "$b" ] && echo WRITABLE WRITABLE
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY. La différence, c'est le comportement d'access(2). POSIX permet les deux comportements. -- Christian "naddy" Weisgerber
On 2021-01-12, Francois Lafont <francois.lafont@nospam.invalid> wrote:
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire
/usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même
comportement qu'avec FreeBSD :
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD : ~# b=/usr/sbin/apache2 ~# [ -w "$b" ] && echo WRITABLE WRITABLE
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY. La différence, c'est le comportement d'access(2). POSIX permet les deux comportements. -- Christian "naddy" Weisgerber
Francois Lafont
Bonsoir, On 1/12/21 3:54 PM, Christian Weisgerber wrote:
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD :
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY.
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : ------------------------------------------------------------------------ ~# whoami root # Mon service Apache2 en cours d'exécution. ~# service apache2 status * apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Drop-In: /lib/systemd/system/apache2.service.d `-apache2-systemd.conf Active: active (running) since Tue 2021-01-12 19:22:04 CET; 11s ago Main PID: 948 (apache2) Tasks: 55 (limit: 2375) CGroup: /system.slice/apache2.service |-948 /usr/sbin/apache2 -k start |-951 /usr/sbin/apache2 -k start `-952 /usr/sbin/apache2 -k start Jan 12 19:22:04 bionic-vbox systemd[1]: Starting The Apache HTTP Server... Jan 12 19:22:04 bionic-vbox systemd[1]: Started The Apache HTTP Server. ~# ls -l /usr/sbin/apache2 -rwxr-xr-x 1 root root 671392 Aug 12 23:33 /usr/sbin/apache2 ~# sha1sum /usr/sbin/apache2 013eebcb901aa2c3e1ea7057e08811563fc866c7 /usr/sbin/apache2 # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2 # Et j'ai bien modifié le fichier sans erreur. # Autant dire qu'en modifiant le fichier avec vim, je l'ai complètement # corrompu mais j'ai quand même pu le modifier, l'opération n'a pas échoué. ~# sha1sum /usr/sbin/apache2 6adbc993c5de98abe63c930629f200646c9ae978 /usr/sbin/apache2 ------------------------------------------------------------------------ Au passage, après la modification, le service Apache2 fonctionne toujours sur la VM. Par contre, si je fais un restart du service, évidemment ça plante car le binaire est corrompu. Du coup, je suis toujours perplexe quant Í cette différence de comportement entre FreeBSD et Linux. -- François Lafont
Bonsoir,
On 1/12/21 3:54 PM, Christian Weisgerber wrote:
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire
/usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même
comportement qu'avec FreeBSD :
# C'est bête évidemment mais c'est juste pour modifier (n'importe comment)
# le fichier.
~# vim /usr/sbin/apache2
# Et j'ai bien modifié le fichier sans erreur.
# Autant dire qu'en modifiant le fichier avec vim, je l'ai complètement
# corrompu mais j'ai quand même pu le modifier, l'opération n'a pas échoué.
~# sha1sum /usr/sbin/apache2
6adbc993c5de98abe63c930629f200646c9ae978 /usr/sbin/apache2
------------------------------------------------------------------------
Au passage, après la modification, le service Apache2 fonctionne toujours
sur la VM. Par contre, si je fais un restart du service, évidemment ça plante
car le binaire est corrompu.
Du coup, je suis toujours perplexe quant Í cette différence de comportement
entre FreeBSD et Linux.
Bonsoir, On 1/12/21 3:54 PM, Christian Weisgerber wrote:
Sur cette Ubuntu, j'ai un daemon Apache2 qui tourne via le binaire /usr/sbin/apache2. Comme tu peux voir ci-dessous, je n'ai pas le même comportement qu'avec FreeBSD :
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY.
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : ------------------------------------------------------------------------ ~# whoami root # Mon service Apache2 en cours d'exécution. ~# service apache2 status * apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Drop-In: /lib/systemd/system/apache2.service.d `-apache2-systemd.conf Active: active (running) since Tue 2021-01-12 19:22:04 CET; 11s ago Main PID: 948 (apache2) Tasks: 55 (limit: 2375) CGroup: /system.slice/apache2.service |-948 /usr/sbin/apache2 -k start |-951 /usr/sbin/apache2 -k start `-952 /usr/sbin/apache2 -k start Jan 12 19:22:04 bionic-vbox systemd[1]: Starting The Apache HTTP Server... Jan 12 19:22:04 bionic-vbox systemd[1]: Started The Apache HTTP Server. ~# ls -l /usr/sbin/apache2 -rwxr-xr-x 1 root root 671392 Aug 12 23:33 /usr/sbin/apache2 ~# sha1sum /usr/sbin/apache2 013eebcb901aa2c3e1ea7057e08811563fc866c7 /usr/sbin/apache2 # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2 # Et j'ai bien modifié le fichier sans erreur. # Autant dire qu'en modifiant le fichier avec vim, je l'ai complètement # corrompu mais j'ai quand même pu le modifier, l'opération n'a pas échoué. ~# sha1sum /usr/sbin/apache2 6adbc993c5de98abe63c930629f200646c9ae978 /usr/sbin/apache2 ------------------------------------------------------------------------ Au passage, après la modification, le service Apache2 fonctionne toujours sur la VM. Par contre, si je fais un restart du service, évidemment ça plante car le binaire est corrompu. Du coup, je suis toujours perplexe quant Í cette différence de comportement entre FreeBSD et Linux. -- François Lafont
Christian Weisgerber
On 2021-01-12, Francois Lafont wrote:
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY.
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2
Essaie quelque chose de simple. # echo fdfdjjdf > /usr/sbin/apache2 Je ne sais pas ce que vim fait. Peut-être il invoque rename(2) ou unlink(2) et crée un nouveau fichier après.
Si tu essaies de surécrire le binaire, ça va quand même échouer avec une erreur ETXTBSY.
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2
Essaie quelque chose de simple. # echo fdfdjjdf > /usr/sbin/apache2 Je ne sais pas ce que vim fait. Peut-être il invoque rename(2) ou unlink(2) et crée un nouveau fichier après.
Re, On 1/12/21 9:32 PM, Christian Weisgerber wrote:
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2
Essaie quelque chose de simple. # echo fdfdjjdf > /usr/sbin/apache2 Je ne sais pas ce que vim fait. Peut-être il invoque rename(2) ou unlink(2) et crée un nouveau fichier après.
Bien vu, merci beaucoup. En effet, j'aurais dÍ» le tester. Je ne vais pas copier/coller les commandes Í nouveau mais avec un « ls -li » sur le binaire pour afficher le numéro d'inode avant et après le vim, on peut constater qu'il change. Donc tu as raison, vim doit faire un rename ou un unlink. Et si je regarde les fichiers ouverts par les processus apache2 avec la commande lsof après modification avec vim, on voit bien le fichier /usr/sbin/apache2 ouvert mais en deleted. Le fichier n'est donc plus référencé dans l'aborescence du filesystem mais existe toujours et n'a pas été modifié. Et enfin, avec un echo comme tu le suggères, j'ai bien comme toi : ~# echo AAAAAAAAA > /usr/sbin/apache2 -bash: /usr/sbin/apache2: Text file busy Et le echo fonctionne si le service apache2 est stoppé donc. Bon, ben c'est cool, j'ai appris un truc « système » même si c'est un truc vieux de 40 ans :). Du coup, comme tu le disais, dans la question qui me préoccupe dans ce fil, la seule différence est bien au niveau de access() : 1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle part et mentionne même clairement le contraire). 2. sur une FreeBSD, access() renvoie bien une erreur sur un ETXTBSY. Par facile de trouver une doc de référence lÍ -dessus. La seule chose que j'ai trouvée (mais j'ai peut-être mal cherché) c'est cette page https://pubs.opengroup.org/onlinepubs/9699919799/ o͹ il y a juste Í la fin la mention elliptique suivante : ----------------------------------------------------- Issue 6 The following new requirements on POSIX implementations derive from alignment with the Single UNIX Specification: * The [ELOOP] mandatory error condition is added. * A second [ENAMETOOLONG] is added as an optional error condition. * The [ETXTBSY] optional error condition is added. <= LÍ ! ----------------------------------------------------- J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu. -- François Lafont
Re,
On 1/12/21 9:32 PM, Christian Weisgerber wrote:
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) :
# C'est bête évidemment mais c'est juste pour modifier (n'importe comment)
# le fichier.
~# vim /usr/sbin/apache2
Essaie quelque chose de simple.
# echo fdfdjjdf > /usr/sbin/apache2
Je ne sais pas ce que vim fait. Peut-être il invoque rename(2) ou
unlink(2) et crée un nouveau fichier après.
Bien vu, merci beaucoup. En effet, j'aurais dÍ» le tester. Je ne vais pas
copier/coller les commandes Í nouveau mais avec un « ls -li » sur le binaire
pour afficher le numéro d'inode avant et après le vim, on peut constater qu'il
change. Donc tu as raison, vim doit faire un rename ou un unlink. Et si je
regarde les fichiers ouverts par les processus apache2 avec la commande lsof
après modification avec vim, on voit bien le fichier /usr/sbin/apache2 ouvert
mais en deleted. Le fichier n'est donc plus référencé dans l'aborescence du
filesystem mais existe toujours et n'a pas été modifié.
Et enfin, avec un echo comme tu le suggères, j'ai bien comme toi :
~# echo AAAAAAAAA > /usr/sbin/apache2
-bash: /usr/sbin/apache2: Text file busy
Et le echo fonctionne si le service apache2 est stoppé donc.
Bon, ben c'est cool, j'ai appris un truc « système » même si c'est un truc vieux
de 40 ans :). Du coup, comme tu le disais, dans la question qui me préoccupe dans
ce fil, la seule différence est bien au niveau de access() :
1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur
sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle
part et mentionne même clairement le contraire).
2. sur une FreeBSD, access() renvoie bien une erreur sur un ETXTBSY.
Par facile de trouver une doc de référence lÍ -dessus. La seule chose que j'ai
trouvée (mais j'ai peut-être mal cherché) c'est cette page
https://pubs.opengroup.org/onlinepubs/9699919799/ o͹ il y a juste Í la fin la
mention elliptique suivante :
The following new requirements on POSIX implementations derive from alignment
with the Single UNIX Specification:
* The [ELOOP] mandatory error condition is added.
* A second [ENAMETOOLONG] is added as an optional error condition.
* The [ETXTBSY] optional error condition is added. <= LÍ !
-----------------------------------------------------
J'ai encore une dernière petite interrogation si possible : la vérité ultime
c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution
(sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils
voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que
c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
Re, On 1/12/21 9:32 PM, Christian Weisgerber wrote:
Ce n'est pas ce que je constate sur ma Ubuntu 18.04 (une petite VM de test) : # C'est bête évidemment mais c'est juste pour modifier (n'importe comment) # le fichier. ~# vim /usr/sbin/apache2
Essaie quelque chose de simple. # echo fdfdjjdf > /usr/sbin/apache2 Je ne sais pas ce que vim fait. Peut-être il invoque rename(2) ou unlink(2) et crée un nouveau fichier après.
Bien vu, merci beaucoup. En effet, j'aurais dÍ» le tester. Je ne vais pas copier/coller les commandes Í nouveau mais avec un « ls -li » sur le binaire pour afficher le numéro d'inode avant et après le vim, on peut constater qu'il change. Donc tu as raison, vim doit faire un rename ou un unlink. Et si je regarde les fichiers ouverts par les processus apache2 avec la commande lsof après modification avec vim, on voit bien le fichier /usr/sbin/apache2 ouvert mais en deleted. Le fichier n'est donc plus référencé dans l'aborescence du filesystem mais existe toujours et n'a pas été modifié. Et enfin, avec un echo comme tu le suggères, j'ai bien comme toi : ~# echo AAAAAAAAA > /usr/sbin/apache2 -bash: /usr/sbin/apache2: Text file busy Et le echo fonctionne si le service apache2 est stoppé donc. Bon, ben c'est cool, j'ai appris un truc « système » même si c'est un truc vieux de 40 ans :). Du coup, comme tu le disais, dans la question qui me préoccupe dans ce fil, la seule différence est bien au niveau de access() : 1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle part et mentionne même clairement le contraire). 2. sur une FreeBSD, access() renvoie bien une erreur sur un ETXTBSY. Par facile de trouver une doc de référence lÍ -dessus. La seule chose que j'ai trouvée (mais j'ai peut-être mal cherché) c'est cette page https://pubs.opengroup.org/onlinepubs/9699919799/ o͹ il y a juste Í la fin la mention elliptique suivante : ----------------------------------------------------- Issue 6 The following new requirements on POSIX implementations derive from alignment with the Single UNIX Specification: * The [ELOOP] mandatory error condition is added. * A second [ENAMETOOLONG] is added as an optional error condition. * The [ETXTBSY] optional error condition is added. <= LÍ ! ----------------------------------------------------- J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu. -- François Lafont
Christian Weisgerber
On 2021-01-13, Francois Lafont wrote:
1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle part et mentionne même clairement le contraire).
La page dit: | access() and faccessat() may fail if: ... | ETXTBSY | Write access was requested to an executable which is being | executed. https://man7.org/linux/man-pages/man2/access.2.html C'est « may », donc il est permis, il se peut que ça renvoie une telle erreur. Cette formulation est floue et quasi copiée-collée de POSIX.
J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est seulement de vérifier les permissions du inode et qu'un ETXTBSY est une situation exceptionnelle au-dehors de ce qu'access() doit faire. -- Christian "naddy" Weisgerber
On 2021-01-13, Francois Lafont <francois.lafont@nospam.invalid> wrote:
1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur
sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle
part et mentionne même clairement le contraire).
La page dit:
| access() and faccessat() may fail if:
...
| ETXTBSY
| Write access was requested to an executable which is being
| executed.
https://man7.org/linux/man-pages/man2/access.2.html
C'est « may », donc il est permis, il se peut que ça renvoie une
telle erreur. Cette formulation est floue et quasi copiée-collée
de POSIX.
J'ai encore une dernière petite interrogation si possible : la vérité ultime
c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution
(sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils
voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que
c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est
seulement de vérifier les permissions du inode et qu'un ETXTBSY est
une situation exceptionnelle au-dehors de ce qu'access() doit faire.
--
Christian "naddy" Weisgerber naddy@mips.inka.de
1. sur un Linux (en tout cas sur ma Ubuntu 18.04) access() ne renvoie pas d'erreur sur un ETXTBSY (même si la page man access(2) de ma Ubuntu ne le mentionne nulle part et mentionne même clairement le contraire).
La page dit: | access() and faccessat() may fail if: ... | ETXTBSY | Write access was requested to an executable which is being | executed. https://man7.org/linux/man-pages/man2/access.2.html C'est « may », donc il est permis, il se peut que ça renvoie une telle erreur. Cette formulation est floue et quasi copiée-collée de POSIX.
J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est seulement de vérifier les permissions du inode et qu'un ETXTBSY est une situation exceptionnelle au-dehors de ce qu'access() doit faire. -- Christian "naddy" Weisgerber
Francois Lafont
Bonjour, On 1/13/21 11:59 PM, Christian Weisgerber wrote:
La page dit: | access() and faccessat() may fail if: ... | ETXTBSY | Write access was requested to an executable which is being | executed. https://man7.org/linux/man-pages/man2/access.2.html C'est « may », donc il est permis, il se peut que ça renvoie une telle erreur. Cette formulation est floue et quasi copiée-collée de POSIX.
Ah oui, en effet. Bien vu. C'est comme avec les RFC avec les nuances entre must, may etc.
J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est seulement de vérifier les permissions du inode et qu'un ETXTBSY est une situation exceptionnelle au-dehors de ce qu'access() doit faire.
Ok, ça se tient. Et bien Merci beaucoup Christian de m'avoir aidé Í approfondir le sujet, c'est sympa. Je pense que tout est clair pour moi maintenant et je considère le fil comme définitivement résolu. ;) Merci encore. À+ -- François Lafont
Bonjour,
On 1/13/21 11:59 PM, Christian Weisgerber wrote:
La page dit:
| access() and faccessat() may fail if:
...
| ETXTBSY
| Write access was requested to an executable which is being
| executed.
https://man7.org/linux/man-pages/man2/access.2.html
C'est « may », donc il est permis, il se peut que ça renvoie une
telle erreur. Cette formulation est floue et quasi copiée-collée
de POSIX.
Ah oui, en effet. Bien vu. C'est comme avec les RFC avec les nuances entre
must, may etc.
J'ai encore une dernière petite interrogation si possible : la vérité ultime
c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution
(sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils
voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que
c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est
seulement de vérifier les permissions du inode et qu'un ETXTBSY est
une situation exceptionnelle au-dehors de ce qu'access() doit faire.
Ok, ça se tient.
Et bien Merci beaucoup Christian de m'avoir aidé Í approfondir le sujet, c'est
sympa. Je pense que tout est clair pour moi maintenant et je considère le fil
comme définitivement résolu. ;)
Bonjour, On 1/13/21 11:59 PM, Christian Weisgerber wrote:
La page dit: | access() and faccessat() may fail if: ... | ETXTBSY | Write access was requested to an executable which is being | executed. https://man7.org/linux/man-pages/man2/access.2.html C'est « may », donc il est permis, il se peut que ça renvoie une telle erreur. Cette formulation est floue et quasi copiée-collée de POSIX.
Ah oui, en effet. Bien vu. C'est comme avec les RFC avec les nuances entre must, may etc.
J'ai encore une dernière petite interrogation si possible : la vérité ultime c'est donc que le binaire n'est pas modifiable quand il est en cours d'exécution (sur un Unix), mais alors pourquoi diable sur Linux les développeurs ont-ils voulu implémenter une fonction access() qui ne dit pas la vérité (elle dit que c'est modifiable alors que c'est faux) ? J'avoue que la logique m'échappe un peu.
J'imagine qu'ils pensent que la fonctionnalité d'access() est seulement de vérifier les permissions du inode et qu'un ETXTBSY est une situation exceptionnelle au-dehors de ce qu'access() doit faire.
Ok, ça se tient. Et bien Merci beaucoup Christian de m'avoir aidé Í approfondir le sujet, c'est sympa. Je pense que tout est clair pour moi maintenant et je considère le fil comme définitivement résolu. ;) Merci encore. À+ -- François Lafont