linux进程标识符详解1

每个进程都有一个实际用户标识符和一个实际组标识符,它们永远是启动该进程之用户的用户标识符和组标识符。

进程有效用户标识符有效组标识符也许更重要些,它们被用来确定一个用户能否访问某个确定的文件。在通常情况下,它们与实际用户标识符和实际组标识符是一致的。

有几个系统调用可以用来得到进程的用户标识符和组标识符,详见下列程序:

/* 取进程的实际用户标识符 */

uid=getuid();

/* 取进程的有效用户标识符 */

euid=geteuid();

/* 取进程的实际组标识符 */

gid=getgid();

/* 取进程的有效组标识符 */

egid=getegid();

另外,还有两个系统调用可以用来设置进程的有效用户标识符和有效组标识符,它们的使用格式如下:

/* 设定进程的有效用户标识符 */

status=setuid(newuid);

/* 设定进程的有效组标识符 */

status=setgid(newid)

通过这两个系统调用,进程可以改变自己的标识符,进而改变自己的权限(因为Linux中权限是通过标识符来判断的)。比如一个root 建立的进程可以用这种方法放弃一部分的root 权限而只保留工作所需的权限。这样可以提高系统的安全性。

<span style="font-size:14px;">#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>

int main(int argc,char* argv[])
{
	int fd;
	fd = fork();
	switch(fd){
		case -1:{
			perror("fork");
			exit(-1);
		}
		break;
		case  0:
		{  //开始进程用户id和有效用户id
			printf("uid=%d,euid=%d\n",getuid(),geteuid());

			//设置用户id为1000,改变用户权限
			setuid(1000);

			//改变后的用户id和有效用户id
			printf("uid=%d,euid=%d\n",getuid(),geteuid());

			//root用户才能查看shadow文件,测试权限是否改变
			execlp("cat","cat","/etc/shadow",NULL);
		}
		break;
		default:
		{ //开始进程用户id和有效用户id
			printf("uid=%d,euid=%d\n",getuid(),geteuid());
			//root用户才能查看shadow文件
			execlp("cat","cat","/etc/shadow",NULL);
		}
		break;
	}

	return 0;
}
</span>

在root权限下运行结果:

[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

cat: /etc/shadow: 权限不够

uid=0,euid=0

root:$$MG0tTs8yWCPoKMrG$tVrZQKQ6IK52ucaSGfHIMKdVHB7zP.rpqD5GO/1w07eYQj0Jgue9S/UijUtyYYQa9Irm2vwj7r.DwaY.5IXIp0:15195:0:99999:7:::

bin:*:14789:0:99999:7:::

但是需要注意的是,一旦root 进程通过这种方式放弃了root 特权,将无法再通过setuid()调用的方式重新获得root权,因为一个非root 标识符的进程是无法设定root 标识符的。这时可以使用Linux 的另外两个系统调用seteuid()和setegid()。其调用方式和前两个完全相同。但是它们是根据进程程序文件的标识符来判断设定的。因此,一个root 的程序文件在任何时候都可以将自己重新seteuid()为root。

<span style="font-size:14px;">#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>

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

	//开始进程用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置用户id为1000,改变用户权限
	setuid(1000);

	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置用户id为0,改变用户权限为root
	if(-1 == setuid(0)){
		perror("setuid to root");
		exit(-1);
	}
	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	return 0;
}
</span>

root下运行结果:

[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

setuid to root: Operation not permitted

<span style="font-size:14px;">#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>

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

	//开始进程用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置用户id为1000,改变用户权限
	setuid(1000);

	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置用户id为1000,改变用户权限为自己
	if(-1 == setuid(1000)){
		perror("setuid to root");
		exit(-1);
	}
	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	return 0;
}</span>

运行结果:

以上例子说明不是超级用户所引用的进程,只能把它的有效用户表示符和有效组标识符重新设置成其实际用户标识符和实际组标识符。超级用户所引用的进程就可以自由进行其有效用户标识符和有效组标识符的设置。

以上使用setuid()永久改变权限,现在使用seteuid()暂时改变用户权限:

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

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

	//开始进程用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置有效用户id为1000,暂时改变用户权限
	seteuid(1000);

	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	//设置有效用户id为0,改变用户权限为自己
	if(-1 == setuid(0)){
		perror("setuid to root");
		exit(-1);
	}
	//改变后的用户id和有效用户id
	printf("uid=%d,euid=%d\n",getuid(),geteuid());

	return 0;
}

