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

相关文章

MySQL中COALESCE函数示例详解

《MySQL中COALESCE函数示例详解》COALESCE是一个功能强大且常用的SQL函数,主要用来处理NULL值和实现灵活的值选择策略,能够使查询逻辑更清晰、简洁,:本文主要介绍MySQL中C... 目录语法示例1. 替换 NULL 值2. 用于字段默认值3. 多列优先级4. 结合聚合函数注意事项总结C

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function