# Systemy operacyjne lista 6
## Zadanie 1 kasia


:::info
__Tożsamość__ procesu - identyfikatory (dla użytkownika i dla grupy (w sumie 6)):
- Real user ID (rzeczywisty) - władca procesu,
- Effective user ID (obowiązujący) - aktualny użytkownik,
- Saved set-user-ID (zachowany) - kiedy uprzywilejowany użytkownik ma wykonać nieuprzywilejowane zadanie to zachowuje tu swój identyfikator i użytkownik staje się euid'em.
Procesy mają tożsamość (ang. identity) użytkownika, z reguły tego który je utworzył.
:::
Początkowa tożsamość naszego procesu to: ruid = 1000, euid = 0, suid = 0. (0 to root)
Jak zmieni się tożsamość procesu po wywołaniu następujących funkcji:
- setuid(2000) - sets the effective user ID of the calling process. If the calling process is privileged the real UID and saved set-user-ID are also set.
Root jest uprzywilejowany, suid = ruid = euid = 2000.
- setreuid(-1, 2000) - set real and effective user or group ID, supplying a value of -1 for either the real or effective user ID forces the system to leave that ID unchanged.
ruid = 1000, euid = 2000.
If the real user ID is set (i.e., ruid is not -1) or the effective user ID is set to a value not equal to the previous real user ID, the saved set-user-ID will be set to the new effective user ID.
suid = 0.
- seteuid(2000) - sets the effective user ID of the calling process. Unprivileged processes may only set the effective user ID to the real user ID, the effective user ID or the saved set-user-ID. ruid = 1000, euid = 2000, suid = 0.
- setresuid(-1, 2000, 3000) - sets the real user ID, the effective user ID, and the saved set-user-ID of the calling process. A privileged process may set its real UID, effective UID, and saved set-user-ID to arbitrary values. If one of the arguments equals -1, the corresponding value is not changed. Regardless of what changes are made to the real UID, effective UID, and saved set-user-ID, the filesystem UID is always set to the same value as the (possibly new) effective UID. ruid = 1000, euid = 2000, suid = 3000.
_Czy proces z tożsamością ruid = 0, euid = 1000, suid = 1000 jest uprzywilejowany?_
Proces jest uprzywilejowany, jeśli euid == 0, a teraz nie jest.
## Zadanie 2 Marcin

