linux 中的用户ID (ZZ)

2024-06-05 11:58
文章标签 linux 用户 id zz

本文主要是介绍linux 中的用户ID (ZZ),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、进程与权限

A.进程时Linux/Unix操作系统中最重要的抽象之一

B.进程是一个处于执行期的程序(目标代码存储在某种介质上)
A process is a program(object code stored on some media) in the midst of
execution.

而进程在执行过程中经常涉及到文件访问操作等
1.一个运行中的进程究竟可以访问哪些资源,而不能访问哪些资源?
2.一个进程运行过程中如何实现在某个执行阶段拥有一些权限而在另一个阶段又具备另外一种权限呢?

上述状况对应于进程的访问权限以及进程执行中不同权限的切换。这一切都和进程实际用户ID,进程有效用户ID,进程保存设置用户ID有关联。

二、进程的用户ID

1.实际用户ID(real user id,RUID)

为该进程的创建者的用户ID,也可以说是进程的执行者。该ID仅root用户可以修改

2.有效用户ID(effective user id,EUID)

该ID用户标识用户进程执行操作的权限。例如:如果EUID是0即(root),此时进程拥有root用户权限。普通用户可以将EUID设置为RUID或者SUID,而超级用户可以将EUID设置为任意的合法UID。

注意:对于一个可执行的二进制文件,如果其set-user-id bit被设置,则运行改程序时,对应进程的有效用户ID(EUID)为该文件的文件所有者用户ID。

3.保存设置用户ID(saved set-user-id,SUID)

对于没有设置set-uid-bit的可执行程序而言,其对应进程的保存设置用户ID(SUID)为其实际用户ID;而对于设置了set-uid-bit的程序而言,其对应的保存设置用户ID(SUID)为该可执行文件的文件拥有者用户ID。只能root用户权限,才能更改(当一个程序文件运行的时候,其值已经确定)。

注意:linux不提供返回保存的设置-用户-ID的函数

总结:
RUID代表此进程是哪个用户创建的, EUID代表此进程所拥有的权限,SUID保存了EUID,当EUID改变后,如果想回到以前的EUID,此时SUID将发挥作用。

三、相关API

#include <sys/types.h>
#include <unistd.h>

int setuid(uid);

可以用setuid函数设置实际用户ID和有效用户ID。注意,我们并不能想怎么设就怎么设。有若干规则需要我们遵守:

(1)若进程具有超级用户特权,则setuid函数将实际用户ID、有效用户ID,以及保存的设置-用户-D设置为uid。

(2)若进程没有超级用户特权,但是uid等于实际用户ID或保存的设置-用户-ID,则setuid只将有效用户ID设置为。不改变实际用户ID和保存的设置-用户-ID。

(3)如果上面两个条件都不满足,则errno设置为EPERM,并返回出错.。

关于内核所维护的三个用户ID,还要注意下列几点

(1)只有超级用户进程可以更改实际用户ID。通常,实际用户ID是在用户登录时,由login(1)程序设置的,而且决不会改变它。因为login是一个超级用户进程,当它调用setuid时,设置所有三个用户ID。

(2)仅当对程序文件设置了 set-user-id bit时,exec函数设置有效用户ID为文件所有者。如果set-user-id bit没有设置,则exec函数不会改变有效用户ID,而将其位置原先值。任何时候都可以调用setuid,将有效用户ID设置为实际用户ID或保存的设置-用户-ID。自然,不能讲有效用户ID设置为任意随机值。

四、探究

案例一:
有个要在MacOS上实现一个关机程序,它熟悉linux,其实老祖宗都是unix,所以MacOS对他并不陌生。如下他写了如下程序实现关机



编译运行:



从上面看,这段代码可以实现关机,但是有个不符合要求的地方,运行程序不能是超级用户,只能是普通用户。

他很苦恼,后来找到了我,我做了如下事情



呵呵,可以了。我将这个可执行文件的owner和group都改为了root,然后有讲其set-user-id bit位加以了设置。这样以普通用户运行这个程序时,此进程的EUID就是root了,这样满足了shutdown命令执行的权限。

