Provided by: manpages-pl-dev_0.6-2_all bug

NAZWA

       execve - uruchomienie programu

SKŁADNIA

       #include <unistd.h>

       int execve(const char *filename, char *const argv[],
        char *const envp[]);

OPIS

       execve()  wykonuje  program  wskazywany  przez  filename.  filename  musi  być  albo wykonywalnym plikiem
       binarnym, albo skryptem zaczynającym się od linii w postaci:

           #! interpreter [opcjonalny-parametr]

       Szczegóły tego ostatniego przypadku można znaleźć poniżej w rozdziale "Skrypty interpretowane".

       argv jest tablicą łańcuchów przekazywanych jako argumenty nowego programu. Zgodnie z konwencją pierwszy z
       nich powinien zawierać nazwę pliku skojarzonego z wykonywanym  programem.  envp  jest  tablicą  łańcuchów
       postaci  klucz=wartość,  która  jest przekazywana jako środowisko do nowego programu. Zarówno argv, jak i
       envp muszą być zakończone wskaźnikiem pustym (NULL). Tablica argumentów oraz  środowisko  są  dostępne  w
       funkcji main wywoływanego programu, jeżeli jest ona zdefiniowana jako:

           int main(int argc, char *argv[], char *envp[])

       W  razie  powodzenia  execve()  nie  powraca, a sekcje tekstu, danych, bss i stos wywołującego procesu są
       nadpisywane odpowiednimi sekcjami ładowanego programu.

       Jeśli obecny program jest śledzony za pomocą ptrace, wysyła się mu SIGTRAP po pomyślnym execve().

       Jeżeli plik programu wskazywany przez filename ma ustawiony bit set-user-ID i plik ten  jest  umieszczony
       na  systemie  plików  zamontowanym  bez opcji nosuid (znacznika MS_NOSUID wywołania mount(2)) oraz proces
       wywołujący nie jest śledzony (ptrace(2)), to efektywny  identyfikator  użytkownika  procesu  wywołującego
       jest  ustawiany  na  właściciela  pliku  programu. Podobnie, jeżeli dla pliku programu ustawiony jest bit
       set-group-ID, to efektywnemu identyfikatorowi grupy procesu wywołującego jest  przypisywana  grupa  pliku
       programu.

       Efektywny identyfikator użytkownika jest kopiowany do saved-set-user-ID; podobnie efektywny identyfikator
       grupy  jest  kopiowany  do  saved-set-group-ID.  Kopiowanie  odbywa  się  po  zmianie   któregokolwiek  z
       efektywnych identyfikatorów związanej z bitami praw dostępu set-user-ID i set-group-ID.

       Jeśli program wykonywalny jest skonsolidowany dynamicznie w formacie a.out z bibliotekami dzielonymi,  to
       na  początku  uruchamiania  wywoływany  jest  konsolidator  dynamiczny  ld.so(8),  który ładuje wszystkie
       biblioteki do pamięci i konsoliduje z nimi program wykonywalny.

       Jeżeli program jest  skonsolidowany  dynamicznie  jako  ELF,  to  do  załadowania  potrzebnych  bibliotek
       współdzielonych  używany  jest  interpreter  określony  w  segmencie  PT_INTERP.  Tym  interpreterem jest
       zazwyczaj /lib/ld-linux.so.2, w wypadku programów skonsolidowanych z biblioteką glibc2.

       Wszystkie atrybuty procesu są zachowywane podczas execve(), z wyjątkiem poniższych:

       *  Ustawienia obsługi sygnałów, które są przechwytywane, są zmieniane na wartości domyślne (signal(7)).

       *  Alternatywny stos sygnałów nie jest zachowywany (sigaltstack(2)).

       *  Mapowania pamięci nie są zachowywane (mmap(2))

       *  Dołączone segmenty pamięci dzielonej Systemu V są odłączane (shmat(2)).

       *  Regiony pamięci dzielonej POSIX są odmapowane (shm_open(3)).

       *  Otwarte kolejki komunikatów POSIX są zamykane (mq_overview(7)).

       *  Otwarte semafory nazwane POSIX są zamykane (mq_overview(7)).

       *  Timery POSIX nie są zachowywane (timer_create(2)).

       *  Otwarte strumienie katalogów są zamykane (opendir(3)).

       *  Blokady pamięci nie są zachowywane (mlock(2), mlockall(2)).

       *  Zarejestrowanie  funkcje  wykonywanych  po  zakończeniu  procesu  nie   są   zachowywane   (atexit(3),
          on_exit(3)).

       *  Środowisko zmiennoprzecinkowe jest ustawiane na domyślne (patrz fenv(3)).

       Atrybuty procesu w liście przedstawionej powyżej są określone w POSIX.1-2001. Następujące specyficzne dla
       Linuksa atrybuty procesu również nie są zachowywane podczas execve():

       *  Znacznik  PR_SET_DUMPABLE  prctl(2)  jest  ustawiany,  chyba  że  wykonywany  program ma ustawiony bit
          set-user-ID lub set-group-ID, w którym przypadku znacznik ten jest czyszczony.

       *  Znacznik PR_SET_KEEPCAPS prctl(2) jest czyszczony.

       *  (Od Linuksa 2.4.36 / 2.6.23) Jeśli wykonywany program ma ustawiony bit set-user-ID  lub  set-group-ID,
          to jest czyszczony znacznik PR_SET_PDEATHSIG  sygnału śmierci rodzica ustawiony przez  prctl(2).

       *  Nazwa  procesu  ustawiona przez PR_SET_NAME z prctl(2) (i wyświetlana przez ps -o comm) jest ustawiana
          na nazwę nowego pliku wykonywalnego.

       *  Znacznik SECBIT_KEEP_CAPS w securebits jest czyszczony. Patrz capabilities(7).

       *  Sygnał zakończenia jest ustawiany na SIGCHLD (patrz clone(2)).

       Dalsze uwagi:

       *  Wszystkie wątki oprócz wątku wywołującego są niszczone podczas execve(). Muteksy, zmienne warunkowe  i
          inne obiekty pthreads nie są zachowywane.

       *  Odpowiednik setlocale(LC_ALL, "C") jest wykonywany po uruchomieniu programu.

       *  POSIX.1-2001  określa,  że  ustawienie procedur obsługi sygnału na ignorowanie lub na wartość domyślną
          jest pozostawiane bez zmian. POSIX.1-2001 przewiduje jeden wyjątek od tej reguły: jeśli  SIGCHLD  jest
          ignorowany,  to  implementacja  może  albo  nie zmienić tego ustawienia, albo przestawić je na wartość
          domyślną; Linux robi to pierwsze.

       *  Wszystkie asynchroniczne operacje wejścia/wyjście są anulowane (aio_read(3), aio_write(3)).

       *  Sposób obsługi atrybutów (zdolności) procesu podczas execve() opisano w capabilities(7).

       *  Domyślnie deskryptory  plików  pozostają  otwarte  po  execve().  Deskryptory  plików  oznaczone  jako
          "close-on-exec"  są  zamykane,  patrz  opis  FD_CLOEXEC  w  fcntl(2). (Jeśli deskryptor pliku zostanie
          zamknięty,  to  zwolnione  zostaną  wszystkie  blokady  rekordów  dotyczące  pliku  związanego  z  tym
          deskryptorem.  Szczegóły można znaleźć w fcntl(2)). POSIX.1-2001 mówi, że jeżeli deskryptory plików 0,
          1 i 2 zostałyby zamknięte po pomyślnym wykonaniu execve(), a  proces  uzyskałby  przywileje  z  powodu
          ustawionego  na wykonywanym pliku bitu uprawnień set-user-ID lub set-group-ID, to system może otworzyć
          bliżej nieokreślony plik dla każdego z tych deskryptorów plików. Jako zasadę należy przyjąć, że  żaden
          przenośny  program,  uprzywilejowany  czy  nie,  nie może zakładać, że te trzy deskryptory plików będą
          zamknięte po execve().

   Skrypty interpretowane
       Skrypt interpretowany jest plikiem tekstowym mającym ustawione prawo do wykonywania. Pierwsza linia  tego
       pliku jest w postaci:

           #! interpreter [opcjonalny-parametr]

       interpreter  mus  być  poprawną  nazwą  ścieżki  do  pliku  wykonywalnego, który nie jest skryptem. Jeśli
       argument  filename  wywołania  execve()  określa  interpreter,  to  zostanie  uruchomiony  interpreter  z
       następującymi argumentami:

           interpreter [opcjonalny-arg] filename arg...

       gdzie arg... jest serią słów, na które wskazuje argument argv wywołania execve(), poczynając od argv[1].

       Dla  zachowania  przenośności  na  inne systemu optional-arg albo w ogóle nie powinien być podawany, albo
       powinien być podany jako pojedyncze słowo (nie powinien zawierać spacji); patrz UWAGI poniżej.

   Ograniczenia rozmiaru argumentów i środowiska
       Większość implementacji Uniksa narzuca ograniczenia na całkowity rozmiar argumentów linii poleceń  (argv)
       i  środowiska  (envp)  przekazywanych  do  nowego  programu.  POSIX.1  pozwala  implementacji  ogłosić te
       ograniczenia  za  pomocą  stałej  ARG_MAX  (albo  zdefiniowanej  w  <limits.h>,  albo  dostępnej  podczas
       wykonywania programu za pomocą wywołania sysconf(_SC_ARG_MAX)).

       W jadrach Linuksa wcześniejszych niż 2.6.23, pamięć używana do przechowywania łańcuchów znaków środowiska
       i   argumentów   była  ograniczana  do  32  stron  (zdefiniowane  przez  stałą  jądra  MAX_ARG_PAGES).  W
       architekturach mających strony o rozmiarze 4 kB oznaczało to maksymalny rozmiar równy 128 kB.

       W jądrze 2.6.23 i późniejszych większość  architektur  wspiera  ograniczenie  rozmiaru  wywodzące  się  z
       miękkiego  limitu  zasobu   RLIMIT_STACK  (patrz getrlimit(2)), obowiązującego podczas wywołania execve()
       (Wyjątek stanowią architektury  nie  mające  jednostki  zarządzania  pamięcią:  przechowują  ograniczenie
       obowiązujące  przed  wersją  jądra   2.6.23). Zmiana ta pozwala programom na posiadanie znacznie większej
       listy argumentów lub środowiska. Na  tych  architekturach  całkowity  rozmiar  jest  ograniczony  do  1/4
       dopuszczalnego  rozmiaru  stosu.  (Limit   1/4  zapewnia, że zostanie jakaś przestrzeń na stos dla nowego
       programu). Od Linuksa 2.6.25 jądro przyjmuje wartość minimalną 32 stron dla  tego  limitu  rozmiaru,  tak
       żeby  zagwarantować,  że w przypadku gdy RLIMIT_STACK ma niewielką wartość, aplikacje dostaną co najmniej
       taką przestrzeń na argumenty i środowisko,  jaką  miały  w  Linuksie  2.6.23  i  wcześniejszych.  (Takiej
       gwarancji nie ma w Linuksach 2.6.23 i 2.6.24). Dodatkowo ograniczeniem na pojedynczy łańcuch znaków są 32
       strony (stała jądra MAX_ARG_STRLEN), a maksymalna liczba takich łańcuchów wynosi 0x7FFFFFFF.

