---
# System prepended metadata

title: SO Lista 4

---

# SO Lista 4
## Zadanie 1
![](https://i.imgur.com/eieyoML.png)

### Do czego służy kod sterujący CPR opisany w CSI?
Służą do odczytania pozycji kursora, sam kod powoduje, że terminal transmituje '\033\[n;mR', gdzie n,m to odpowiednio rząd i kolumna 

### TCGEST
pobiera aktualne atrybuty terminala i zapisuje w `argp` (ioctl(fd, TCGETS, argp)) to samo co tcgetattr(fd, argp)

### TCSETSW
czeka, aż output queue się wyczyści, po czym ustwaia atrybuty na te w `argp`, tcsetattr(tcsetattr(fd, TCSADRAIN, argp) to samo co (ioctl(fd, TCSETSW, argp))

### TIOCINQ
zapisz ilość bajtów z input queue do `argp` (ioctl(fd,  TIOCINQ, argp)

### TIOCSTI
wsadź bajt `argp` do input queue(ioctl(fd, TIOCSTI, argp))

### Jak flagi ECHO, ICANON, CREAD wpływaja na działanie sterowników terminala 

tryp kanoniczny(wł/wył)
echo na terminal(wł/wył)
czytanie z terminala (wł/wył)

![](https://i.imgur.com/sljB20e.png)


<!-- zad1 zdjecia -->
![](https://i.imgur.com/htXoyV3.jpg)


## Zadanie 2
![](https://i.imgur.com/GffeIcl.png)
<!-- zad2 zdjecia -->
### Script 
podczas sesji terminala loguje wszystkie znaki z input i output queue i zapisuje do pliku

### Pseudoterminal 
para urządzeń z komunikacją w dwie strony - <b> master i slave </b>. 
#### Slave 
służy jako terminal kontrolny, do kórego mogą przyłączać się procesy, pisać, czytać etc. 
#### Master
jest od strony użytkownika i przekazuje wszystko do slave

### ICRNL 
mapuje CR na NL (carriage return a newline) '\r' -> '\n'

### ONLCR 
mapuje NL na CRNL na outpucie 

### Pokaż że sterownik terminala dobrze przepisuje znaki zgodnie z tymi flagami 

1. Po każdej komendzie mamy '\r\n', ale wpisaliśmy tylko '\n', więc podczas echo na terminal zostało zmienione 
2. ctrl+M to znak CR jak odpalimy np xxd i tam zaczniemy to wpisywać to dostaniemy NL

### Na podstawie pliku script.log pokaż jak script używa pseudoterminala do komunikacji z programami działającymi pod <u>dash</u>

widzimy, ze terminal kontrolny jest na fd=3 po otworzeniu go przez openat(),
script czyta z niego wyniki komend i nasz input, bo echo włączone i przesyła dalej do nas.
![](https://i.imgur.com/PVyxaTU.png)

![](https://i.imgur.com/JZjn0Pz.jpg)


## Zadanie 3
![](https://i.imgur.com/4IpVdJ8.png)
![](https://i.imgur.com/WE0mjwe.png)
![](https://i.imgur.com/OYOspkm.png)


### Potok 
mechanizm komunikacji między procesowej

Przed odpaleniem filtruj po wymienionych syscallach + pipe2

### Które procesy i w jakiej kolejności będą wołały następne wywołania systemowe?

#### dup2(old,new)
tworzy nowy fol(?)2 numerem new, który odwołuje się do tego samego pliku co old

#### pipe2(pipefd[2], flags)
tworzy potok jednokierunkowy

1. Wczytał linie z komendą -> dash
2. Tworzymy potok(3) - read, (4) - write, zamyka koniec write - (4) -> dash
3. forkuje dziecko (ps) -> dash
4. Tworzy potok(4) - read, (5) - write -> dash
5. forkuje dziecko(grep) -> dash
6. ps zamyka stronę read(3) -> ps
7. ps podłącza stdout do końća write(4), dup2(4,1) -> ps
8. ps zamyka write(4) -> ps
9. dash zamyka read(3) -> dash
10. dash zamyka write(5) -> dash
11. ps robi execve z komendy "ps -ef" -> ps
12. grep zamyka write(4) -> grep
13. grep ustawia stdin na read(3) -> grep i zamyka read(3)
14. grep ustawia stdout na write(5) -> grep i zamyka write(5)
15. grep robi execve z komendą "grep sh" -> grep
16. wc ustawia stdin na read(4) -> wc i zamyka write(4)
17. wc otwiera plik openat("cnt") -> wc
18. wc przekierowuje output na fd od pliku cnt dup2(cnt_fd, 1) i zamyka plik -> wc
19. wc robi execve("wc -l") -> wc

<!-- zad3 zdjecia -->
![](https://i.imgur.com/noCnuqd.jpg)


![](https://i.imgur.com/tgshgNc.png)



## Zadanie 4
![](https://i.imgur.com/ssu6Zsj.png)

### setgpid(pid, pgid)
ustawia id grupy procesu pid na pgid 

### ioctl(fd, TIOCSPGRP, [pid])
ustaw grupę procesów pid jako grup pierwszoplanową

### Wskaż kiedy powłoka tworzy nową grupę procesów i jak umieszcza tam procesy realizujące potok
setgpid(0, pid) -> grupa procesu który woła funkcje jest ustawiona na pid


(dodaj do filtra setgpid, fnctl, getpid, getppid, ioctl)

### Kiedy setpgid tworzy nową grupę?
Kiedy pid i pgid jest równy, a wybrany proces jest leaderem grupy

Gdy pid != pgid i pid != 0 to setpgid zmienia grupę jakiegoś procesu pid

### Dlaczego setpgid jest robione w procesie powłoki i procesie potomnym?
pgid potoku - pid pierwszego procesu w potoku
Ponieważ po fork() nie mamy pewności, który proces będzie działał pierwszy (dziecko czy rodzic), tak więc dla pewnosci w rodzicu ustawiamy pgid dziecka (setpgid(child,pgid_potoku)), a w dziecku on sam ustawia swój pgid na pgid potoku (setpgid(0,pgid_potoku))

### Kiedy powłoka ustala grupę pierwszoplanową? 
(z pomocą ioctl()) 
pierwszy proces w pipeline jest liderem grupy i to jego pid jest używany przy tych callach ioctl(). Taki call pojawia się zawsze po forku w dziecku po ustawieniu setpgid() z wyżej wymienionych przyczyn 

### Na jakiej podstawie powłoka wyznacza kod  wyjścia z potoku? 
Na podstawie kodu wyjścia ostatniego procesu
<!-- zad4 zdjecia -->
![](https://i.imgur.com/Y01IIAH.png)

![](https://i.imgur.com/qbLgQDW.jpg)


## Zadanie 5
![](https://i.imgur.com/W5Q31st.png)

### Czemu nie można robić read() i write() na katalogach?
katalog jest uznawany za zupełnie inny typ pliku, tylko kernel może pisać do katalogów, uprawnienia rwx mają inne znaczenie, w szczególności używana jest struktura DIR* zamiast FILE* oraz inny zestaw instrukcji

### Czym czytać katalog? 
opendir() lyb readdir() (man readdir)

### Dlaczego zawartość katalogu nie jest posortowana?
Położenie plików w katalogu zależy od położenia ich rekordów w nim w systemie plików i od tego jak system plików zarządza lukami pomiędzy rekordami

### Z czego wynika podana podana lista dowiązań?

Prawdopodobnie z tego że jest jest X odwołań do katalogu w innych miejscach w systemie, dokładniej to każdy katalog w '/' ma w sobie '.\.' takich jest Y, do tego '.' w '/' i jakiś katalog w którym jest root systemu - i mamy link count X

<!-- zad5 zdjecia -->
![](https://i.imgur.com/kueDVC6.jpg)


## Zadanie 6
![](https://i.imgur.com/mlBcOOj.png)
access("file",F_OK) -> sprawdza czy plik istnieje

### Mamy race condition w sytuacji, gdy:
1. Podczas access(path,F_OK) plik nie będzie istniał
2. Przed wywołaniem open(), wygramy wyścig tworząc plik, wtedy potencjalnie
   program będzie myslał ze nałożył blokade na plik (ustawił 700 maske), ale
   tak naprawde dalej mamy dostęp bo sami go stworzylismy (nie wiem co pisze ten
   przykład nawet nie jest potrzebny raczej)

### Jakie zagrożenie niesie za sobą taki błąd?
Pisanie do plików z uprawnieniami roota, za czym idzie mieszanie w konfigach, ustawieniach serwisów, plików z hasłami (passwd), co może doprowadzić do zrootowania (dostania uprawnień roota) systemu.

<!-- zad6 zdjecia -->
![](https://i.imgur.com/4MjBkoC.png)


```c
#include "csapp.h"

// bool f_lock(const char *path) {
// 	if (access(path, F_OK) == 0)
// 		return false;
// 	(void)Open(path, O_CREAT|O_WRONLY, 0700);
// 	return true;
// }

bool f_lock(const char *path) {
	int fd = Open(path, O_CREAT|O_EXCL|O_WRONLY, 0700);
	if (fd > 0)
		return true;
	return false;
}

void f_unlock(const char *path) {
	Unlink(path);
}
```

## Zadanie 7
![](https://i.imgur.com/0WKNGjR.png)
```c
 /* innocent.c */
 /* TODO: Something is missing here! */
  char buf[MAXLINE],path[MAXLINE];
  int n;

  for (int fd = 4; fd <= max_fd; fd++)
  {
    if(fcntl(fd,F_GETFD) != -1 && lseek(fd, 0, SEEK_CUR) != -1){
      printf("got a hit on fd=%d\n",fd);
      Lseek(fd,0,SEEK_SET);
      snprintf(path,sizeof(path),"/proc/self/fd/%d",fd);
      n = Readlink(path,buf,sizeof(buf));
      buf[n] = '\0';
      dprintf(out,"File descriptor %d is ’%s’ file!\n",fd,buf);
      while((n = Read(fd,buf,sizeof(buf))) > 0)
        Write(out,buf,n);
    }
  }
  
  /* zeby janek rozpruwacz zcrakował hasło trzeba przekleic tą linijke do innego pliku np 'hash_to_crack'
     a potem odpalic 'john hash_to_crack' */
```
```c
 /* leaky.c */
 /* TODO: Something is missing here to fix the issue! */

  int val = fcntl(fd_2, F_GETFD, 0);
  val |= FD_CLOEXEC; /* close on exec */
  fcntl(fd_2,F_SETFD,val);
```

## Zadanie 8
![](https://i.imgur.com/gKNk6ce.png)
### Metadane 
dane które opisują dane np. ile bajtów ma plik, jaki jest encoding, data modyfikacji itd.

st_blocks * st_blksize = faktyczny rozmiar pliku

### Czemu liczba używanych bloków jest mniejsza od tej wynikającej z objętości pliku z pola «st_size»
Ponieważ możemy przesunąć kursor tak daleko jak chcemy i tam pisać dalej 

### Czemu jest większa od liczby faktycznie używanych bloków zgłaszanych przez «mkholes»?
Bo struct stat liczy w 512B blokach, a program w 4096B

<!-- zad8 zdjecia -->
![](https://i.imgur.com/iVFde4J.png)

