linux setuid函数_setuid函数解析

在讨论这个setuid函数之前,我们首先要了解的一个东西就是内核为每个进程维护的三个UID值。这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user-ID)。

首先说这个实际用户ID,就是我们当前以哪个用户登录了,我们运行的程序的实际用户ID就是这个用户的ID。有效用户ID就是当前进程是以哪个用户ID来运行的,一般情况下是实际用户ID,如果可执行文件具有了SUID权限,那么它的有效用户ID就是可执行文件的拥有者。保存的设置用户ID就是有效用户ID的一个副本,与SUID权限有关。

关于那个SUID,最经典的例子莫过于passwd命令。passwd这个可执行文件的所有者是root,但是其他用户对于它也有执行权限,并且它自身具有SUID权限。那么当其他用户来执行passwd这个可执行文件的时候,产生的进程的就是以root用户的ID来运行的。如下图所示:

3661dbab082d6a865debd69cf6575a42.png

这个passwd的所有者是root,并且在权限那一栏中s代表的是SUID权限。我以普通用户michael来运行这个命令,产生的进程如下:

2ff2087c000aaed9ba9c8a735b04c89a.png

大家可以看到,倒数第二行这个进程其命令是passwd,但是其USER却是root。这就是SUID权限。

接下来,我们开始扯正题,setuid函数。这是setuid函数的声明和返回值:

c89b5720875d1a9fa672f7bdbe7856da.png

955f34b9fd3458cd2e99da62677b411d.png

如果成功返回0,如果失败返回-1,并将errno设置为合适的值。

关于这个函数的功能,APUE(《UNIX环境高级编程》,下面的APUE为相同的意思,不再赘述)上面是这样写的:

1ccede8beb3987d6e779e543c50042d5.png

这样光讲概念可能有点干巴巴了,下面我来举几个分别说明一下:

开始讲之前,我先验证一下我的电脑是支持"保存的设置用户ID"这个功能的,在电脑上运行以下代码:

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #define BUFSIZE 512

8 void err_exit(char *fmt,...);9 int main(int argc,char *argv[])10 {11 if(sysconf(_SC_SAVED_IDS) > 0)12 printf("_POSIX_SAVED_IDS effective!\n");13

14 return 0;15 }

程序的运行结果如下:

8c2778412b2f7e710102888814b1fc7e.png

首先说一下我用到的用户,一共使用了三个用户,root(UID=0),michael(UID=500),xiaojie(UID=501)如下图所示:

5c3ce3a6bdec6537faa4f01870cd47f9.png

先讲第一点,如果进程具有超级用户特权,那么这三个UID都被设置成了uid(setuid函数的参数)的值。比如下面这段代码:

1 #include

2 #include

3 #include

4 int main(int argc,char *argv[])5 {6 uid_t ruid,euid,suid;7 //这三个uid分别是实际用户ID,有效用户ID,保存的设置用户ID

8

9 setuid(500);10 getresuid(&ruid,&euid,&suid);11 printf("real:%d\teffective:%d\tset-user-id:%d\n",ruid,euid,suid);12

13 return 0;14 }

我用root用户来运行这个程序,那么刚开始这个进程的有效用户ID为0,然后这个进程中调用setuid(500),这三个UID的值都会被设置成500(在程序中通过getresuid函数来获取进程的三个UID的值),运行结果如下图:

ea6b0b327419c5542c5d6a28d34ad0e8.png

接下来我们再来讨论第二种情况,如果函数的参数uid等于进程的实际用户ID或者保存的设置用户ID,那么就将有效用户ID设置为uid,其他的两个(实际用户ID和保存的设置用户ID)保持不变。比如下面这个程序:

1 #include

2 #include

3 #include

4 void err_exit(char *fmt,...);5 int main(int argc,char *argv[])6 {7 uid_t ruid,euid,suid;8

9 printf("Before:\n");10 if(-1 == getresuid(&ruid,&euid,&suid))11 err_exit("[getresuid]:");12 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);13 setuid(500);14 printf("After:\n");15 if(-1 == getresuid(&ruid,&euid,&suid))16 err_exit("[getresuid]:");17 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);18

19 return 0;20 }

关于这段代码生成的可执行文件,我让它的拥有者变成了xiaojie(UID=501),并且给它加上了SUID权限,如下图所示:

9869977e4b74891efbc66ad79f8e4bfe.png

