open中的 O_CLOEXEC 标志

含义:在进程执行exec系统调用时关闭此打开的文件描述符。在子进程没有相应权限的情况下,防止父进程将打开的文件描述符泄露给子进程,防止子进程间接获得权限。

fd泄露引起普通用户访问无权限的文件:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>

int main()
{
    int count;
    pid_t pid;
    char buf[1024] = {0};
    int fd;

    //以root身份打开文件
    fd = open("/etc/shadow", O_RDONLY);
    if( fd < 0 )
    {
	    perror("open /etc/shadow");
	    return -1;
    }

	pid = fork();
	if( 0 == pid )
	{
        seteuid(500);
        setegid(500);
        //fd是从父进程泄露出来,不受权限制约,可以读取文件
        printf("EUID:%d, UID:%d\n", geteuid(), getuid());
        while( (count = read(fd, buf, sizeof(buf))) > 0 )
        {
	        write(STDOUT_FILENO, buf, count);
        }
        
        close(fd);

        //普通用户! 无法打开文件
        fd = open("/etc/shadow", O_RDONLY);
        printf("fd=%d\n", fd);

        if( fd<0 )
        {            
            perror("open /etc/shadow");
            return -1;
        }
        return 0;
    }

    close(fd);
    return 0;
}

设置O_CLOEXEC一般是在open时设置,这个是原子操作;也可以用fcntl()的F_SETFD命令来设置,但它有并发危险,如多线程中,一个线程将要设置O_CLOEXEC标志时,虽一个线程fork(),且先得到执行,导致打开的文件描述符泄露到子进程中。

猜你喜欢

转载自blog.csdn.net/konga/article/details/39062691