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

  1. Statycznie alokuje zmienną bprm typu struct linux_binprm na dane o pliku wykonywalnym.
  2. 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.
  3. 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).
  4. Wywołuje funkcję prepare_bin_prm() w celu dalszej inicjacji bprm. Funkcja ta:
    1. Sprawdza jeszcze raz możność wykonania pliku.
    2. 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.
    3. Zeruje pole buf struktury bprm i wczytuje do niej pierwsze 128 bajtów pliku.
  5. 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().
  6. 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.

    1. 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).
    2. 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().
    3. 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.