Linux内核中prepare_binprm函数if语句里按位与(&)操作的作用解析
prepare_binprm Great question — let's break down exactly what this bitwise logic is doing, step by step. It’s all about correctly identifying when a file should act as a setgid executable, rather than being marked for mandatory locking.
First, some quick context: Linux file permissions and special flags (like setgid) are stored as individual bits in an integer value called mode. The macros S_ISGID and S_IXGRP represent specific bits in this integer:
S_ISGID: The "set-group-ID" bit — when set on an executable, the process running it inherits the file’s group ID as its effective GID.S_IXGRP: The "group execute" permission bit — allows users in the file’s group to run the executable.
Now let’s unpack the condition:
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { bprm->e_gid = inode->i_gid; }
Step 1: S_ISGID | S_IXGRP — Create a Target Mask
The bitwise OR (|) combines the two flags into a single mask where both the S_ISGID and S_IXGRP bits are set to 1, and all other bits are 0. For example, if S_ISGID is 0o2000 (octal, binary 10000000000) and S_IXGRP is 0o0010 (binary 00000001000), their OR result is 0o2010 (binary 10000001000).
Step 2: mode & (S_ISGID | S_IXGRP) — Extract Relevant Bits
The bitwise AND (&) here acts like a filter: it takes the file’s mode value and keeps only the bits that match our mask, clearing all others. This tells us the state of just the S_ISGID and S_IXGRP bits in the file’s permissions.
For example:
- If
modehas both S_ISGID and S_IXGRP set, the result equals our mask (0o2010). - If only S_ISGID is set, the result is
0o2000(doesn’t match the mask). - If only S_IXGRP is set, the result is
0o0010(doesn’t match the mask). - If neither is set, the result is
0.
Step 3: The Equality Check — Verify Both Bits Are Set
By comparing the result of the AND operation to our original mask, we’re verifying that both the S_ISGID and S_IXGRP bits are enabled in the file’s mode.
Why This Matters
As the comment in the code explains:
If setgid is set but no group execute bit then this is a candidate for mandatory locking, not a setgid executable.
Linux uses the S_ISGID bit for two different purposes:
- Setgid executable: When S_ISGID and S_IXGRP are both set — the process runs with the file’s group ID.
- Mandatory locking: When S_ISGID is set but S_IXGRP is not — this marks the file for mandatory file locking (a rare feature where the kernel enforces locks on the file).
This condition ensures we only trigger the setgid behavior when it’s actually intended, avoiding confusion with mandatory locking.
内容的提问来源于stack exchange,提问作者Yuv

