반응형

execvp(3)

#include <unistd.h>

int execvp(const char *file, char *const argv[]);

execve(2)함수의 wrapping함수로 실행가능한 파일인 file의 실행코드를 현재 프로세스에 적재하여 기존의 실행코드와 교체하여 새로운 기능으로 실행합니다. 즉, 현재 실행되는 프로그램의 기능은 없어지고 file 프로그램을 메모리에 loading하여 처음부터 실행합니다. file은 명령어 또는 실행가능 한 파일로 환경변수 PATH에 디렉토리가 포함되어 있으면, 명령어만 설정가능합니다. 환경변수는 현재 프로세스의 환경변수를 그대로 상속받습니다.

 

이 함수는 $PATH의 순서에 의해서 실행할 프로그램이 변경될 수 있어서 보안 취약함수로 분류됩니다.

 

상세내용은 execve(2)를 참조하세요.

 

 

파라미터

file
    - 명령어 또는 실행가능한 파일. 
    - 환경변수 PATH에 설정된 디렉토리면 파일명만 그렇지 않으면, 절대 또는 상대 path의 실행파일
      (ex. ls 또는 /usr/bin/ls)
argv
    - c언어의 main(int argc, char *argv[])에서 argv와 비슷하며, main함수에는 argc가 있지만 
      execve에는 argc가 없으므로 main의 argv에 마지막 array 다음에 NULL을 하나 더 넣어야 합니다.

 

RETURN

없음
    - 정상적으로 처리되면 execv(3) 다음 로직은 실행할 수 없습니다. 
      왜냐하면 이미 다른 프로그램이 되었기 때문입니다.

-1
     - binary 교체가 실패하였으며, 상세한 오류 내용은 errno 전역변수에 설정됩니다.

 E2BIG : argv 또는 envp list가 너무 많습니다.
 EACCES : file의 디렉토리에 구성에 search권한이 없거나 
             file파일이 실행권한이 없거나 파일이 실행할 수 없는 파일입니다.
             또는 파일 시스템이 마운트되지 않았습니다.
 EFAULT : file이라는 변수가 access할 수 없는 메모리 영역입니다.
 EINVAL : ELF 실행파일이 하나이상의 PT_INTERP segment를 가진 경우
 EIO : I/O 오류가 발생하였습니다.
 EISDIR : file이 디렉토리입니다.
 ELIBBAD : ELF가 인식할 수 없는 format입니다.
 ELOOP : 너무 많은 symbolic link depth입니다.
 EMFILE : 프로세스가 열 수 있는 최대 갯수의 file을 open하였습니다.
 ENAMETOOLONG : path의 문자열의 파일명이 너무 길거나 디렉토리가 너무 깁니다.
 ENFILE : 시스템에서 열 수 있는 최대 갯수의 파일이 열렸습니다.
 ENOENT : file이 존재하지 않는 파일입니다.
 ENOEXEC : file이 실행할 수 없는 format입니다.
 ENOMEM : kernel이 사용할 수 있는 메모리가 부족합니다.
 ENOTDIR : file을 구성하는 디렉토리가 디렉토리가 아닙니다.
 EPERM : 파일시스템이 nosuid로 마운트되었으며, user가 superuser가 아니고 
             file이 set-user-ID, set-group-ID bit가 설정안됨
 ETXTBSY : 다른 프로세스에 의해서 쓰기를 위해 open된 경우

 


활용 예제

 

Sample). sample1.c : ls 명령어로 치환

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

int main(int argc, char *argv[])
{
    char **new_argv;
    char command[]  = "ls";
    int  idx;

    new_argv = (char **)malloc(sizeof(char *) * (argc + 1));

    /* 명령어를 ls로 변경 */
    new_argv[0] = command;

    /* command line으로 넘어온 parameter를 그대로 사용 */
    for(idx = 1; idx < argc; idx++) {
        new_argv[idx] = argv[idx];
    }
 
    /* argc를 execve 파라미터에 전달할 수 없기 때문에 NULL이 파라미터의 끝을 의미함 */
    new_argv[argc] = NULL;

    if(execvp("ls", new_argv) == -1) {
        fprintf(stderr, "프로그램 실행 error: %s\n", strerror(errno));
        return 1;
    }

    /* ls 명령어 binary로 실행로직이 교체되었으므로 이후의 로직은 절대 실행되지 않습니다. */
    printf("이곳이 이제 ls 명령어라 이 라인은 출력이 되지 않습니다.\n");
    
    return 0;
}

--------------------------------------------------------------
실행방법
sample1 -al <enter>
결과는 ls -al 한 것과 같음.

 


see also: Process 관리 함수 

 

 

 

반응형
블로그 이미지

자연&사람

행복한 개발자 programmer since 1995.

,