然后我用michael用户(UID=500)来运行这个程序,那么这个程序的实际用户ID=500,而有效用户ID和保存的设置用户ID都为501。接着,在这个程序中调用setuid函数,传入的参数为500,大家可以猜想到,最终应该只有有效用户ID受到影响,而保存的设置用户ID保持不变。运行结果如下图所示:

a0690ee66b65ad86cb056627b22d42bf.png

这就符合了我们的预期,仅仅只有有效用户ID受到了影响,而实际用户ID和保存的设置用户ID并没有改变。(这里我仅仅是验证了保存的设置用户ID不受影响,大家也可以自己写一个程序,来验证实际用户ID并不受影响。)

最后一点,如果setuid函数的参数的uid的值即不等于实际用户ID,也不等于保存的设置用户ID,而且这个进程的有效用户ID也不是0(非特权进程)。那么这个程序就会出错,并将errno设置为EPERM。比如下面这个程序:

1 #include

2 #include

3 #include

4 #include

5 #include

6 int main(int argc,char *argv[])7 {8 uid_t ruid,euid,suid;9

10 getresuid(&ruid,&euid,&suid);11 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);12

13 if(-1 == setuid(500))14 {15 printf("%s\n",strerror(errno));16 if(errno ==EPERM)17 {18 printf("Error number is EPERM!\n");19 }20 }21 else

22 {23 getresuid(&ruid,&euid,&suid);24 printf("real:%d\teffective:%d\tset-user:%d\n",ruid,euid,suid);25 }26

27 return 0;28 }

我以xiaojie用户(UID=501)来运行这个程序,那么这个程序的三个用户ID都为501,然后在这个程序中,调用setuid(500)。于是程序就会报错,并将errno设置为EPERM,如下图所示:

e60151f4c059099d3ec7daf1ba91de84.png

OK,这就是APUE上关于setuid函数的解释,讲了这么多,综合成一句话就是,root是神,想怎么干就怎么干,没人管得了。而普通用户呢,只能管自己分内的事(把进程的有效ID改成自己的ID),不能胡乱来。

OK,that‘s all。希望这篇文章对大家能够有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中asl_带你认识绕不开的ASLR

