Provided by: manpages-ru-dev_4.21.0-2_all bug

ИМЯ

       execve - выполнить программу

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #include <unistd.h>

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

ОПИСАНИЕ

       Вызов  execve  выполняет программу, задаваемую pathname. При этом программа, выполняющаяся
       вызвавшим процессом, замещается новой программой, заново  инициализируется  стек,  куча  и
       сегменты данных (инициализированные и не инициализированные).

       В pathname должно быть указано имя двоичного исполняемого файла или сценарий, начинающийся
       со строки вида:

           #!интерпретатор [необязательный параметр]

       Подробней о сценариях написано далее в «Интерпретируемые сценарии».

       argv is an array of pointers to strings passed to the  new  program  as  its  command-line
       arguments.   By convention, the first of these strings (i.e., argv[0])  should contain the
       filename associated with the file being executed.  The argv array must be terminated by  a
       NULL pointer.  (Thus, in the new program, argv[argc] will be NULL.)

       envp  is  an array of pointers to strings, conventionally of the form key=value, which are
       passed as the environment of the new program.  The envp array must be terminated by a NULL
       pointer.

       This  manual  page  describes  the  Linux  system  call  in detail; for an overview of the
       nomenclature and the many,  often  preferable,  standardised  variants  of  this  function
       provided by libc, including ones that search the PATH environment variable, see exec(3).

       The  argument  vector  and environment can be accessed by the new program's main function,
       when it is defined as:

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

       Однако заметим, что использование третьего  аргумента  главной  функции  не  определено  в
       POSIX.1;  согласно  POSIX.1,  окружение  должно  быть  доступно  через  внешнюю переменную
       environ(7).

       При успешном выполнении execve() управление не  возвращается,  а  код,  инициализированные
       данные,  неинициализированные  данные  (bss)  и  стек вызвавшего процесса перезаписываются
       содержимым загруженной программы.

       Если текущая программа выполнялась под  управлением  ptrace,  то  после  успешного  вызова
       execve() ей посылается сигнал SIGTRAP.

       If  the  set-user-ID  bit  is  set  on  the program file referred to by pathname, then the
       effective user ID of the calling process is changed to that of the owner  of  the  program
       file.   Similarly,  if the set-group-ID bit is set on the program file, then the effective
       group ID of the calling process is set to the group of the program file.

       Вышеупомянутые преобразования эффективных IDs не выполняются (т. е.,  биты  set-user-ID  и
       set-group-ID игнорируются), если что-либо из следующего истинно:

       •  установлен атрибут no_new_privs для вызывающей нити (смотрите prctl(2));

       •  подлежащая файловая система смонтирована с nosuid (флаг MS_NOSUID для mount(2)); или

       •  вызывающий процесс выполняется под контролем ptrace.

       Также  игнорируются  мандаты  файла  программы  (смотрите capabilities(7)), если что-то из
       вышеперечисленного истинно.

       Фактический идентификатор пользователя процесса  копируется  в  сохранённый  идентификатор
       пользователя   (set-user-ID),   также   фактический   идентификатор  группы  копируется  в
       сохранённый  идентификатор  группы  (set-group-ID).  Это  копирование  выполняется   после
       изменения  любого  фактического  идентификатора, которое происходит из-за выставленных бит
       режима set-user-ID и set-group-ID.

       The process's real UID and real GID, as well as its supplementary group IDs, are unchanged
       by a call to execve().

       Если   исполняемый  файл  является  динамически-скомпонованным  файлом  в  формате  a.out,
       содержащим заглушки для  динамических  библиотек,  то  в  начале  выполнения  этого  файла
       вызывается динамический компоновщик Linux ld.so(8), который начинает выполнение с загрузки
       общих объектов в память и компонует их с исполняемым файлом.

       Если исполняемый файл является динамически  компонуемым  файлом  в  формате  ELF,  то  для
       загрузки  необходимых  общих  объектов  используется  интерпретатор,  указанный в сегменте
       PT_INTERP. Для программ, скомпонованных с glibc, обычно это  /lib/ld-linux.so.2  (смотрите
       ld-linux.so(8)).

   Effect on process attributes
       При вызове execve() сохраняются все свойства процесса, за исключением:

       •  Значения  обработчиков всех захватываемых сигналов сбрасываются в значения по умолчанию
          (signal(7)).

       •  Любой альтернативный стек сигнала не сохраняется (sigaltstack(2)).

       •  Проецирование памяти не сохраняется (mmap(2)).

       •  Подключённые общие сегменты памяти System V отключаются (shmat(2)).

       •  Области общей памяти POSIX становятся неспроецированными (shm_open(3)).

       •  Открытые дескрипторы в очереди сообщений POSIX закрываются (mq_overview(7)).

       •  Все открытые именные семафоры POSIX закрываются (sem_overview(7)).

       •  Таймеры POSIX не сохраняются (timer_create(2)).

       •  Все открытые потоки каталогов (directory streams) закрываются (opendir(3)).

       •  Блокировки памяти не сохраняются (mlock(2), mlockall(2)).

       •  Обработчики завершения работы (exit handlers) не сохраняются (atexit(3), on_exit(3)).

       •  Окружения плавающей точки сбрасываются в настройки по умолчанию (fenv(3)).

       В POSIX.1 определён список сохраняемых  свойств  процесса.  Следующие  свойства  процесса,
       имеющиеся только в Linux, также не сохраняются при execve():

       •  The process's "dumpable" attribute is set to the value 1, unless a set-user-ID program,
          a set-group-ID program, or a program with capabilities is being executed, in which case
          the  dumpable  flag may instead be reset to the value in /proc/sys/fs/suid_dumpable, in
          the circumstances described under PR_SET_DUMPABLE in prctl(2).  Note  that  changes  to
          the  "dumpable"  attribute  may  cause  ownership  of  files in the process's /proc/pid
          directory to change to root:root, as described in proc(5).

       •  Флаг PR_SET_KEEPCAPS (prctl(2)) очищается.

       •  (Начиная с Linux 2.4.36 / 2.6.23) Если  выполняется  программа  с  установленным  битом
          set-user-ID  или  set-group-ID,  то  сигнал о смерти родителя, установленный prctl(2) с
          флагом PR_SET_PDEATHSIG, очищается.

       •  Имя процесса, установленное через prctl(2) PR_SET_NAME  (и  отображаемое  ps -o  comm),
          изменяется на имя нового исполняемого файла.

       •  Флаг SECBIT_KEEP_CAPS securebits очищается. Смотрите capabilities(7).

       •  Сигнал завершения (termination signal) устанавливается в SIGCHLD (clone(2)).

       •  Таблица  файловых дескрипторов не является общей, отменяется действие флага CLONE_FILES
          у clone(2).

       Также стоит учитывать следующее:

       •  Все нити (threads), отличные от вызывающей, уничтожаются execve().  Мьютексы,  условные
          переменные и другие объекты pthreads не сохраняются.

       •  При запуске программы выполняется эквивалент setlocale(LC_ALL, "C").

       •  В POSIX.1 указано, что действия по отношению к любым игнорируемым или имеющим настройку
          по умолчанию сигналам, остаются неизменными.  В  POSIX.1  есть  одно  исключение:  если
          SIGCHLD  игнорируется,  то  реализация  может  оставить обработку сигнала (disposition)
          неизменной или вернуть настройку по умолчанию; в Linux используется первое.

       •  Все ожидающие выполнения  асинхронные  операции  ввода-вывод  отменяются  (aio_read(3),
          aio_write(3)).

       •  Как   происходит   обработка   мандатов   (capabilities)   при   вызове  execve(),  см.
          capabilities(7).

       •  По  умолчанию,  после  execve()  файловые  дескрипторы  остаются  открытыми.   Файловые
          дескрипторы,   помеченные  как  close-on-exec  (закрывать  при  запуске),  закрываются;
          смотрите описание FD_CLOEXEC в fcntl(2) (если файловый дескриптор закрыт, это  приводит
          к  освобождению  всех  имеющихся  блокировок, полученных на соответствующий файл данным
          процессом. Подробней смотрите fcntl(2)).  В  POSIX.1  сказано,  что  если  бы  файловые
          дескрипторы 0, 1 и 2 были закрыты после успешного вызова execve(), и процесс получил бы
          привилегии из-за установленных битов режима set-user-ID или set-group-ID на исполняемом
          файле, то система смогла бы открыть произвольный файл для каждого из этих дескрипторов.
          Считается, что переносимая программа, с привилегиями или без,  не  может  рассчитывать,
          что эти три файловых дескриптора будут оставаться закрытыми после execve().

   Интерпретируемые сценарии
       Интерпретируемый  сценарий  —  это  текстовый файл, у которого установлен бит выполнения и
       первая строка имеет вид:

           #!интерпретатор [необязательный параметр]

       В поле интерпретатор должно быть указано имя файла запуска.

       Если в аргументе pathname для execve() указан интерпретируемый сценарий, то  интерпретатор
       будет вызван со следующими параметрами:

           интерпретатор [необязательный параметр] pathname параметр…

       where  pathname  is  the pathname of the file specified as the first argument of execve(),
       and arg... is the series of words pointed to by the argv argument of execve(), starting at
       argv[1].   Note  that  there  is no way to get the argv[0] that was passed to the execve()
       call.

       В целях переносимости, необязательный параметр должен  быть  или  пустым,  или  задаваться
       одним словом (т.е., не должен содержать пробельных символов); см. ЗАМЕЧАНИЯ далее.

       Начиная  с  Linux 2.6.28 ядро позволяет интерпретатору сценария самому быть сценарием. Это
       разрешение рекурсивно (до четырёх раз), поэтому сценарий  может  быть  сценарием,  который
       интерпретируется сценарием и т. д.

   Ограничения на размер параметров и окружения
       Большинство  реализаций  UNIX накладывает некоторые ограничения на полный размер параметра
       командной строки (argv) и  окружения  (envp),  которые  можно  передать  новой  программе.
       POSIX.1   позволяет   реализации   объявить   это   ограничение  через  константу  ARG_MAX
       (определённую в <limits.h> или сделать  её  доступной  во  время  выполнения  через  вызов
       sysconf(_SC_ARG_MAX)).

       Before  Linux  2.6.23,  the  memory used to store the environment and argument strings was
       limited to 32 pages (defined by the kernel constant MAX_ARG_PAGES).  On architectures with
       a 4-kB page size, this yields a maximum size of 128 kB.

       On  Linux  2.6.23 and later, most architectures support a size limit derived from the soft
       RLIMIT_STACK resource limit (see getrlimit(2))  that is  in  force  at  the  time  of  the
       execve()  call.  (Architectures with no memory management unit are excepted: they maintain
       the limit that was in effect before Linux 2.6.23.)  This change allows programs to have  a
       much  larger argument and/or environment list.  For these architectures, the total size is
       limited to 1/4 of the allowed stack size.  (Imposing the 1/4-limit ensures  that  the  new
       program  always  has some stack space.)  Additionally, the total size is limited to 3/4 of
       the value of the kernel constant _STK_LIM (8 MiB).  Since Linux 2.6.25,  the  kernel  also
       places a floor of 32 pages on this size limit, so that, even when RLIMIT_STACK is set very
       low, applications are guaranteed to have at least as much argument and  environment  space
       as  was  provided  by Linux 2.6.22 and earlier.  (This guarantee was not provided in Linux
       2.6.23 and 2.6.24.)  Additionally, the limit per string is 32 pages (the  kernel  constant
       MAX_ARG_STRLEN), and the maximum number of strings is 0x7FFFFFFF.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       On  success,  execve()   does  not  return,  on  error -1 is returned, and errno is set to
       indicate the error.

