在文章 登录时显示服务器信息 中,有这样一个需求,/etc/profile.d
中的一个脚本,只在用户登录时执行一次,用户使用 sudo
或者 su
切换到其他用户时不执行。所以需要判断用户是否有变化。文章给出的方案如以下代码。
# 登录时显示机器业务信息
user=`who am i |awk '{print $1}'`
userSu=`whoami`
# 通过su sudo切换后,user和userSu变量将不同,此时不显示登录信息
if [ "$user"x == "$userSu"x ];then
cat /etc/logininfo.conf
fi
即判断 who am i
和 who
的结果是否一致,不一致则认为切换过用户,不执行 cat /etc/logininfo.conf
命令。为什么可行呢?来看看这两个命令的区别。
Contents
whoami
首先是 whoami
。
NAME
whoami - print effective userid
DESCRIPTION
Print the user name associated with the current effective user ID. Same as id -un.
可见其功能是打印 有效的用户(effective userid),和 id -un
作用一样,来看 id -un
的说明:
-n, --name print a name instead of a number, for -ugG
-u, --user print only the effective user ID
who am i
首先看 am i
是啥意思。
$ who --help
Usage: who [OPTION]... [ FILE | ARG1 ARG2 ]
Print information about users who are currently logged in.
...
If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.
即如果有两个参数,那么不管参数是啥,都相当于 who -m
。-m
参数的作用是:
-m only hostname and user associated with stdin
即 只面对和标准输入有直接交互的主机和用户,这个用户是 真实用户(real userid)。
用户ID
关于 effective userid,参考维基百科:
有效用户ID(Effective UID,即EUID)与有效用户组ID(Effective Group ID,即EGID)在创建与访问文件的时候发挥作用;具体来说,创建文件时,系统内核将根据创建文件的进程的EUID与EGID设定文件的所有者/组属性,而在访问文件时,内核亦根据访问进程的EUID与EGID决定其能否访问文件。
zh.wikipedia.org/wiki/用户ID
真实用户ID(Real UID,即RUID)与真实用户组ID(Real GID,即RGID)用于辨识进程的真正所有者,且会影响到进程发送信号的权限。没有超级用户权限的进程仅在其RUID与目标进程的RUID相匹配时才能向目标进程发送信号,例如在父子进程间,子进程从父进程处继承了认证信息,使得父子进程间可以互相发送信号。
暂存用户ID(Saved UID,即SUID)于以提升权限运行的进程暂时需要做一些不需特权的操作时使用,这种情况下进程会暂时将自己的有效用户ID从特权用户(常为root)对应的UID变为某个非特权用户对应的UID,而后将原有的特权用户UID复制为SUID暂存;之后当进程完成不需特权的操作后,进程使用SUID的值重置EUID以重新获得特权。在这里需要说明的是,无特权进程的EUID值只能设为与RUID、SUID与EUID(也即不改变)之一相同的值。
stackoverflow 上的一段解释:
The distinction between a real and an effective user id is made because you may have the need to temporarily take another user's identity (most of the time, that would be root, but it could be any user). If you only had one user id, then there would be no way of changing back to your original user id afterwards (other than taking your word for granted, and in case you are root, using root's privileges to change to any user).
So, the real user id is who you really are (the one who owns the process), and the effective user id is what the operating system looks at to make a decision whether or not you are allowed to do something (most of the time, there are some exceptions).
When you log in, the login shell sets both the real and effective user id to the same value (your real user id) as supplied by the password file.
Now, it also happens that you execute a setuid program, and besides running as another user (e.g. root) the setuid program is also supposed to do something on your behalf. How does this work?
After executing the setuid program, it will have your real id (since you're the process owner) and the effective user id of the file owner (for example root) since it is setuid.The program does whatever magic it needs to do with superuser privileges and then wants to do something on your behalf. That means, attempting to do something that you shouldn't be able to do should fail. How does it do that? Well, obviously by changing its effective user id to the real user id!
Now that setuid program has no way of switching back since all the kernel knows is your id and… your id. Bang, you're dead.
This is what the saved set-user id is for.
stackoverflow.com/a/32456814/4952955
setuid
程序主要用于临时获取 root
权限,比如 passwd
命令,用户组是 root
,但是普通用户也能修改自己的密码,关键就在于 setuid 位:
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 27856 Aug 9 2019 /usr/bin/passwd
注意 权限是 -rws
而不是 -rwx
,s
表示是一个带 setuid
位的程序。
setuid
和 SUID 需要区分:
The Saved user ID (SUID) is being used when a privileged process is running (as root for example) and it needs to do some unprivileged tasks.
In that case, the effective UID (EUID) from before will be saved inside SUID and then changed to an unprivileged task. When the unprivileged task is completed the EUID will be taken from the value of SUID and switch back to privileged account.
stackoverflow.com/a/58123923/4952955
setuid: (set user ID upon execution) is a Unix/Linux access rights flag that allow users to run an executable with the permissions of the executable's owner. It is needed for tasks that require higher privileges than those which common users have, such as changing their login password.
suid: (saved user ID) is used when a program running with elevated privileges needs to temporarily do some unprivileged work. It changes its effective user ID from a privileged value (typically root) to some unprivileged one.
nosuid. When mount use this option then the file system doesn't allow set-user-identifier (setuid) or set-group-identifier (setgid) bits to take effect.
https://unix.stackexchange.com/a/257702
setuid
是指文件的一个特殊权限,可以用 chmod
设置,置于 u
的 x
位,即:
chmod u+x /path/to/file
类似的还有 setgid
,sticky bits
权限,分别用以下方法设置:
# setgid 置于 g 的 x 位
chmod g+s /path/to/file
# sticky bits 置于 o 的 x 位
chmod o+t /path/to/file
在 8 禁止表示的权限前面加 4
,2
,1
分别代表 setuid
,setgid
和 sticky bits
位,因此 chmod 1777 /tmp
也可以为 /tmp
加上 sticky bits
权限。因此,可以通过 find
的 -perm
参数找到带特殊权限的文件,比如找出 /usr/bin
下带 setuid
权限的文件:
$ find /usr/bin -perm 4755
/usr/bin/at
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/crontab
/usr/bin/su
/usr/bin/chage
/usr/bin/mount
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/newgrp
参考资料
1. https://zh.wikipedia.org/wiki/用户ID
2. https://stackoverflow.com/a/32456814/4952955
3. https://stackoverflow.com/a/58123923/4952955
4. https://unix.stackexchange.com/a/257702
发表回复