进程的uid和euid

一 进程的uid和euid

转自:http://bbs.linuxpk.com/thread-39597-1-1.html

linux系统中每个进程都有2个ID,分别为用户ID(uid)和有效用户ID(euid),UID一般表示进程的创建者(属于哪个用户创建),而EUID表示进程对于文件和资源的访问权限(具备等同于哪个用户的权限)。C语言中,可以通过函数getuid()和geteuid()来获得进程的两个ID值。

当一个用户登陆系统时,系统会将UID和EUID都赋值为/etc/passwd文件中的UID,一般情况下2个ID是相同的,但是某些情况下会出现2个ID不同的情况。
gid和egid同理。

下面一段C代码将解释区别:"printid.c"

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

int main(void)
{
    printf(" UID\t= %d\n", getuid());
    printf(" EUID\t= %d\n", geteuid());
    printf(" GID\t= %d\n", getgid());
    printf(" EGID\t= %d\n", getegid());

    return EXIT_SUCCESS;
}

编译之:
aguo@linux-x9rc:~> gcc -o printid printid.c

执行:
aguo@linux-x9rc:~> ./printid
Real UID        = 1000
Effective UID        = 1000
Real GID        = 100
Effective GID        = 100

看看/etc/passwd里uid和gid:
aguo@linux-x9rc:~> cat /etc/passwd | grep aguo | awk -F":" '{print "uid:"$3 "\tgid:"$4}'
uid:1000        gid:100

以上是相同的例子。

下面演示uid和euid不同的例子。
首先,修改一下文件属性,setuid或setgid
aguo@linux-x9rc:~> chmod u+s printid #这样一来,文件在执行阶段具有文件所有者的权限。
还可以再补充一个:
aguo@linux-x9rc:~> chmod g+s printid #这样一来,文件在执行阶段具有文件所属组的权限。

其次,变成其他用户,再来试验一下,比如变成root;
linux-x9rc:/home/aguo # ./printid
Real UID        = 0
Effective UID        = 1000
Real GID        = 0
Effective GID        = 100

看到了吧?uid和euid是有区别的!
以上演示环境:
OS:SuSE Desktop Linux 11
gcc:4.3.2

顺便补充一下:
perl里面的特殊变量$<、$>表示uid euid; $(、$)表示gid egid。
只是,$(和$)会存储一个列表,第一位表示的才是gid和egid,这个是perl的设置,不在本文讨论范围中。

二 passwd 实例

转自:http://keren.blog.51cto.com/720558/144908 

【关于linux的passwd命令】
passwd命令是用来修改用户登陆密码的,用来记录用户登陆密码的文件为/etc/shadow,该文件只有root用户具有访问权限,如下所示:
gaolu@gaolu-desktop:~$
gaolu@gaolu-desktop:~$ cd /etc
gaolu@gaolu-desktop:/etc$ ls -l shadow
-rw-r----- 1 root shadow 978 2009-02-22 21:25 shadow
gaolu@gaolu-desktop:/etc$

这是出现了矛盾:出于安全考虑,不允许普通用户查看并修改shadow文件;但是如果这样普通用户就无法为自己修改密码。

Linux系统就是使用setuid来解决这个矛盾的问题:如果一个程序被设置了setuid位,那么它无论被哪个用户启用,都会具备程序所有者的权限。而passwd程序的所有者是root用户,passwd的权限如下所示,那么任何用户执行该程序,程序的EUID就会变成root用户的EUID,而不是执行该程序的UID。

gaolu@gaolu-desktop:/etc$ cd /usr/bin
gaolu@gaolu-desktop:/usr/bin$ ls -l passwd
-rwsr-xr-x 1 root root 32988 2008-06-10 02:10 passwd
gaolu@gaolu-desktop:/usr/bin$
gaolu@gaolu-desktop:/usr/bin$

因此,普通用户可以通过passwd程序修改shadow文件内容,完成密码修改。
 
 
一个系统启动后,用户login登录后,会产生一个用户进程,该进程和其它进程一样有7个id值:实际用户id,有效用户id,保存的set-user-id,实际组id,有效组id,添加组id以及保存的set-group-id.

  这里只说uid,这三个id都来自登录名。

  至此我们有了一个用户shell进程,当执行程序时,通常由fork+exec函数来做。由用户进程fork出来的子进程将继承父进程的uid,euid。子进程再调用exec(),这时,若程序的set-user-id没有被置位,那么这个子进程的uid,euid保持不变,而保存的set-user-id从euid复制。如果程序的set-user-id被置位了,那么子进程的实际uid保持不变,euid设置位程序文件的uid,set-user-id从euid复制。程序的set-user-id只能由所有者去置位,特权用户可以置位所有的程序。

  下面以apue上的例子access.c来说明一下set-user-id的作用。

#include
#include
#include "ourhdr.h"

int
main(int argc, char *argv[])
{
if (argc != 2)
err_quit("usage: a.out ");

if (access(argv[1], R_OK) < 0)
err_ret("access error for %s", argv[1]);
else
printf("read access OK\n");

if (open(argv[1], O_RDONLY) < 0)
err_ret("open error for %s", argv[1]);
else
printf("open for reading OK\n");

exit(0);
}

  假定该源文件是以renshui身份创建的。

  那么我们执行程序后,进程的

uid=renshui
euid=renshui
set-user-id=renshui

  如果我们为程序传入的参数是该源文件access.c

  则access函数可以读该文件,因为进程的uid等于文件的所有者id

  open函数也可以读该文件,因为进程的euid等于文件的所有者id

  如果我们为程序传入的参数是 /etc/shadow

  该文件的mode为

  -r-------- 1 root root 1325 03-16 18:29 /etc/shadow

  也就是说只有root可以去读。

  我们用普通登录名去执行access程序,则无论是access还是open都无法读该/etc/shadow文件。

  我们切换到超级用户

  $ su 成为超级用户
  # chown root access 将文件用户id改为root
  # chmod u+s access 打开set-user-id
  # exit 恢复为正常用户

  我们再去执行access去访问/etc/shadow,则该进程的

  uid=renshui
  euid=root
  set-user-id=root

  用access尝试去读仍然不可以,因为内核是以进程的uid执行访问权限测试的。用open去读就可以了,因为内核是以进程的euid执行访问权限测试的,这时euid等于/etc/shadow的所有者root。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值