WARTOŚĆ ZWRACANA

       Po  pomyślnym  zakończeniu  execve()  nie wraca, w wypadku błędu zwracane jest -1 i odpowiednio ustawiane
       errno.

BŁĘDY

       E2BIG  Całkowita liczba bajtów środowiska (envp) i listy argumentów (argv) jest za duża.

       EACCES Brak praw do przeszukiwania dla składnika ścieżki filename lub ścieżki interpretera skryptu (patrz
              także path_resolution(7)).

       EACCES Plik lub interpreter skryptu nie jest zwykłym plikiem.

       EACCES Brak praw wykonywania dla pliku, skryptu lub intepretera ELF.

       EACCES System plików jest zamontowany jako noexec.

       EAGAIN (od Linuksa 3.1)
              Po zmianie swojego rzeczywistego UID za pomocą jednego z wywołań set*uid(), wywołujący był—i wciąż
              jest—powyżej swojego limitu zasobó RLIMIT_NPROC  (zob.  setrlimit(2)).  Więcej  informacji  o  tym
              błędzie znajduje się w rozdziale UWAGI.

       EFAULT filename  lub jeden ze wskaźników w wektorach argv lub envp wskazuje poza dostępną dla użytkownika
              przestrzeń adresową.

       EINVAL Plik wykonywalny w formacie ELF ma więcej niż jeden segment PT_INTERP (tzn. ma  więcej  niż  jeden
              interpreter).

       EIO    Wystąpił błąd wejścia-wyjścia.

       EISDIR Intepreter ELF jest katalogiem.

       ELIBBAD
              Nie został rozpoznany format interpretera ELF.

       ELOOP  Podczas  rozwiązywania  filename, nazwy skryptu lub interpretera ELF napotkano zbyt wiele dowiązań
              symbolicznych.

       EMFILE Proces osiągnął już maksymalną liczbę otwartych plików.

       ENAMETOOLONG
              filename jest zbyt długie.

       ENFILE Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

       ENOENT Plik filename, skrypt,  lub  intepreter  ELF  nie  istnieje  albo  nie  można  znaleźć  biblioteki
              współdzielonej potrzebnej do uruchomienia pliku lub interpretera.

       ENOEXEC
              Nie  rozpoznano  formatu  pliku  binarnego, plik ten jest skompilowany dla innej architektury albo
              wystąpił jakiś inny błąd formatu pliku, który powoduje, że program nie może być uruchomiony.

       ENOMEM Brak dostępnej pamięci jądra.

       ENOTDIR
              Składnik ścieżki filename, ścieżki skryptu lub ścieżki interpretera ELF nie jest katalogiem.

       EPERM  System plików jest zamontowany jako  nosuid,  użytkownik  nie  jest  administratorem,  a  plik  ma
              ustawiony bit set-user-ID lub set-group-ID.

       EPERM  Proces  jest  śledzony  (trace),  użytkownik  nie jest superużytkownikiem, a plik ma ustawiony bit
              set-user-ID lub set-group-ID.

       ETXTBSY
              Plik wykonywalny był otwarty do zapisu przez jeden lub więcej procesów.

