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.