ОШИБКИ

       E2BIG  Слишком большое общее количество байт для  окружения  (envp)  и  списка  параметров
              (argv).

       EACCES В  одном  из  каталогов  префикса  pathname  или  интерпретатора  не разрешён поиск
              (смотрите также path_resolution(7)).

       EACCES Файл или интерпретатор не являются обычным файлом.

       EACCES Не установлен бит выполнения на файле или сценарии или интерпретаторе ELF.

       EACCES Файловая система смонтирована с noexec.

       EAGAIN (начиная с Linux 3.1)
              Having changed its real UID using one of the set*uid()  calls, the  caller  was—and
              is  now still—above its RLIMIT_NPROC resource limit (see setrlimit(2)).  For a more
              detailed explanation of this error, see NOTES.

       EFAULT Значение pathname или один из указателей в векторах  argv  или  envp  указывает  за
              пределы доступного адресного пространства.

       EINVAL Исполняемый  ELF-файл содержит более одного сегмента PT_INTERP (т.е., в нём указано
              более одного интерпретатора).

       EIO    Произошла ошибка ввода-вывода.

       EISDIR Интерпретатор ELF является каталогом.

       ELIBBAD
              Не распознан формат интерпретатора ELF.

       ELOOP  Во время определения pathname, имени сценария или  интерпретатора  ELF  встретилось
              слишком много символьных ссылок.

       ELOOP  Достигнут   предел   количества   рекурсий  при  интерпретации  сценария  (смотрите
              «Интерпретируемые сценарии» выше). До  Linux  3.8  для  этого  случая  возвращалась
              ошибка ENOEXEC.

       EMFILE Было  достигнуто  ограничение  по  количеству  открытых  файловых  дескрипторов  на
              процесс.

       ENAMETOOLONG
              Слишком длинное значение аргумента pathname.

       ENFILE Достигнуто максимальное количество открытых файлов в системе.

       ENOENT The file pathname or a script or ELF interpreter does not exist.

       ENOEXEC
              Не распознан формат исполняемого файла, он не подходит для архитектуры,  или  имеет
              ошибки в формате, из-за чего не может быть выполнен.

       ENOMEM Недостаточное количество памяти ядра.

       ENOTDIR
              Компонент  пути  в  pathname, сценарии или интерпретаторе ELF в действительности не
              является каталогом.

       EPERM  Файловая   система   смонтирована    с    nosuid,    пользователь    не    является
              суперпользователем, а на файле установлен бит set-user-ID или set-group-ID.

       EPERM  Над    процессом    выполняется    трассировка,    пользователь   не   имеет   прав
              суперпользователя, а у файла установлен бит set-user-ID или set-group-ID.

       EPERM  Приложение «с недоработанными мандатами» (capability-dumb) не  получило  бы  полный
              набор   ограничивающих   мандатов,   разрешаемых   исполняемым   файлом.   Смотрите
              capabilities(7).

       ETXTBSY
              Заданный исполняемый файл был открыт на запись одним или более процессов.

