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

相关文章

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程