ZGODNE Z

       SVr4, 4.3BSD, POSIX.1-2001. POSIX.1-2001 nie opisuje zachowania #!,oprócz tego jest zgodny.

UWAGI

       Procesy z ustawionymi  znacznikami  set-user-ID  oraz  set-group-ID  nie  mogą  być  śledzone  za  pomocą
       ptrace(2).

       Efekt  zamontowania  systemu  plików nosuid jest różny dla różnych wersji jądra Linuksa: niektóre odmówią
       uruchomienia programów set-user-ID i  set-group-ID,  gdy  spowodowałoby  to  udostępnienie  użytkownikowi
       możliwości,  którymi  w  danym  momencie  nie  dysponuje  (i zwrócą EPERM), inne po prostu zignorują bity
       set-user-ID i set-group-ID i pomyślnie wykonają exec(). W Linuksie, argv i envp mogą być  określone  jako
       NULL.  W  obu  przypadkach  ma  to  ten  sam  skutek,  co  określenie  argumentu  jako wskaźnika do listy
       zawierającej pojedynczy wskaźnik zerowy. Proszę  nie  korzystać  z  tej  "funkcji"!  Jest  to  zachowanie
       niestandardowe  i  nieprzenośne,  większość  innych  systemów  uniksowych  zwróci  w takim przypadku błąd
       (EFAULT).

       POSIX.1-2001 określa, że wartości zwracane przez sysconf(3) nie powinny  się  zmieniać  przez  cały  czas
       życia  procesu.  Jednakże  od  wersji  2.6.23 Linuksa zmiana limitu zasobów RLIMIT_STACK powoduje również
       zmianę wartości zwracanej przez _SC_ARG_MAX, żeby  odzwierciedlić  fakt,  że  zmieniły  się  ograniczenia
       przestrzeni służącej do przechowywania argumentów linii poleceń i zmiennych środowiska.

       W  większości  sytuacji  gdy execve() zawiedzie, kontrola powraca do oryginalnego obrazu wykonywalnego, a
       wywołujący execve() może następnie obsłużyć błąd.  Jednak  są  (rzadkie)  przypadki  (zwykle  przy  braku
       zasobów),  gdy błąd może wystąpić w momencie bez powrotu: oryginalny obraz wykonywalne został podzielony,
       a nie można całkowicie zbudować nowego obrazu. W takich sytuacjach jądro zabija proces sygnałem SIGKILL.

   Skrypty interpretowane
       Maksymalna długość pierwszego wiersza skryptu interpretera wynosi 127 znaków.

       Semantyka argumentu optional-arg skryptu interpretera różni się pomiędzy  implementacjami.  Pod  Linuksem
       cały  łańcuch  znaków  występujący  po  nazwie  interpretera  jest przekazywany jako pojedynczy argument.
       Jednakże inne systemy zachowują się inaczej. Niektóre systemy traktują  pierwszy znaku białej spacji jako
       znak kończący optional-arg. Na innych systemach skrypt interpretera może przyjmować  wiele  argumentów  i
       białe znaki optional-arg służą do ich rozdzielania.

       Linux ignoruje bity set-user-ID i set-group-ID dla skryptów.

   execve() i EAGAIN
       Poniżej  znajduje  się  bardziej szczegółowy opis błędu EAGAIN, który może wystąpić (od Linuksa 3.1) przy
       wywoływaniu execve().

       Błąd  EAGAIN  może  wystąpić,  gdy  wywołanie  poprzedzające  setuid(2),  setreuid(2)  lub   setresuid(2)
       spowodowało,  że  rzeczywisty  ID użytkownika procesu zmienił się i ta zmiana doprowadziła do wyczerpania
       jego limitu zasobów RLIMIT_NPROC (tzn. liczba procesów należących do nowego rzeczywistego UID  przekroczy
       limit zasobów). W wersjach Linuksa od 2.6.0 do 3.0 powodowało to niepowodzenie wywołania set*uid(). Przed
       wersja  2.6  limit  zasobów  nie  był nakładany  w  przypadku  procesów  zmieniających swój identyfikator
       użytkownika.

       Od Linuksa 3.1, opisana sytuacja nie powoduje już niepowodzenia wywołania set*uid(), ponieważ zbyt często
       prowadziło to do dziur  bezpieczeństwa,  gdy  nieprawidłowo  napisane  programy  nie  sprawdzały  statusu
       zakończenia  i  przyjmowały,  że—jeśli  wywołujący  ma  uprawnienia roota—wywołanie zawsze powiedzie się.
       Obecnie wywołania set*uid() poprawnie zmieniają rzeczywisty UID,  lecz  jądro  ustawia  wewnętrzną  flagę
       PF_NPROC_EXCEEDED,  wskazując  że  przekroczono limit zasobów RLIMIT_NPROC. Jeśli flaga PF_NPROC_EXCEEDED
       jest ustawiona, a limit zasobów jest wciąż  przekroczony  w  trakcie  kolejnego  wywołania  execve(),  to
       wywołanie  to zakończy się z błędem EAGAIN.  Ta logika jądra zapewnia, że limit zasobów RLIMIT_NPROC jest
       wciąż wymuszony dla zwykłej pracy demonów uprzywilejowanych —przykładem  jest  fork(2)   +  set*uid()   +
       execve().

       Jeśli jednak limit zasobów nie był już przekroczony w trakcie wywołania execve() (ponieważ zakończyły się
       inne  procesy należące do tego rzeczywistego UID pomiędzy wywołaniami set*uid() i execve()), to wywołanie
       execve() powiedzie się, a jądro usunie  flagę  procesu  PF_NPROC_EXCEEDED.  Flaga  jest  usuwana  również
       wówczas, gdy kolejne wywołanie do fork(2) przez ten proces powiedzie się.

   Historia
       W Uniksie V6 lista argumentów wywołania exec() była kończona 0, podczas gdy lista argumentów funkcji main
       była  kończona  -1.  Dlatego  lista  argumentów  przekazana  do  main  nie mogła być bezpośrednio użyta w
       wywołaniu exec(). Od Uniksa V7 obie te wartości są NULL.