微软从windows vista/windows server 2008(kernel version 6.0)开始采用ASLR技术,主要目的是为了防止缓冲区溢出ASLR技术会使PE文件每次加载到内存的起始地址随机变化,并且进程的栈和堆的起始地址也会随机改变。ASLR(Address space layout randomization…

java复杂性_java – 计算Big-O复杂性

我最终会给这个程序一个类似60,000个400像素图像的输入文件,所以我试着想一想这个代码如何用大输入运行.为了便于阅读,我用“blah”和所有带有简单字母(nn,mm和kk)的ArrayList名称替换了不重要的东西.for (Perceptron P : nn){//blah}for (Perceptron P : mm) {//blah}for (Per…

java泛型与接口_Java泛型用于方法,类和接口

什么是泛型?型就是数据类型参数化。就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了。使用的时候再确定就可以了。泛型的特点是JDK1.5的新特性泛型可…

unix系统编码 java_JAVA字符编码系列三:Java应用中的编码问题

这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记录下来以便日后参考。为了构成一个完整的对文字编码的认识和深入把握,以便处理在Java开发过程中遇到的各种问题,特别是乱码问题&#xff…

Java 捕获 mybatis异常_3 springboot集成mybatis和全局异常捕获

mybatis有两种方式,一种是基于XML,一种是基于注解springboot集成mybatis首先先创建表,这里都简化了DROP TABLE IF EXISTS user;CREATE TABLE user (id int(11) NOT NULL auto_increment,username varchar(255) default NULL,PRIMARY KEY (id)…

java背景图片加上组件_关于 java swing组件加背景图片的问题

最近自己做了一个小的进销存软件,背景图片加上后不能最大化。尝试了好几种方法 最后终于把问题解决了。下面把自己写的实例 分享一下:一个是在JFrame窗体中加如背景图片一个是在Jpanel 面板中加入背景图片都可以伸缩铺满整个屏幕,算是自己的一个小心得。…

java applet 访问文件_使用JavaApplet访问数据库

使用Java Applet访问数据库学习任何的程序语言,当然都得与数据库,Java刚刚诞生的时候,对数据库的支持并不是很好,经过这几年的发展,它对数据库的支持也已经完全达到了成熟的境地。由于这里主要是介绍Java Applet小程序…

java ip 范围内打卡_定位地理位置PHP判断员工打卡签到经纬度是否在打卡之内

具体代码如下所述:/* 计算两组经纬度坐标之间的距离* param $lat1 纬度1* param $lng1 经度1* param $lat2 纬度2* param $lng2 经度2* param int $len_type 返回值类型(1-m 2-km)* param int $decimal 保留小数位数* return float*/public function getDistance($l…

与java线程有关的,线程多少和什么有关?大神们表示有话要说!

原标题:线程多少和什么有关?大神们表示有话要说!来源:importnew.com/10780.htmlEddie的回答:Charlie Martin的回答:benjismith的回答:Neil Coffey的回答:McGovernTheory在StackOverflow提了这样一个问题:Java虚拟机最多支持多少个…

php正则表达式 匹配数字,正则表达式之匹配数字范围

最近有个需求就是根据产品编号批量下架产品,需要下架日期为16-31号之间的产品,比如编号为B201607280023匹配表达式如下:^201607(1[6-9]|2[0-9]|3[0-1]).逻辑很简单,如果是必须是1或2或3开头,如果是1开头则后面范围为6-9&#xff0…

php中带?错误,参考-此错误在PHP中意味着什么?

这是什么?这是有关警告,错误和注意事项的许多答案,这些警告,错误和注意事项在您对PHP进行编程时可能会遇到,并且不知道如何解决它们。这也是一个社区Wiki,因此邀请所有人参与添加并维护此列表。为什么是这样…

yiilite.php,YII Framework学习教程-YII的V-view的render若干函数-2011-11-17 | 学步园

YII中,在action可以通过$this->render来指定它的view。其实还其他一$this->render开头的函数。yiilite.php中有这么几个函数。public function renderText($text,$returnfalse){if(($layoutFile$this->getLayoutFile($this->layout))!false)$text$this-…

php生成链接列表,根据URL链接和抛文本生成链接a标签的PHP函数

这个函数可以为组成一个链接,第一个参数是链接的URL,第二个参数是抛文本。最后生成抛文本function parseurl($url, $text) {if(!$url && preg_match("/((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\…

java 项目 人力资源项目,基于jsp的人力资源系统-JavaEE实现人力资源系统 - java项目源码...

基于jspservletpojomysql实现一个javaee/javaweb的人力资源系统, 该项目可用各类java课程设计大作业中, 人力资源系统的系统架构分为前后台两部分, 最终实现在线上进行人力资源系统各项功能,实现了诸如用户管理, 登录注册, 权限管理等功能, 并实现对各类人力资源系统相关的实体…

php阿拉伯语字符串,按字母顺序命名阿拉伯语名称Mysql和php

我试图用阿拉伯语对 alphabetical order 中的结果进行排序,但出于某种原因 not sorting correctly ..$ d1 mysqli_query($ connector,“SELECT * FROM article where type 1ORDER BY name ASC”); while($ a1 mysqli_fetch_array($ d1)){echo“$ a1 [n…

matlab里inline定义矩阵,Matlab中的inline函数_matlab中inline函数

Matlab中的inline函数1.有时为了描述某个数学函数的方便,可以用inline()函数来直接编写该函数,形式相当于M-函数,但无编写一个真正的MATLAB文件,就可以描述出某种数学关系。其调用格式为funinline(‘函数内容’,自变量…

matlab最佳拟合的指标是什么意思,Matlab拟合好坏常用指标

Matlab拟合好坏常用指标用过Matlab的拟合、优化和统计等工具箱的网友,会经常遇到下面几个名词:SSE(和方差、误差平方和):The sum of squares due to errorMSE(均方差、方差):Mean squared errorRMSE(均方根、标准差):R…

matlab保存并关闭excel文件夹,[转载]Matlab批量操作目标文件夹下的Excel文件

本程序主要使matlab批量操作Excel表,其中用到了parfor并行计算加快处理速度。相同效果,速度上和Excel vba是有差距的。%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%tic;clear;dirsdir(E:我的文…

php html标签自定义属性,浅谈JS读取DOM对象(标签)的自定义属性

DOM对象对于js来说,是个很基础的元素,我们写js一般来说,都一定会对它进行操作。我们可以很方便地给它加上自定义的属性,比如:var test document.getElementById("test");test.adang "adang";ale…

如何使用matlab的siso,利用Matlab内建程式SISODesignTool完成系统分析(Matlab61)开启.PDF...

利用Matlab内建程式SISODesignTool完成系统分析(Matlab61)开启.PDF利用 Matlab 內建程式 SISO Design Tool 完成系統分析(Matlab 6.1) :開啟 Matlab (6.x 以上版本) ,如下圖一左方視窗中點選Control System Toolbox 並執行 SISO Design Tool &#xff0c…