最近在看APUE,看到3.14节,fcntl的时候
#include <fcntl.h>
int fcntl(int fd, int cmd, .../* int arg */);
出错返回-1,具体返回值依赖于cmd参数。
其中提到一个CMD,FD_GETFD FD_SETFD所返回的文件描述符标志FD_CLOEXEC(当前的文件描述符标志只有这一个)
最8.10节 函数子进程调用exec是对打开文件的处理。
对于fork一个进程,子进程与父进程共享一些数据,包裹已打开的文件描述符(子进程复制了所有父进程打开的文件描述符)
fork后,经常地,会调用exec程序,执行另外的一些任务,将子进程的正文段、数据段、堆、栈等替换为新的程序内容。此时,若设置了FD_CLOEXEC标志,子进程对父进程的文件描述符副本,被关闭。否则,将不关闭。
默认情况下,子进程调用exec并不关闭这些文件描述符副本,除非显式地用fcntl(fd,FD_SETFL,1)进行设置。
对于目录流,POSIX.1明确要求将此标志设置为1,通常,由opendir函数调用fcntl实现。
4.14节:
与一个进程关联的ID有6个。
real uid/real gid < login时从登录文件取出,显然,你用什么用户登录系统,实际用户就是谁。
effective uid/effective gid/supplementary group IDs.
saved set-user-ID/saved set-group-ID 被exec函数保存的saved set-user-ID/saved set-group-ID。
当一个程序被加载到内存执行的时候,通常用的是exec函数中的一个。
通常情况下,real uid与effective uid是相同的,你以什么身份执行一个程序,这个进程就属于谁这个相当容易理解。
但是:当 set-user-ID位被设置,也就是文件权限位第三位是s的时候,exec将会:把进程的effective user id 设置为 文件所有者ID。
这个时候,如果不属于当前用户的文件被执行,其effective user id = 文件所有者ID。
同时,exec还会将此文件所有者ID进行保存,所以,才叫 saved set-user-id;
那么,当执行一个具有set-user-id位的程序的时候,进程的real user id 与 effective user id 是不一定相同的。
我们可以用一个小程序来验证是否属实。
这个程序打印 程序运行时候的 real user ID与effective user ID。
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
puts("I am child process");
printf("userId=%d,euserId=%d\n",getuid(),geteuid());
return 0;
}
同时将其权限设置为 -rwsr-xr-x 中的's'就是saved-user-Id,当执行此程序时将以超级用户权限执行。要想验证很简单。
编译后执行他。获得输出:
I am child process
userId=500,euserId=0
-----------
同时,我们可以在程序中调用 int setuid (uid_t newuid) 函数来更改进程的real user id, effective user id;
但是我们必须明白:
1、只有root进程可以更改 real user id , saved set-user-id。
2、当root进程调用setuid函数时 real user id , effective user id , saved-user-id 都被设置为newuid;
3、如果一个不具有root权限的进程试图调用此函数,会出现什么呢?
如果 newuid == real user id or newuid == saved set-user-id
那么进程的 uid = newuid。
不然,出错。
同时,任何时候,进程都可以用setuid函数将,进程UID设置为:real user id 或者 saved set-user-id;
我们可以用 getuid() geteuid() 函数获取 real user id 和 effective user id,但我们无法用函数获得 save set-user-id;