Cours 7 : Privilèges, Utilisateurs et Fichiers
Mots de passe
/etc/passwd
: ne contient plus de mdp cryptés, car tout le monde pouvait récupérer le fichier essayer de cracker les mdp (mots de passe) par force brute.
⟶ les mdp sont dans /etc/shadow
: il faut l’accès root
Lorsqu’on initialise son mdp, on utilise une fonction de cryptage, et l’image de notre mdp par cette fonction est stockée dans /etc/shadow
: puis, à chaque fois qu’on se logue : l’image de l’input est comparé à cette image.
/bin/false
: on n’est pas censé utiliser ce compte avec un login.
Utilisateurs virtuels : root, daemons, etc…
- Groupes :
-
Chaque utilisateur appartient à un groupe primaire, et éventuellement des groupes supplémentaires.
Les groupes :
- primaires sont dans
/etc/passwd
- supplémentaires dans
/etc/groups
Commande id
: affiche tous les ids des groupes auxquels l’utilisateur courant appartient.
Utilisateurs
getuid
: id de l’utilisateur réel, i.e celui qui a lancé le processus.
geteuid
: id de l’utilisateur effectif, i.e celui qui détermine les droits sur le processus.
En remplaçant u
par g
⟶ idem pour les groupes
NB :
-
Normalement, ce sont les mêmes.
- Mais pas toujours : quand on veut changer son mdp (sans être root), par ex, car on n’a pas accès à
/etc/shadow
- Par contre, quand on fait un
sudo
: c’est carrément l’utilisateur réel qui devient le root
- Mais pas toujours : quand on veut changer son mdp (sans être root), par ex, car on n’a pas accès à
Fichiers
Sur UNIX :
- Fichier :
-
toutes les entrées/sorties, qui ont des opérations de lecture et d’écriture. Selon le type du fichier, la relation entre read et write est différente
- ex: pour certains fichiers (buffers temporaires, connexion réseau, etc…) : écriture “destructive”
Exs de fichiers :
- un fichier réel sur le disque dur
- buffer - zone de mémoire temporaire
- stdin / stdout
- imprimantes / CDs / périphériques
- processus
Avec read/write : l’interface est la même pour toutes les lectures/écritures sur tous les fichiers : mais le noyau renvoie sur un pilote qui convient la lecture/l’écriture selon le fichier.
NB : le terme “système de fichiers” est ambigu : c’est
- la gestion des fichiers sur une partition
- ou : l’ensemble des fichiers.s
Entrées/Sorties :
Deux aspects à considérer :
-
l’aspect statique :
- stockage des données au delà de la vie d’un processus donné
-
La gestion des
1. Système de fichiers
C’est une arborescence, dont :
- les noeuds internes sont les dossiers
- les feuilles sont les fichiers
Chemin absolu/relatif : le dossier actuel est un attribut du processus ⟶ le processus fils hérite de celui-ci, par un fork
ex :
void main(){
chdir("tmp"); // va dans tmp
system("cat toto");
}
Après avoir exécuté ce fichier, le shell reste dans son répertoire de départ.
void main(){
unlink("tmp/toto"); // supprime le fichier -> interprété de manière relative au dossier actuel, indépendamment de l'endroit où se trouve le programme
}
Les fonctions du système font l’interprétation (caractère relatif des chemins) pour nous.
Métadonnées VS données
Les métadonnées d’un fichier (propriétaire, droits d’accès, etc…, mais pas son nom) sont stockées de manière particulière :
un partie des blocs du disque dur est dédiée au stockage des métadonnées, alors qu’une autre stocke les fichiers proprement dits.
Un fichier = une référence
ls -i
:-
affichage (en premier) en plus d’un numéro inoeud (inode)
Il y a 3 références pour un répertoire donné : .
dans le répertoire courant, nom
dans répertoire parent, ..
dans les répertoires enfants.
Toutes ces références ont le même inode.
stat repertoire
:-
affichage des métadonnées.
ln toto tata
:-
création d’un lien de toto vers tata : ils ont alors le même numéro inoeud (inode).
Inoeud : normalement, ne se voit pas, sauf des cas particuliers :
ex :
- Erreur : “lost inode”
Noms de fichiers
Un inode existe tant qu’il y a une référence vers lui dans une entrée quelconque.
⟶ existence de la métadonnée Links
: nombre de liens pointant vers cet inoeud.
⟶ unlink
: en C, supprime les liens vers l’inoeud.
- Si on fait
rm tata
: le lien toto existe toujours. - Puis : quand on supprime toto : le dernier lien vers l’inoeud est supprimé ⟶ on ne peut plus accéder au fichier
- Un répertoire :
-
un fichier qui contient une liste de paires (nom, inoeud)
Quand on fait ls
: la liste est obtenue, puis un stat
est fait sur chaque fichier pour obtenir les métadonnées.
UGO
User - Group - Others : droits rwx
Il y a au total 12 bits pour les droits d’accès : les 9 bits ordinaires rwx
(pour l’utilsateur, son groupe primaire ET ses groupes supplémentaires, et les autres)
Pour les fichiers :
chmod a+r fichier
:-
donner tous les droits de lecture de
fichier
(o
: others,u
: user,a
: all) chmod u-r fichier
:-
m’enlever les droits de lecture de
fichier
NB : un fichier peut être lisible pour les autres sans l’être pour moi.
Pour les dossiers :
-
le bit
r
: droit de lire la liste des fichiers du dossier- ex :
ls
requiert ce droit
- ex :
- le bit
r
: droit de modifier la liste des fichiers du dossier ⟶ modifier/supprimer les fichiers qui y sont -
le bit
x
: droit de faire unstat
, et l’appel systèmechdir
dans ce dossier- NB : ce droit est nécessaire pour le traverser.
Ex :
Si on fait
chmod -x repertoire
⟶ on peut faire un ls
, mais pas un ls -l
⟶ on ne peut faire un cd
: chdir
: droit refusé
-
le bit
s
: droitx
+ de faire unsetuid
- les fichiers créés dans le répertoire appartiennent au groupe du répertoire.
-
le bit
S
: de faire unsetuid
seulement
(s’affiche en rouge avec ls
)
Quand un processus crée un fichier, normalement : le groupe du processus = le groupe du fichier créé
-
Sticky bit : sémantique pas très bien définie, mais typiquement : permet de créer des fichiers personnels dans le répertoire, sans toucher à ceux des autres
- ex : le répertoire
/tmp/
a le sticky bit
- ex : le répertoire
Descripteurs
Un entier qui représente un accès à un fichier.
Un même fichier peut avoir différents descripteurs.
open("fichier")
:-
si la lecture réussit, renvoie le descripteur du fichier.
read(descripteur, adresse, nb_octets_souhaites
:-
lire
nb_octets_souhaites
et les renvoyer à l’adresseadresse
(renvoie 0 si on arrive à la fin du fichier).
Plusieurs processus peuvent écrire en même temps dans un même fichier
main(){
char c;
int f = open("foo", O_RDONLY);
while(read(f,&c,1)){
putchar(c);
fflush(sdtout);
sleep(2);
}
}
Dans le noyau :
inoeud, node d’accès, position dans le fichier
void do_read(char *name, int fd)
{
char c;
while(read(f,&c,1)){
printf("%s : %c\n", name, c);
sleep(2);
}
}
main(){
int fd = open("foo", O_RDONLY);
int pid = fork();
if (pid) do_read("parent", fd);
else {sleep(1); do_read("child", fd))}
}
Lecture tour à tour du parent et du fils dans le même fichier : alternance père/fils de l’affichage de la lecture des caractères du fichier.
- le père lit le premier caractère
- le fils le second
- le père le troisième
- le fils le quatrième
NB : si on fait open
après fork
: il y a répétition des caractères du fichier lu :
- le père lit le premier caractère
- le fils le premier
- le père le second
- le fils le second
0xxx
: en octal
umask
:-
affichage des droits enlevés aux fichiers créés par les processus avec
open
(par défaut):- ex : si
umask
affiche0002
: on retire les droits d’exécution aux autres.
- ex : si
Descripteurs standard :
- 0 : entrée standard
- 1 : sortie standard
- 2 : sortie erreur
dup(nombre)
:-
crée un nouveau descripteur dupliqué (pointant vers le même fichier) du descripteur numéro
nombre
ex :
g = dup(3)
: duplique le descripteur 3
dup2(nombre1, nombre2)
:-
fait pointer le descripteur
nombre2
vers le même fichier que celui vers lequel pointenombre1
NB : c’est ce qui est utilisé par le shell quand on fait echo xxx > sortie
par exemple.
Mini-Shell : PIPE
- Père :
pipefd[0]
pipefd[1]
⇓ 1
- Fils 1 :
pipefd[0]
pipefd[1]
⇓
- Fils 2:
pipefd[0]
pipefd[1]
⇓ 0
- ANSI-C :
-
standard C valable sur n’import quel système.
man
:-
- Section 2 : fonctions faisant des appels système.
- Section 3 : fonction ayant recours à des fonctions de de la section 2 (
printf
, etc…)
```{c id:”iw24ujr0”} char *t[100]; // sur la pile char *s = malloc(100); // sur le tas
scanf(“%100s”, t); // 100 octets max scanf(“%ms”, &t); // on donne un pointeur ⟶ alloue la place nécessaire
```
cf.
asprintf
: pour allocation variablesnprintf
: taille limite en octet spécifiée
fopen
:-
fait
open
, et crée un FILE avec ce descripteur, et en fait une string. strace
/ltrace
:-
affichage des appels systèmes
NB : printf
, etc… : économisent les appels noyaux avec un système de tamponnage (printf
sort q’une fois qu’on a fait un retour à la ligne)
Pour vider le tampon : fflush(stdout)
voir aussi :
setlinebuf(f)
setbuf(f, NULL)
- ex:
setbuf(stdout, NULL)
: mode non temponné
- ex:
Threads
Structure pthread_t
pthread_create(&t1, NULL, titi, NULL)
Quand on compile avec gcc
: le faire avec l’option -pthread
Pas de hiérarchie chez les threads : un thread lancé après un autre a la même “priorité” que celui-ci.
pthread_join
:-
équivalent de
wait
, mais pour les threads pthread_detach
:-
si le thread termine, il ne devient pas zombie (il est directement effacé de la mémoire) : mais attention, on ne peut plus faire de
pthread_join
.
fork
VS threads
:
fork
pour avoir des processus totalement indépendants (si le fils d’un thread est tué, tout le monde l’est)-
threads : mémoire partagée entre tous les threads.
- ex: Firefox utilise beacoup de threads : si il y a un plugin qui bogue ⟶ ça tue tout le navigateur entier.
exit
dans un thread : tue tous les autres.
-
NB:
exit
dans lemain
tue tous le processus, peu importe qu’il reste des threads ou non. - Attention : certains appels suystèmes ne peuvent êtres appelés deux fois en parallèle dans un même processus.
Sémaphores :
init(s, 1)
wait(s)
:-
attend tant que
s=0
post(s)
:-
passe le flambeau (libère le créneau).
Leave a comment