PRZYKŁAD

       Następujący program jest zaprojektowany do wykonania przez drugi program przedstawiony poniżej. Wyświetla
       swoje argumenty uruchomienia po jednym w wierszu.

           /* myecho.c */

           #include <stdio.h>
           #include <stdlib.h>

           int
           main(int argc, char *argv[])
           {
               int j;

               for (j = 0; j < argc; j++)
                   printf("argv[%d]: %s\n", j, argv[j]);

               exit(EXIT_SUCCESS);
           }

       Tego programu można użyć do uruchomienia programu podanego w argumencie linii poleceń:

           /* execve.c */

           #include <stdio.h>
           #include <stdlib.h>
           #include <unistd.h>

           int
           main(int argc, char *argv[])
           {
               char *newargv[] = { NULL, "witaj", "świecie", NULL };
               char *newenviron[] = { NULL };

               if (argc != 2) {
                   fprintf(stderr, "Użycie: %s <plik-do-uruchomienia>\n", argv[0]);
                   exit(EXIT_FAILURE);
               }

               newargv[0] = argv[1];

               execve(argv[1], newargv, newenviron);
               perror("execve");   /* execve() wraca tylko w przypadku błędu */
               exit(EXIT_FAILURE);
           }

       Możemy użyć drugiego programu do uruchomienia pierwszego:

           $ cc myecho.c -o myecho
           $ cc execve.c -o execve
           $ ./execve ./myecho
           argv[0]: ./myecho
           argv[1]: witaj
           argv[2]: świecie

       Możemy także użyć tych programów do pokazania używania interpretera  skryptu.  Aby  to  zrobić,  tworzymy
       skrypt, którego "interpreterem"  jest nasz program myecho:

           $ cat > script.sh
           #! ./myecho script-arg
           ^D
           $ chmod +x script.sh

       Następnie używamy naszego programu do wykonania skryptu:

           $ ./execve ./script.sh
           argv[0]: ./myecho
           argv[1]: script-arg
           argv[2]: ./script.sh
           argv[3]: witaj
           argv[4]: świecie

ZOBACZ TAKŻE

       chmod(2),    fork(2),   ptrace(2),   execl(3),   fexecve(3),   getopt(3),   credentials(7),   environ(7),
       path_resolution(7), ld.so(8)

O STRONIE

       Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis  projektu,  informacje
       dotyczące   zgłaszania   błędów,   oraz   najnowszą   wersję   oryginału   można   znaleźć   pod  adresem
       http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

       Autorami  polskiego  tłumaczenia  niniejszej   strony   podręcznika   man   są:   Przemek   Borys   (PTM)
       <pborys@dione.ids.pl>,    Andrzej    Krzysztofowicz    (PTM)    <ankry@mif.pg.gda.pl>,   Robert   Luberda
       <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.

       Polskie tłumaczenie jest częścią  projektu  manpages-pl;  uwagi,  pomoc,  zgłaszanie  błędów  na  stronie
       http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją  3.71 oryginału.

Linux                                              2014-08-19                                          EXECVE(2)