运行结果:

#./a.out

uid=0,euid=0

uid=0,euid=1000

uid=0,euid=0

[[email protected] file]# ./a.out

uid=0,euid=0

uid=0,euid=1000

uid=0,euid=0[[email protected]
file]# ./a.out

uid=0,euid=0

uid=0,euid=1000

uid=0,euid=0

[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

uid=1000,euid=1000[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

uid=1000,euid=1000[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

uid=1000,euid=1000[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

uid=1000,euid=1000[[email protected] file]# ./a.out

uid=0,euid=0

uid=1000,euid=1000

uid=1000,euid=1000

linux进程标识符详解1

时间: 2024-10-11 04:25:27

linux进程标识符详解1的相关文章

linux进程地址空间详解(转载)

linux进程地址空间详解(转载) 在前面的<对一个程序在内存中的分析 >中很好的描述了程序在内存中的布局,这里对这个结果做些总结和实验验证.下面以Linux为例(实验结果显示windows上的结果也一样). 我们还是利用前面看到过的这个图,如下图:32位X86机器的内存布局图,内存主要分为栈.堆.BSS段.数据段.代码段5个段.   代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域.这部分区域的大小在程序运行前就已经确定,并且内存

Linux进程退出详解(do_exit)--Linux进程的管理与调度(十四))

日期 内核版本 架构 作者 GitHub CSDN 2016-05-12 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度 Linux进程的退出 linux下进程退出的方式 正常退出 从main函数返回return 调用exit 调用_exit 异常退出 调用abort 由信号终止 _exit, exit和_Exit的区别和联系 _exit是linux系统调用,关闭所有文件描述符,然后退出进程. exit是c语言的库函数,他最

Linux进程退出详解(do_exit)--Linux进程的管理与调度(十四)

Linux进程的退出 linux下进程退出的方式 正常退出 从main函数返回return 调用exit 调用_exit 异常退出 调用abort 由信号终止 _exit, exit和_Exit的区别和联系 _exit是linux系统调用,关闭所有文件描述符,然后退出进程. exit是c语言的库函数,他最终调用_exit.在此之前,先清洗标准输出的缓存,调用用atexit注册的函数等, 在c语言的main函数中调用return就等价于调用exit. _Exit是c语言的库函数,自c99后加入,等

LINUX 信号概念详解

LINUX 信号概念详解 我们运行如下命令,可看到Linux支持的信号列表: # kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD 18) SIGCONT 19) SIGSTOP

Linux netstat命令详解

Linux netstat命令详解 简介 Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicast Memberships) 等等. 输出信息含义 执行netstat后,其输出结果为 Active Internet connections (w/o servers)Proto Recv-Q Send-Q Local Address Foreign Address State

红帽Linux故障定位技术详解与实例(2)

红帽Linux故障定位技术详解与实例(2) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍然可以访问,故障处理人员可通过console, ssh等方式登录到操作系统上,在shell上执行各种操作命令或测试程序的方式对故障环境进行观察,分析,测试,以定位出故障发生的原因. AD:2014WOT全球软件技术峰会北京站 课程视频发布 3.内核故障情形及处理 (1)内核panic panic是内

红帽Linux故障定位技术详解与实例(1)

红帽Linux故障定位技术详解与实例(1) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍然可以访问,故障处理人员可通过console, ssh等方式登录到操作系统上,在shell上执行各种操作命令或测试程序的方式对故障环境进行观察,分析,测试,以定位出故障发生的原因. AD:2014WOT全球软件技术峰会北京站 课程视频发布 红帽Linux故障定位技术详解与实例是本文要介绍的内容,主要

Linux系统启动过程详解

 Linux系统启动过程详解 启动第一步--加载BIOS当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬盘信息.内存信息.时钟信息.PnP特性等等.在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了. 启动第二步--读取MBR众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,

linux screen 命令详解

linux screen 命令详解 一.背景 系统管理员经常需要SSH 或者telent 远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份.ftp 传输等等.通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为它们执行的时间太长了.必须等待它们执行完毕,在此期间不能关掉窗口或者断开连接,否则这个任务就会被杀掉,一切半途而废了. 二.简介 GNU Screen是一款由GNU计划开发的用于命令行终端切换的自由软件.用户可以通过该软件同时连接多个本地或远程的命