每天学五分钟 Liunx 0111 | 服务篇:进程权限


程序存储在硬盘中,需要执行的时候被加载到内存里,内存中的程序以进程的方式运行,进程会根据程序的内容去做读写文件,执行指令等操作。
文件/指令等都有自己的执行权限,符合权限的才能被执行。相应的,进程也需要有这些权限才能执行相应的操作。

进程权限

命令 cat /proc//status | egrep "Uid|Gid" 查看进程的权限:
[root@lianhua lib]$ cat /proc/37220/status | egrep "Uid|Gid"
Uid:    1004    1004    1004    1004
Gid:    1007    1007    1007    1007

 

以第一行为例,从左到右分别表示进程的 real user id, effective user id,saved set user id 和 filesystem UID。
 
各 id 的意义如下:
read user id: 进程执行者 id,从父进程那里继承来的 user id。
 
effective user id: 进程执行的实际 id,通过这个 id 验证进程是否有文件的访问权限。如果设置了 SUID 则进程执行时的 effective user id 会成为执行文件/程序的 owner id,这时候 effective user id 和 real user id 是不一样的。比如,passwd 命令(只有 root 才能执行)设置了 SUID,如果进程以 1004 的身份去执行 passwd, effective user id 会成为 root 的 id:
[robot@lianhua ~]$ ll /bin/passwd
-rwsr-xr-x. 1 root root 27832 Jan 30  2014 /bin/passwd
[robot@lianhua ~]$ passwd
Changing password for user robot.
Changing password for robot.
(current) UNIX password:
 
[root@lianhua ~]$ ps -lA | grep passwd
4 S     0 38063 37943  0  80   0 - 47201 wait_w pts/15   00:00:00 passwd
[root@lianhua ~]$ cat /proc/38063/status | egrep "Uid|Gid"
Uid:    1004    0       0       0
Gid:    1007    1007    1007    1007
 
saved set user id: saved set user id 相当于是一个 buffer,在 exec 函数启动之后,它会拷贝 effective user id 位的信息覆盖自己。所以从上面例子看出 saved user id 也随之改成了 root 的 id 0。
 

程序实现

通过一个简单的小例子加深进程权限的印象。
写一个 copy.sh 脚本,它做的事情是拷贝一个 root 权限的文件到另一个目录,然后更改这个文件的属性:
[root@lianhua lib]$ cat copy.sh
#!/bin/bash
 
sleep 10
 
cp /home_local/robot/systemd/tmp.log /home_local/robot/systemd/lib/
chown test /home_local/robot/systemd/lib/tmp.log
rm -rf /home_local/robot/systemd/lib/tmp.log
 
sleep 10
 
写个服务 copy.service 将这个脚本添加到服务中,并且更改服务中执行脚本的用户(systemd Drop-in 的方式更改)为 robot:
[root@lianhua lib]$ systemctl cat copy.service
# /usr/lib/systemd/system/copy.service
[Unit]
Description=a test copy demo for process conflict handle
Documentation=man:systemd.unit(8)
 
[Service]
Type=simple
ExecStart=/bin/bash /home_local/robot/systemd/lib/copy.sh
Restart=on-failure
 
# /usr/lib/systemd/system/copy.service.d/app.conf
[Service]
User=
User=robot
 
