代码试图实现的背景: 新进程的各种参数(例如,euid、egid、参数列表、环境、文件名等)随后传递给其他函数的是,为了简单起见,组合成linux_binprm类型。Prepare_binprm用于提供许多父进程值(首先是有效UID和GID);然后将剩余的数据(参数列表)手动复制到结构。注意,prepare_binprm还负责处理SUID和SGID位:">
fs/exec.c
int prepare_binprm(struct linux_binprm *bprm)
{
...
bprm->e_uid = current->euid;
bprm->e_gid = current->egid;
if(!(bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID)) {
/* Set-uid? */
if (mode & S_ISUID) {
bprm->e_uid = inode->i_uid;
}
/* Set-gid? */
/*
* If setgid is set but no group execute bit then this
* is a candidate for mandatory locking, not a setgid
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->e_gid = inode->i_gid;
}
}
...
}
在这里,if语句中使用了位与(&)来分析标志。但这能达到什么目的呢?比如,它检查的条件是什么,它是如何评估的?
来源:Linux Kernel Architecture
按位和表达式a & b
的结果是在a
和b
中设置的每个比特上都为1,其他所有比特上都为0的数字。如果该结果恰好等于b
(例如),那么在b
中设置的每个位也必须在a
中设置。如果结果不等于b
,则b
中必须至少有一个位没有在a
中设置。
在您的特定示例中,mode
是文件模式位掩码,S_ISGID
是表示该掩码的set-group-id位的宏,S_IXGRP
是表示该掩码的组可执行位的宏。然后,条件计算S_ISGID
位和S_IXGRP
位是否都设置在mode
中。如果一个普通文件的模式是这样的,那么这个文件就是一个setgid可执行文件。