СТАНДАРТЫ

       POSIX.1-2001, POSIX.1-2008, SVr4,  4.3BSD.  В  POSIX  не  описано  поведение  #!,  но  это
       существует (в нескольких вариантах) в других системах UNIX.

ЗАМЕЧАНИЯ

       Иногда,  про execve() (и подобные функции, описанные в exec(3)) говорят, что он «выполняет
       новый процесс». Это крайне некорректная фраза  —  не  появляется  нового  процесса;  много
       атрибутов  вызывающего  процесса  остаются  неизменными  (в  частности, его PID). Всё, что
       делает  execve(2),  это  перестраивает  существующий  процесс  (вызывавший  процесс)   под
       выполнение новой программы.

       Над процессами с установленными set-user-ID и set-group-ID не может выполняться ptrace(2).

       Результат  работы  при  монтировании  файловой  системы  с параметром nosuid различается в
       разных версиях ядра Linux: некоторые будут  отказывать  в  запуске  исполняемых  файлов  с
       установленными  битами  set-user-ID  и  set-group-ID, если это дало бы пользователю больше
       прав чем уже есть (и возвращать EPERM), другие просто  проигнорируют  биты  set-user-ID  и
       set-group-ID и успешно выполнят exec().

       В  Linux  значения argv и envp могут быть равны NULL. В обоих случаях, это работает также,
       как если аргумент бы содержал указатель на  список  с  единственным  указателем  null.  Не
       пользуйтесь  преимуществом  данной  нестандартной  и  непереносимой возможностью! В многих
       других системах UNIX указание argv равным  NULL  приводит  к  ошибке  (EFAULT).  Некоторые
       другие системы UNIX при envp==NULL работают также как Linux.

       В  POSIX.1 указано, что значения, возвращаемые sysconf(3), должны быть неизменны в течении
       существования процесса. Однако, начиная с версии Linux 2.6.23, если изменяется ограничение
       ресурса  RLIMIT_STACK,  то  значение,  возвращаемое для _SC_ARG_MAX, также будет изменено,
       чтобы отразить, что ограничение на пространство для хранения параметров командной строки и
       окружения было изменено.

       In most cases where execve()  fails, control returns to the original executable image, and
       the caller of execve()  can then handle the error.  However, in  (rare)  cases  (typically
       caused  by  resource  exhaustion),  failure  may  occur  past  the point of no return: the
       original executable image has been torn down, but the new image could  not  be  completely
       built.   In  such  cases, the kernel kills the process with a SIGSEGV (SIGKILL until Linux
       3.17)  signal.

   Интерпретируемые сценарии
       Ядро накладывает ограничение на максимальную длину текста после  символов  «#!»  в  начале
       сценария;  символы  за  пределами границ игнорируются. До Linux 5.1 было ограничение в 127
       символов. Начиная с Linux 5.1 ограничение установлено в 255 символов.

       Семантика  необязательного  параметра   интерпретатора   сценариев   различна   в   разных
       реализациях.  В Linux, вся строка после имени интерпретатора передаётся интерпретатору как
       единый параметр, и эта строка может содержать пробельные символы. Однако, такое  поведение
       отличается  от  других  систем.  Некоторые  системы  используют  первый  пробел в качестве
       признака окончания необязательного параметра. В других системах,  интерпретатор  сценариев
       может иметь несколько параметров, и пробелы в необязательном параметре используются для их
       разграничения.

       На файлах со сценариями в Linux (как  и  большинстве  других  современных  системах  UNIX)
       игнорируются биты set-user-ID и set-group-ID.

   execve() и EAGAIN
       Это  более  подробное объяснение ошибки EAGAIN, которая возвращается (начиная с Linux 3.1)
       при вызове execve().

       The  EAGAIN  error  can  occur  when  a  preceding  call  to  setuid(2),  setreuid(2),  or
       setresuid(2)  caused the real user ID of the process to change, and that change caused the
       process to exceed its RLIMIT_NPROC resource limit (i.e., the number of processes belonging
       to  the  new  real  UID  exceeds the resource limit).  From Linux 2.6.0 to Linux 3.0, this
       caused the set*uid()  call to fail.  (Before Linux 2.6, the resource limit was not imposed
       on processes that changed their user IDs.)

       Since Linux 3.1, the scenario just described no longer causes the set*uid()  call to fail,
       because it too often led to security holes  where  buggy  applications  didn't  check  the
       return  status  and  assumed  that—if the caller had root privileges—the call would always
       succeed.  Instead, the set*uid()  calls now successfully change  the  real  UID,  but  the
       kernel  sets  an  internal  flag,  named  PF_NPROC_EXCEEDED, to note that the RLIMIT_NPROC
       resource limit has been exceeded.  If the PF_NPROC_EXCEEDED flag is set and  the  resource
       limit  is  still exceeded at the time of a subsequent execve()  call, that call fails with
       the error EAGAIN.  This kernel logic ensures that the RLIMIT_NPROC resource limit is still
       enforced  for  the  common  privileged  daemon  workflow—namely,  fork(2)   + set*uid()  +
       execve().

       Если ограничитель ресурса был не превышен  на  момент  вызова  execve()  (так  как  другие
       процессы,  принадлежащие  этому  реальному  UID завершили работу между вызовом set*uid() и
       execve()), то вызов execve() выполнится успешно и ядро очистит  флаг  PF_NPROC_EXCEEDED  у
       процесса. Флаг также очищается, если при успешном выполнении процессом последующего вызова
       fork(2).

   Историческая справка
       В UNIX V6 список аргументов  вызова  exec()  заканчивался  0,  а  список  аргументов  main
       заканчивался  -1.  Поэтому,  этот  список  аргументов  не  мог быть использован напрямую в
       последующем вызове exec(). Начиная с UNIX V7 оба списка стали оканчиваться NULL.

