setuid函数

2024-04-14 22:32
文章标签 函数 setuid

本文主要是介绍setuid函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

setuid(设置真实的用户识别码)
相关函数
getuid,setreuid,seteuid,setfsuid
表头文件
#include<unistd.h>
定义函数
int setuid(uid_t uid)
函数说明
setuid()用来重新设置执行目前进程的用户识别码。不过,要让此函数有作用,其有效的用户识别码必须为0(root)。在Linux下,当root 使用setuid()来变换成其他用户识别码时,root权限会被抛弃,完全转换成该用户身份,也就是说,该进程往后将不再具有可setuid()的权 利,如果只是向暂时抛弃root 权限,稍后想重新取回权限,则必须使用seteuid()。
返回值
执行成功则返回0,失败则返回-1,错误代码存于errno。
附加说明
一般在编写具setuid root的程序时,为减少此类程序带来的系统安全风险,在使用完root权限后建议马上执行setuid(getuid());来抛弃root权限。此外,进程uid和euid不一致时Linux系统将不会产生core dump。


内核会给每个进程关联两个和进程ID无关的用户ID,一个是真实用户ID,还有一个是有效用户ID或者称为setuid(set user ID)。真实用户ID用于标识由谁为正在运行的进程负责。有效用户ID用于为新创建的文件分配所有权、检查文件访问许可,还用于通过kill系统调用向其 它进程发送信号时的许可检查。内核允许一个进程以调用exec一个setuid程序或者显式执行setuid系统调用的方式改变它的有效用户ID。 所谓setuid程序是指一个设置了许可模式字段中的setuid bit的可执行文件。当一个进程exec一个setuid程序的时候,内核会把进程表以及u区中的有效用户ID设置成该文件所有者的ID。为了区分这两个 字段,我们把进程表中的那个字段称作保存用户ID。可以通过一个例子来演示这两个字段的区别。 setuid系统调用的语法是 setuid(uid) ,其中,uid是新的用户ID,该系统调用的结果取决于有效用户ID的当前值。如果调用进程的有效用户ID是超级用户,内核会把进程表以及u区中的真实和 有效用户ID都设置成uid。如果调用进程的有效用户ID不是超级用户,仅当uid等于真实用户ID或保存用户ID时,内核才会把u区中的有效用户ID设 置成uid。否则,该系统调用将返回错误。一般来说,一个进程会在fork系统调用期间从父进程那儿继承它的真实和有效用户ID,这些数值即使经过 exec系统调用也会保持不变。 存储在u区中的有效用户ID是最近一次setuid系统调用或是exec一个setuid程序的结果;只有它会被用于文件访问许可。进程表中的保存用户 ID使得一个进程可以通过执行setuid系统调用把有效用户ID设置成它的值,以此来恢复最初的有效用户ID。

非root用户是不可能通过setuid或者seteuid取得其他权限(包括root权限)的,它只能恢复原来的权限。允许通过setuid或者seteuid取得root权限是非常危险的这样他就可以在程序的后边做任何想做的事了(包括kill掉你的系统)。只能通过exec一个设置了setuid位的可执行程序,来取得其他(程序文件所有者)权限(包括root权限)。例如用户执行su即可获得root权限(su的属主为root)。

-rwsr-xr-x 1 root root 27108 2008-11-23 /bin/su

注意其中的s,该标志即为setuid标志(文件除基本的r、w、x权限外,还有s)。出于安全,防止普通用户取得root权限后威胁系统安全,该权限只针对不可更改的可执行文件(不能执行自定义程序)

要想取得root权限就必须exec一个root所有的可执行文件(当然首先得有执行权限),而该程序由root所有,其安全就由root负责。所以非root用户就不可能以root身份运行属于root以外的程序。至于sudo之类的,是因为sudo本身里有setuid和exec调用(root用户允许的,给非root用户开了一个后门),通过sudo
取得root权限, 作为中介来exec所有程序。但也有限制,就是该用户是sudoers(后门的钥匙,root的亲戚才有,又是安全)!(现在流行靠关系、开后门,到时如果出问题,就该抱怨了:都是开后门惹的祸!)

