====== 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