Bity `rwx` dla katalogów pełnią następującą rolę:
[Link do wikipedii - Notation of traditional Unix permissions](https://en.wikipedia.org/wiki/File-system_permissions)
* r (read) pozwala na pozyskanie listy wszystkich plików w katalogu,
* w (write) pozwala na tworzenie, zmienianie nazw oraz kasowanie plików w katalogu, jak i modyfikowanie atrybutów katalogu,
* x (execute) pozwala na przechodzenie po katalogu, gdy jest on w ścieżce, do której chcemy się dostać, tzn. można dzięki temu dostać się do wszystkich plików i katalogów w środku. Czasami ten bit nazywany jest search bit ze względu na swoje działanie.
Dzięki bitowi `set-gid` w katalogu, wszystkie nowo tworzone pliki i katalogi stają się własnością grupy będącej właścicielem katalogu, zwykle atrybut ten jest dziedziczony przez nowo tworzone podkatalogi.
*(Z Wikipedi)
When `setgid` is applied to a directory, new files and directories created under that directory will inherit their group from that directory. (Default behaviour is to use the primary group of the effective user when setting the group of new files and directories, except on BSD-derived systems which behave as though the setgid bit is always set on all directories (see Setuid).)*
Bit `sticky` w katalogu pozwala na usuwanie/zmienianie uprawnień tylko właścicielowi owego katalogu. Bit ten jest stosowany często w `/tmp`, do którego mogą mieć dostęp wszyscy użytkownicy systemu, przez co użytkownicy nie mogą usuwać plików nienależących do nich.
*(Z wikipedii)
On a directory, the `sticky` permission prevents users from renaming, moving or deleting contained files owned by users other than themselves, even if they have write permission to the directory. Only the directory owner and superuser are exempt from this*
[Flagi premisji do kodu](https://www.gnu.org/software/libc/manual/html_node/Permission-Bits.html)
Czy proces ma upoważniony dostęp mode do pliku o metadanych wczytanych do sb? Taki jest cel funkcji `my_access`. Głównie interesować nas będzie wartość **st_mode** przekazanej struktury **sb**, gdyż w niej zakodowane są uprawnienia na najmniej znaczących bitach.
``` =C
#define MAX_GROUPS_NUMBER 1024
bool my_access(struct stat *sb, int mode)
{
if (geteuid() == 0)//jeśli to jądro to nic nie sprawdzamy tylko dajemy dostęp
return true;
// Jeżeli effective user ID jest takie samo jak ID
// właściciela procesu, to dostęp jest przyznany jeśli
// odpowiedni bit dostępu użytkownika jest ustawiony,
// w przeciwnym wypadku dostęp nie jest przyznawany.
// Odpowiedni bit oznacza, że jeśli proces otwiera plik
// do czytania, to user-read musi być ustawiony, podobnie
// dla write (user-write) i uruchamiania (user-execute).
if (getuid() == geteuid()) {
// Porównaj wszystkie flagi, jeśli (mode >= sb) to przyznaj
// dostęp, w przeciwnym wypadku sprawdzaj dalej warunki.
int sb_mode = sb->st_mode;
uint8_t sb_u_read = (sb_mode & S_IRUSR);
uint8_t sb_u_write = (sb_mode & S_IWUSR);
uint8_t sb_u_exec = (sb_mode & S_IXUSR);
uint8_t md_u_read = (mode & R_OK);
uint8_t md_u_write = (mode & W_OK);
uint8_t md_u_exec = (mode & X_OK);
bool access_flags[3] = {false, false, false};
// Oznaczenie x <= y w tym wypadku oznacza tyle, że y ma
// takie same lub większe uprawnienia (np. x nie wymaga
// uprawnienia czytania, ale y je posiada, więc dostęp
// w takim przypadku też zostanie przyznany).
if (sb_u_read <= md_u_read) access_flags[0] = true;
if (sb_u_write <= md_u_write) access_flags[1] = true;
if (sb_u_exec <= md_u_exec) access_flags[2] = true;
if (access_flags[0] && access_flags[1] && access_flags[2])
return true;
else
return false;
}
// Sprawdzenie, czy jedno z effective group ID lub supplementary
// group ID jest równe group ID pliku, jeżeli tak, to dostęp
// jest przyznawany, w przeciwnym przypadku odrzucany.
gid_t sb_gid = sb->st_gid;
gid_t *group;
group = (gid_t *)malloc(MAX_GROUPS_NUMBER * sizeof(gid_t));
int groups = getgroups(MAX_GROUPS_NUMBER, group);
for (int i = 0; i < groups; i++)
if (sb_gid == group[i])
return true;
// Jeśli odpowiedni bit dostępu jest ustawiony dla other,
// dostęp jest przyznany, w przeciwnym wypadku nie. Proces
// sprawdzania bardzo podobny do tego, co w przypadku drugiego if'a.
return false; // jak nie przejdą żadne testy, to nie ma dostępu
}
```
The mode specifies the accessibility check(s) to be performed, and is either the value F_OK, or a mask consisting of the bitwise OR of one or more of R_OK, W_OK, and X_OK. F_OK tests for the existence of the file. R_OK, W_OK, and X_OK test whether the file exists and grants read, write, and execute permissions, respectively.
POSIX refers to the stat.st_mode bits corresponding to the mask S_IFMT (see below) as the file type, the 12 bits corresponding to the mask 07777 as the file mode bits and the least significant 9 bits (0777) as the file permission bits.
## Zadanie 3 Kuba

## Zadanie 4 Olek

## Zadanie 5 Kornelia

`void exit(int status)` - powoduje normalne zakończenie procesu i zwraca najmniej znaczący bajt wartości `status` do procesu rodzica (patrz `wait(2)`); wszystkie otwarte strumienie stdio są opróżniane i zamykane, pliki utworzone przez tmpfile(3) są usuwane.
_Opisz problemy z buforowaniem plików, które mogą wystąpić dla strumieni biblioteki stdio(3) w przypadku użycia wywołań `fork(2)`, `execve(2)` i `_exit(2)`_
Żadna z tych funkcji nie opróznia bufora.
:::spoiler Przykład
``` c
#include <stdio.h>
int main()
{
printf("Before fork");
fork();
return 0;
}
```
Na standardowe wyjście zostanie wypisane : `Before forkBefore fork`
:::
Po wykonaniu `fork()`, nowo utworzony proces jest kopią swojego rodzica - w szczególności zawartość buforów dziecka i rodzica jest taka sama, więc zostanie wypisana dwukrotnie.
:::spoiler Przykład
``` c
#include <stdio.h>
int main() {
printf("Before execve");
char *args[2];
args[0] = "/bin/ls";
args[1] = NULL;
execve(args[0], args, NULL);
}
```
Zostanie wypisany jedynie wynik polecenia `ls`.
:::
Z kolei tekst, który chcieliśmy wypisać przed wywołaniem `execve` lub `_exit` może zostać wrzucony do bufora i nigdy niewypisany.
_Jak zapobiec tym problemom?_
- Możemy wyłączyć buforowanie wywołując `setbuf(stdout, NULL)`.
- Używać funkcji `write(2)` -> nieefektywne.
- Oprózniać bufor przez `fflush(stdout)`.
- Podawać znak końca linii w przypadku buforowania wierszami.
_Domyślna strategia buforowania strumiania związanego z :_
- plikiem termianala -> buforowane wierszami (wypisuje, gdy natrafi na znak końca linii)
- plikiem zwykłym -> buforowanie pełne (wypisuje, gdy bufor się zapełni)
- standardowym wyjściem błędów -> niebuforowane
_Piszesz program który używa biblioteki «stdio». Działanie programu da się przerwać sygnałem «SIGINT». Ma on wtedy opróżnić wszystkie bufory otwartych strumieni i dopiero wtedy wyjść. Zaproponuj rozwiązanie pamiętając, że w procedurach obsługi sygnału nie wolno korzystać z funkcji, które nie są wielobieżne._
Aby opróżnić bufory otwartych strumieni przed zamknięcem programu możemy w procedurze obsługi sygnału `SIGINT` użyć funkcji `tcflush()`.
---

## Zadanie 6

## Zadanie 7