su=super user
sudo是什么的缩写?super user ? ?(应为swicth user

还有非root权限用户,不能改变实际用户ID,而只能改变有效用户ID,包括通过exec一个setuid程序。
只有root用户进程才能更改实际用户ID。这样普通用户进程就不能通过改变实际用户ID,然后再通过setuid,设置有效用户ID为实际用户ID,进而取得与该实际用户ID对应的权限了(包括root)。正如上面说过的:
允许通过setuid或者seteuid取得root权限是非常危险的

对于文件访问权限的验证是根据有效用户ID。有些文件只有root用户才有读写或者执行的权力,对于这些文件,普通用户程序就需要以root权限(进程的有效用户ID为0)来访问。

举个例子:
sudo vim /etc/sudoers
====================以下分析错误=========================
sudoers是取得root权限的关键文件,只有root可以写。所以,普通用户是不能用VIM编辑的。但sudoers用户可以运行sudo,运行sudo可以将进程有效用户ID设为文件所有者root,但exec  vim后,由于vim不是setuid程序,子进程不会将euid设置为vim所有者uid,而会继承父进程的euid即为root的uid=0,所以vim进程的euid为0,这时的vim以写方式打开sudoers文件是可以通过权限检查的。

sudo的实现里有setuid函数,但对于上边那个例子只用fork和exec已经可以实现了。什么时候会把[子]进程的实际用户ID也设为0,这个还没弄清楚,运行一个属主非root的steuid程序?
=======================================================
通过输出父子进程的uid和euid证实,sudo通过setuid将进程的实际用户ID和有效用户ID都设置为了0,也就是整个过程中进程都是有root权限的。关键不在exec处了!!

这篇关于setuid函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/904200

相关文章

Python函数作用域与闭包举例深度解析

《Python函数作用域与闭包举例深度解析》Python函数的作用域规则和闭包是编程中的关键概念,它们决定了变量的访问和生命周期,:本文主要介绍Python函数作用域与闭包的相关资料,文中通过代码... 目录1. 基础作用域访问示例1:访问全局变量示例2:访问外层函数变量2. 闭包基础示例3:简单闭包示例4

Python中isinstance()函数原理解释及详细用法示例

《Python中isinstance()函数原理解释及详细用法示例》isinstance()是Python内置的一个非常有用的函数,用于检查一个对象是否属于指定的类型或类型元组中的某一个类型,它是Py... 目录python中isinstance()函数原理解释及详细用法指南一、isinstance()函数

python中的高阶函数示例详解

《python中的高阶函数示例详解》在Python中,高阶函数是指接受函数作为参数或返回函数作为结果的函数,下面:本文主要介绍python中高阶函数的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录1.定义2.map函数3.filter函数4.reduce函数5.sorted函数6.自定义高阶函数

Python中的sort方法、sorted函数与lambda表达式及用法详解

《Python中的sort方法、sorted函数与lambda表达式及用法详解》文章对比了Python中list.sort()与sorted()函数的区别,指出sort()原地排序返回None,sor... 目录1. sort()方法1.1 sort()方法1.2 基本语法和参数A. reverse参数B.

Python函数的基本用法、返回值特性、全局变量修改及异常处理技巧

《Python函数的基本用法、返回值特性、全局变量修改及异常处理技巧》本文将通过实际代码示例,深入讲解Python函数的基本用法、返回值特性、全局变量修改以及异常处理技巧,感兴趣的朋友跟随小编一起看看... 目录一、python函数定义与调用1.1 基本函数定义1.2 函数调用二、函数返回值详解2.1 有返

Python Excel 通用筛选函数的实现

《PythonExcel通用筛选函数的实现》本文主要介绍了PythonExcel通用筛选函数的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录案例目的示例数据假定数据来源是字典优化:通用CSV数据处理函数使用说明使用示例注意事项案例目的第一

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N