启动 copy.service ,查看进程权限 id:
[root@lianhua ~]$ systemctl status copy.service
● copy.service - a test copy demo for process conflict handle
   Loaded: loaded (/usr/lib/systemd/system/copy.service; static; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/copy.service.d
           └─app.conf
   Active: activating (start) since Sun 2020-05-10 16:24:40 CST; 7s ago
     Docs: man:systemd.unit(8)
  Control: 40081 (bash)
   Memory: 432.0K
   CGroup: /system.slice/copy.service
           ├─40081 /bin/bash /home_local/robot/systemd/lib/copy.sh
           └─40083 sleep 10
May 10 16:33:52 lianhua systemd[1]: Starting a test copy demo for process conflict handle...
May 10 16:34:02 lianhua bash[40767]: chown: changing ownership of ‘/home_local/robot/systemd/lib/tmp.log’: Opera…ermitted
 
[root@lianhua ~]$ cat /proc/40081/status| egrep "Uid|Gid"
Uid:    1004    1004    1004    1004
Gid:    1007    1007    1007    1007
[root@lianhua ~]$ ps -lAf | grep copy.service
4 S root     40075 32280  0  80   0 - 33707 poll_s 16:24 pts/15   00:00:00 systemctl restart copy.service
0 S root     40130 32507  0  80   0 - 28179 pipe_w 16:25 pts/16   00:00:00 grep --color=auto copy.service
[root@lianhua ~]$ ps -lAf | grep 40081
4 S robot    40081     1  0  80   0 - 28296 do_wai 16:24 ?        00:00:00 /bin/bash /home_local/robot/systemd/lib/copy.sh
0 S robot    40098 40081  0  80   0 - 26990 hrtime 16:24 ?        00:00:00 sleep 10
 
[root@lianhua lib]$ ll
total 4
-rw-r--r-- 1 root  root  197 May 10 16:24 copy.sh
-rw-r--r-- 1 robot robot   0 May 10 16:26 tmp.log
[root@lianhua lib]$ cd ..
[root@lianhua systemd]$ ll
total 0
drwxrwxrwx 2 root root  6 May  7 11:17 bin
drwxrwxrwx 2 root root 36 May 10 16:24 lib
-rw-r--r-- 1 root root  0 May  7 11:17 tmp.log
 
从上述结果可以看出:
1. systemd 以 root 身份执行 copy.service ,它的父进程是 bash 进程 32280。
2. systemd 以 robot 身份执行 copy.sh 脚本,默认 systemd 以 root 身份去执行,这里添加了 Drop-in 文件,使得 systemd 去掉 root 而以 robot 身份去执行该脚本。进程 id 是 40081,它的父进程是 id 为 1 的 systemd 进程。
3. 执行 copy.sh 脚本会产生一个 40081 的进程来执行脚本里的内容,它的 Uid/Gid 分别是 1004(robot 用户的 Uid) 和 1007(robot 用户的 Gid)。
4. 进程在执行 cp 过程时,会更改原本权限为 root/root 的 tmp.log 文件为自己的 Uid/Gid 对应的用户身份 robot/robot。
5. 脚本中使用的 chown 命令并未设置 SUID,所以进程 40081 执行 chown 会报错,显示权限不允许。
6. sleep 命令对于用户 robot 来说时可以执行的,内核以 fork and exec 的方式执行它,产生了一个 40098 的进程,它的父进程是 40081,且执行的用户身份是继承自父进程的。
 

SUID and SGID

针对上述第五点,进程 40081 没办法使用 chown 命令,这里简单介绍 SUID 以及 SGID,再手动更改 chown 的 SUID 使得进程可以执行它。
 
SUID:
  • SUID 仅对二进程程序有效;
  • 执行者对于该程序需要有 x 的可执行权限;
  • 执行者将执行程序时将取得该程序所有者的权限;
  • 执行者取得该程序的权限仅在运行过程 (run-time) 中有效;
 
SGID 也是类似的,不介绍了。
 
查看 chown 的权限:
[root@lianhua ~]$ which chown
/usr/bin/chown
[root@lianhua ~]$ ll /usr/bin/chown
-rwxr-xr-x. 1 root root 62904 Dec  4  2017 /usr/bin/chown
 
更改 chown 使它具有 SUID 权限:
[root@lianhua ~]$ chmod 4755 /usr/bin/chown
[root@lianhua ~]$ ll /usr/bin/chown
-rwsr-xr-x. 1 root root 62904 Dec  4  2017 /usr/bin/chown

 

chmod 执行的第一个参数表示设置 SUID/SGID/SBIT,其中 4 表示 SUID,2 表示 SGID,1表示 SBIT。
 
以 robot 用户执行 chown 命令:
[root@lianhua ~]$ su - robot
[robot@lianhua ~]$ ll /home_local/robot/systemd/lib/tmp.log
-rw-r--r-- 1 robot robot 0 May 10 17:14 /home_local/robot/systemd/lib/tmp.log
[robot@lianhua ~]$ chown test /home_local/robot/systemd/lib/tmp.log
[robot@lianhua ~]$ ll /home_local/robot/systemd/lib/tmp.log
-rw-r--r-- 1 test robot 0 May 10 17:14 /home_local/robot/systemd/lib/tmp.log
 
[root@lianhua lib]$ systemctl status copy.service
● copy.service - a test copy demo for process conflict handle
   Loaded: loaded (/usr/lib/systemd/system/copy.service; static; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/copy.service.d
           └─app.conf
   Active: inactive (dead)
     Docs: man:systemd.unit(8)
 
May 10 17:31:03 lianhua systemd[1]: Starting a test copy demo for process conflict handle...
May 10 17:31:23 lianhua systemd[1]: Started a test copy demo for process conflict handle.
 
robot 用户可以执行 chown 命令,服务 copy.service 顺利执行。
 
 
 
(完)
 

你可能感兴趣的:(每天学五分钟 Liunx 0111 | 服务篇:进程权限)