Zde jsou popsána přístupová práva read, write, execute
http://cs.wikipedia.org/wiki/P%C5%99%C3%ADstupov%C3%A1_pr%C3%A1va_v_Unixu
http://en.wikipedia.org/wiki/File_system_permissions#Traditional_Unix_permissions
Myslím, že přístupová práva pro soubory jsou jasná. Podívejme se na read a execute pro adresáře.
Přístupová práva pro adresáře:
Vytvoříme si adresář, ve kterému “ostatní” uživatelé mají jen právo read
ll /src drwxr-xr-- 2 inst inst 4096 May 12 13:51 test
V tomto adresáři uživatel se jménem “inst” vytvoří soubor “test.txt”
ll /src/test -rw-r--r-- 1 inst inst 10 May 12 13:51 test.txt
Jinému uživateli, který ani nepatří do skupiny “inst” se nepodaří ani vypsat adresář
ll /src/test ls: cannot access '/src/test/test.txt': Permission denied total 0 -????????? ? ? ? ? ? test.txt
Ani zobrazit obstah souboru
cat /src/test/test.txt cat: /src/test/test.txt: Permission denied
Je to divné: pro adresář i soubor mám právo read.
Do adresáře pomocí cd nevstupuji, tak bych execute pro adresář neměl potřebovat.
V dokumentaci knihovny jazyka C, glibc, používané v Linuxu naleznu program pro výpis adresáře.
http://www.gnu.org/software/libc/manual/pdf/libc.pdf
#include <stdio.h> #include <sys/types.h> #include <dirent.h> int main (void) { DIR *dp; struct dirent *ep;dp = opendir ("/src/test"); if (dp != NULL) { while (ep = readdir (dp)) puts (ep->d_name); closedir (dp); } else { perror ("Couldn't open the directory"); } return 0; }
Program přeložím příkazem
gcc list.cc -lc -o list.bin
A program zobrazí jméno souboru “test.txt”
Zobrazí obsah adresáře. Ale nezobrazí obsah souboru.
from __future__ import print_function import os for t in os.listdir ("/src/test") : print ("FILE", t) f = open ("/src/test/test.txt", "r") print (f.read ()) f.close ()
Ani program v jazyce C nezobrazí obsah souboru
#include <stdio.h> #include <stdlib.h> int main () { FILE * f = fopen ("/src/test/test.txt", "rb"); if (f != NULL) { fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); /* same as rewind(f); */ char * text = (char *) malloc (fsize + 1); fread (text, 1, fsize, f); fclose(f); text [fsize] = 0; printf ("%s", text); } else { perror ("Couldn't open the file"); } return 0; }
Zkusme se podívat na přistupová práva v jednoduchém OS.
http://toaruos.org/
http://github.com/klange/toaruos/releases
Zde jsou jednotlivá systémové funkce http://github.com/klange/toaruos/blob/master/kernel/sys/syscall.c
Např. sys_read kontroluje přistupová práva
if (!(FD_MODE(fd) & 01)) {
Nebo sys_write
if (!(FD_MODE(fd) & 02)) {
Makro FD_MODE kontroluje přístupová práva, která si systém poznamenel při otevření souboru
int sys_open(const char * file, int flags, int mode) { if (!(flags & O_WRONLY) || (flags & O_RDWR)) { if (node && !has_permission(node, 04)) { return -EACCES; } else { access_bits |= 01; } } if ((flags & O_RDWR) || (flags & O_WRONLY)) { if (node && !has_permission(node, 02)) { return -EACCES; } } else { access_bits |= 02; } } /* ... */ }
Funkce has_permission
http://github.com/klange/toaruos/blob/master/kernel/fs/vfs.c#L29
int has_permission (fs_node_t * node, int permission_bit) { if (!node) return 0; if (current_process->user == 0 && permission_bit != 01) { /* even root needs exec to exec */ return 1; } uint32_t permissions = node->mask; uint8_t user_perm = (permissions >> 6) & 07; uint8_t other_perm = (permissions) & 07; if (current_process->user == node->uid) { return (permission_bit & user_perm); } else { return (permission_bit & other_perm); } }
Funkci has_permission ještě nalezneme v souboru kernel/fs/vfs.c
http://github.com/klange/toaruos/blob/master/kernel/fs/vfs.c#L354
Přístupová práva kontroluje funkce inode_permission
https://elixir.bootlin.com/linux/latest/source/fs/namei.c#L425
Systémová funkce ksys_chdir pro změnu aktuálního adresáře
http://elixir.bootlin.com/linux/latest/source/fs/open.c#L453
kontroluje execute právo.
int ksys_chdir (const char __user *filename) { /* ... */ error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); /* ... */ }
Ostatní systémové funkce https://elixir.bootlin.com/linux/latest/source/include/linux/syscalls.h#L431
Vyberte si jeden úkol a pokuste se odpovědět