案例二:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>

  7. void test_read_file(const char *name)
  8. {
  9. int fd = -1;

  10. fd = open(name ,O_RDWR);
  11. if(fd < 0){
  12. printf("=[ERROR]:read failed.\n");
  13. }else{
  14. printf("=[OK]:read successful\n");
  15. close(fd);
  16. }
  17. }

  18. //打印uid和euid
  19. void p_states()
  20. {
  21. int uid = 0;
  22. int euid = 0;

  23. printf("------Current states--------\n");
  24. printf("real uid\t %d\n",getuid());
  25. printf("effective uid\t %d\n",geteuid());
  26. printf("----------------------------\n");
  27. }

  28. //调用setuid
  29. void run_setuid_fun(int uid)
  30. {
  31. if(setuid(uid) == -1)
  32. {
  33. printf("=[ERROR]:setuid(%d) error\n",uid);
  34. }

  35. p_states();
  36. }

  37. //调用setuid
  38. void run_seteuid_fun(int uid)
  39. {
  40. if(setuid(uid) == -1)
  41. {
  42. printf("=[ERROR]:seteuid(%d) error\n",uid);
  43. }

  44. p_states();
  45. }

  46. int main()
  47. {
  48. int t_re = 0;
  49. const char *file = "root_only.txt";

  50. printf("\nTEST 1:\n");
  51. p_states();
  52. //此时real uid = login user id
  53. //effective uid = root
  54. //saved uid = root
  55. test_read_file(file);

  56. getchar();

  57. printf("\nTEST 2:setuid(getuid())\n");
  58. run_seteuid_fun(getuid());
  59. //此时real uid = login user id
  60. //effective uid = login user id
  61. //saved uid = root
  62. test_read_file(file);

  63. getchar();

  64. printf("\nTEST 3:setuid(0)\n");
  65. run_setuid_fun(0);
  66. //此时real uid = login user id
  67. //effective uid = root
  68. //saved uid = root
  69. test_read_file(file);

  70. getchar();

  71. printf("\nTEST 4:setuid(0)\n");
  72. run_setuid_fun(0);
  73. //此时real uid = root
  74. //effective uid = root
  75. //saved uid = root
  76. test_read_file(file);

  77. getchar();

  78. printf("\nTEST 5:setuid(503)\n");
  79. run_setuid_fun(503);
  80. //此时real uid = login user id
  81. //effective id = login user id
  82. //saved uid = login user id
  83. test_read_file(file);

  84. getchar();

  85. printf("\nTEST 6:setuid(0)\n");
  86. //read uid = login user id
  87. //effective uid = login user id
  88. //saved uid = login user id
  89. run_setuid_fun(0);
  90. test_read_file(file);

  91. return 0;
  92. }
编译运行:



root_only.txt文件建立:



第一次:

RUID:实际用户
EUID:文件所有者(root)
SUID:文件所有者(root)



此时进程拥有root用户权限,能对 root_only.txt 进行读写操作

第二次:

此时普通用户调用setuid(getuid()),只会将EUID改为getuid(),其他都不变
RUID:实际用户
EUID:实际用户
SUID:root



此时进程没有有root用户权限,不能能对 root_only.txt 进行读写操作

第三次:

此时普通用户调用seteuid(0),只会将EUID改为0,其他都不变
RUID:实际用户
EUID:root
SUID:root



此时进程拥有root用户权限,能对 root_only.txt 进行读写操作

第四次:

此时进程拥有root用户权限,调用setuid(0),会将三个ID都设置为0
RUID:root
EUID:root
SUID:root



此时进程拥有root用户权限,能对 root_only.txt 进行读写操作

第五次:

此时进程拥有root用户权限,调用setuid(503),会将三个ID都设置为503
RUID:503
EUID:503
SUID:503



此时进程拥有普通用户权限,不能对 root_only.txt 进行读写操作

第六次:

此时进程拥有普通用户权限,调用setuid(0),此时RUID,SUID都不为0,这一次操作将失败
RUID:503
EUID:503
SUID:503


此时进程拥有普通用户权限,不能能对 root_only.txt 进行读写操作

这篇关于linux 中的用户ID (ZZ)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespace id不一致处理

《mysql8.0无备份通过idb文件恢复数据的方法、idb文件修复和tablespaceid不一致处理》文章描述了公司服务器断电后数据库故障的过程,作者通过查看错误日志、重新初始化数据目录、恢复备... 周末突然接到一位一年多没联系的妹妹打来电话,“刘哥,快来救救我”,我脑海瞬间冒出妙瓦底,电信火苲马扁.

linux打包解压命令方式

《linux打包解压命令方式》文章介绍了Linux系统中常用的打包和解压命令,包括tar和zip,使用tar命令可以创建和解压tar格式的归档文件,使用zip命令可以创建和解压zip格式的压缩文件,每... 目录Lijavascriptnux 打包和解压命令打包命令解压命令总结linux 打包和解压命令打

linux如何复制文件夹并重命名

《linux如何复制文件夹并重命名》在Linux系统中,复制文件夹并重命名可以通过使用“cp”和“mv”命令来实现,使用“cp-r”命令可以递归复制整个文件夹及其子文件夹和文件,而使用“mv”命令可以... 目录linux复制文件夹并重命名我们需要使用“cp”命令来复制文件夹我们还可以结合使用“mv”命令总

Linux使用cut进行文本提取的操作方法

《Linux使用cut进行文本提取的操作方法》Linux中的cut命令是一个命令行实用程序,用于从文件或标准输入中提取文本行的部分,本文给大家介绍了Linux使用cut进行文本提取的操作方法,文中有详... 目录简介基础语法常用选项范围选择示例用法-f:字段选择-d:分隔符-c:字符选择-b:字节选择--c

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

TP-Link PDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务

《TP-LinkPDDNS服将于务6月30日正式停运:用户需转向第三方DDNS服务》近期,路由器制造巨头普联(TP-Link)在用户群体中引发了一系列重要变动,上个月,公司发出了一则通知,明确要求所... 路由器厂商普联(TP-Link)上个月发布公告要求所有用户必须完成实名认证后才能继续使用普联提供的 D

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.