ПРИМЕРЫ

       Данная программа запускается второй программой, представленной ниже.  Она  просто  выводит
       свои параметры командной строки по одному на строку.

           /* myecho.c */

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

           int
           main(int argc, char *argv[])
           {
               for (size_t j = 0; j < argc; j++)
                   printf("argv[%zu]: %s\n", j, argv[j]);

               exit(EXIT_SUCCESS);
           }

       Эта  программа  может  использоваться  для  запуска программы, чьё имя указано в параметре
       командной строки.

           /* execve.c */

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

           int
           main(int argc, char *argv[])
           {
               static char *newargv[] = { NULL, "hello", "world", NULL };
               static char *newenviron[] = { NULL };

               if (argc != 2) {
                   fprintf(stderr, "Использование: %s <file-to-exec>\n", argv[0]);
                   exit(EXIT_FAILURE);
               }

               newargv[0] = argv[1];

               execve(argv[1], newargv, newenviron);
               perror("execve");   /* execve() возвращается только при ошибке */
               exit(EXIT_FAILURE);
           }

       Мы можем использовать вторую программу для запуска первой:

           $ cc myecho.c -o myecho
           $ cc execve.c -o execve
           $ ./execve ./myecho
           argv[0]: ./myecho
           argv[1]: hello
           argv[2]: world

       Также мы можем использовать эти программы для  демонстрации  использования  интерпретатора
       сценариев.  Для  этого  создадим сценарий, чей "интерпретатор" указывает на нашу программу
       myecho:

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

       Теперь мы можем использовать нашу программу для запуска сценария:

           $ ./execve ./script
           argv[0]: ./myecho
           argv[1]: script-arg
           argv[2]: ./script
           argv[3]: hello
           argv[4]: world

СМ. ТАКЖЕ

       chmod(2),  execveat(2),  fork(2),  get_robust_list(2),  ptrace(2),  exec(3),   fexecve(3),
       getauxval(3),   getopt(3),   system(3),   capabilities(7),   credentials(7),   environ(7),
       path_resolution(7), ld.so(8)

ПЕРЕВОД

       Русский   перевод   этой    страницы    руководства    был    сделан    Azamat    Hackimov
       <azamat.hackimov@gmail.com>,    Yuri    Kozlov    <yuray@komyakino.ru>   и   Иван   Павлов
       <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если вы обнаружите ошибки в переводе  этой  страницы  руководства,  пожалуйста,  отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.