Background on what the code is trying to achieve: “Various parameters of the new process (e.g., euid, egid, argument list, environment, filename, etc.) that are subsequently passed to other functions are, for the sake of simplicity, combined into a structure of type linux_binprm. prepare_binprm is used to supply a number of parent process values (above all, the effective UID and GID); the remaining data — the argument list — are then copied manually into the structure. Note that prepare_binprm also takes care of handling the SUID and SGID bits:“
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; } } ... }
Here, the bitwise AND (&) is being used in the if-statement to analyze the flags. But what does this achieve? As in, what is the condition its checking and how is it evaluated?
Source: Linux Kernel Architecture
Advertisement
Answer
The result of bitwise and expression a & b
is a number with value 1 at every bit that is set in both a
and b
, and value 0 at all other bits. If that result is exactly equal to b
(for example) then it must be the case that every bit that is set in b
is also set in a
. If the result is unequal to b
then there must be at least one bit set in b
that is not set in a
.
In your particular example, mode
is a file mode bitmask, S_ISGID
is a macro representing the set-group-id bit of such a mask, and S_IXGRP
is a macro representing the group-executable bit of such a mask. The condition then evaluates whether both the S_ISGID
bit and the S_IXGRP
bit are set in mode
. If a regular file has a mode for which that is the case then that file is a setgid executable.