====== Přístupová práva k unixovým souborům ====== 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: * r - vypsat soubory v adresáři * w - přidat nebo vymazat soubor nebo adresář * x - vstoupit do podresáře pomocí "cd, change directory" 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 ===== Konzolové příkazy v Linuxu ===== 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ýpis adresáře v jazyce C ===== 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 \\ * 14.1 Working Directory, getcwd, chdir * 14.2 Accessing Directories * 14.2.2 Opening a Directory Stream. opendir * 14.2.4 Simple Program to List a Directory #include #include #include 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" ===== Program v jazyce Python ===== 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 () ===== Obsah souboru - program jazyce C ===== Ani program v jazyce C nezobrazí obsah souboru #include #include 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; } ==== Toaru OS ==== 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 ===== Opravdový Linux ===== 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 ===== Úkoly ===== Vyberte si **jeden** úkol a pokuste se odpovědět * Popište kdy potřebujeme **execute** právo pro adresáře ( a mohou se mírně lišit informace získané experimentem a z různých popisů ) * Jedoduchý systém ToaruOS nepracuje s právy pro skupinu, navrhněte kousek programu, který práva skupiny zkontroluje. * Zkuste slovy vysvětlit komentář v ToaruOS: /* even root needs exec to exec */ * Zkuste najít ve zdrojovém textu Linuxu další místa kde se kontrolují přístupová práva