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

相关文章

Linux镜像文件制作方式

《Linux镜像文件制作方式》本文介绍了Linux镜像文件制作的过程,包括确定磁盘空间布局、制作空白镜像文件、分区与格式化、复制引导分区和其他分区... 目录1.确定磁盘空间布局2.制作空白镜像文件3.分区与格式化1) 分区2) 格式化4.复制引导分区5.复制其它分区1) 挂载2) 复制bootfs分区3)

Linux服务器数据盘移除并重新挂载的全过程

《Linux服务器数据盘移除并重新挂载的全过程》:本文主要介绍在Linux服务器上移除并重新挂载数据盘的整个过程,分为三大步:卸载文件系统、分离磁盘和重新挂载,每一步都有详细的步骤和注意事项,确保... 目录引言第一步:卸载文件系统第二步:分离磁盘第三步:重新挂载引言在 linux 服务器上移除并重新挂p

Linux下屏幕亮度的调节方式

《Linux下屏幕亮度的调节方式》文章介绍了Linux下屏幕亮度调节的几种方法,包括图形界面、手动调节(使用ACPI内核模块)和外接显示屏调节,以及自动调节软件(CaliseRedshift和Reds... 目录1 概述2 手动调节http://www.chinasem.cn2.1 手动屏幕调节2.2 外接显

Linux(centos7)虚拟机没有IP问题及解决方案

《Linux(centos7)虚拟机没有IP问题及解决方案》文章介绍了在CentOS7中配置虚拟机网络并使用Xshell连接虚拟机的步骤,首先,检查并配置网卡ens33的ONBOOT属性为yes,然后... 目录输入查看ZFhrxIP命令:ip addr查看,没有虚拟机IP修改ens33配置文件重启网络Xh

linux实现对.jar文件的配置文件进行修改

《linux实现对.jar文件的配置文件进行修改》文章讲述了如何使用Linux系统修改.jar文件的配置文件,包括进入文件夹、编辑文件、保存并退出编辑器,以及重新启动项目... 目录linux对.jar文件的配置文件进行修改第一步第二步 第三步第四步总结linux对.jar文件的配置文件进行修改第一步进

linux ssh如何实现增加访问端口

《linuxssh如何实现增加访问端口》Linux中SSH默认使用22端口,为了增强安全性或满足特定需求,可以通过修改SSH配置来增加或更改SSH访问端口,具体步骤包括修改SSH配置文件、增加或修改... 目录1. 修改 SSH 配置文件2. 增加或修改端口3. 保存并退出编辑器4. 更新防火墙规则使用uf

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

Linux云服务器手动配置DNS的方法步骤

《Linux云服务器手动配置DNS的方法步骤》在Linux云服务器上手动配置DNS(域名系统)是确保服务器能够正常解析域名的重要步骤,以下是详细的配置方法,包括系统文件的修改和常见问题的解决方案,需要... 目录1. 为什么需要手动配置 DNS?2. 手动配置 DNS 的方法方法 1:修改 /etc/res