int do_execve(char *filename, char **argv, char **envp,
struct pt_regs *regs)
Wewnętrzna funkcja jądra uruchamiająca nowy program
Parametry
- filename
- ścieżka pliku do wykonania
- argv
- argumenty dla uruchomianego programu
- envp
- zmienne środowiskowe
- regs
- rejestry procesu z chwili wywołania systemowego execve()
Algorytm do_execve
- Statycznie alokuje zmienną bprm typu struct
linux_binprm na dane o pliku wykonywalnym.
- Wywołuje funkcję open_exec(). Pobiera ona strukturę
file dla pliku o ścieżce filename. Sprawdza czy
plik istnieje (i jest plikiem regularnym) oraz mamy prawa
wykonania. Zwraca wskaźnik do struktury file tego pliku i
zabrania jego zapisywania(deny_write_access()). Jeśli któraś z
operacji się nie powiedzie, zwraca kod błędu.
- Dokonuje wstępnej inicjacji struktury bprm: czyści
tablicę wskaźników do stron struktury bprm i ustawia jej wskaźnik p
na ostatni element, ustawia liczniki argumentów i zmiennych
środowiskowych (argc, envc).
- Wywołuje funkcję prepare_bin_prm() w celu dalszej
inicjacji bprm. Funkcja ta:
- Sprawdza jeszcze raz możność wykonania pliku.
- Ustawia pola efektywnego użytkownika i grupy
(bprm.e_uid,bprm.e_gid)uwzględniając flagi
setuidisetgid pliku. Jeśli jest ustawione setgid,
ale grupa nie ma praw wykonania e_gid nie jest zmieniany.
- Zeruje pole buf struktury bprm i wczytuje do
niej pierwsze 128 bajtów pliku.
- Do nowo zaalokowanych stron w bprm.page kopiuje po kolei
argumenty programu:filename, envp, argv.Wypełnianie tablicy
odbywa się od tyłu za pomocą funkcji copy_strings(), copy_strings_kernel().
- Wywołuje funkcję search_binary_handler() przekazując jej
strukturę bprm oraz wartości rejestrów procesu. Próbuje ona
zastosować do pliku interpreter któregoś ze znanych formatów plików
binarnych. Jeśli się powiedzie, plik zostanie załadowany i nastąpi
wyjście z funkcji jako nowy program.
Funkcja search_binary_handler() przegląda listę formats. Znajują się
na niej struktury linux_binfmt
reprezentujące formaty plików wykonywalnych.
- Jeśli format definiuje odpowiednią funkcję ładującą (wskaźnik
load_binary w strukturze formatu różny od NULL), zwiększa
licznik referencji do modułu implementującego ten format i wywołuje
tę funkcję dla otrzymanej struktury linux_binprm.
Funkcja load_binary() zwróci błąd
-ENOEXEC, jeśli nie rozpozna formatu pliku. Następuje wtedy
przejście do kolejnego formatu. Jeśli load_binary() rozpozna
format, to przeładuje program procesu i zwróci wartość 0 -
przestrzeń użytkownika procesu została całkowicie zmieniona.
Funkcja do_execve() kończy się propagując każdy kod powrotu
load_binary() różny od -ENOEXEC (0 lub wartość oznaczająca
jakiś błąd).
- Jeśli plik nie został rozpoznany przez żaden z zarejestrowanych
formatów oraz zdefiniowano CONFIG_KMOD - jądro umożliwia dynamiczne
ładowanie modułów - próbuje załadować moduł implementujący ten
format. Nazwa modułu zgadywana jest na podstawie pierwszych bajtów
pliku:
sprintf(modename, "binfmt-%04x", *(unsigned short
*)(& bprm->buf[2])).
Następuje załadowanie modułu modename
- funkcja request_module().
- Następuje drugi obrót pętli (bez sensu, jeśli nie udało się
załadować modułu, lub jądro nie daje takiej możliwości).
Obsługa błędów
W wypadku wystąpienia błędu w trakcie wykonywania algorytmu, następuje
zezwolenie na zapis do pliku (allow_write_access()) i
zwolnienie zasobów, po czym wyjście z funkcji.