I'm not understanding setgid on executables on my platform (ubuntu). g-x,g+s is not giving the process effective group permissions of the program's owner.

$ gcc perms.c -o perms; ls -l ; ./perms
-rwxr-xr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
-rw-r--r-- 1 ubuntu ubuntu 1437 Feb 21 08:41 perms.c
ruid: ubuntu:1000 group:1000
euid: ubuntu:1000 group:1000

$ sudo useradd alice; groups alice $USER
alice : alice
ubuntu : ubuntu sudo rvm

$ chmod g+s ./perms; ls -l ./perms ; sudo -u alice ./perms
rwxr-sr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
ruid: alice:1001 group:1002
euid: alice:1001 group:**1000**

This is all expected, the problem is:

$ chmod g-x ./perms; ls -l ./perms ; sudo -u alice ./perms
-rwxr-Sr-x 1 ubuntu ubuntu 9302 Feb 24 01:00 perms*
ruid: alice:1001 group:1002
euid: alice:1001 group:**1002**

My understanding is that g+s gives the process the effective group id of the program's owner, but it's not. Obviously, this is because of the g-x since that was the only change.

Edit1: removed the section on how g-x,g+s works on directories, because people were thinking I was asking about S on directories. I'm not.

Edit2: since I'm getting condesention from one answer. This is also different than from what happens with u-x,u+s:

$ rm -rf perms temp/; gcc perms.c -o perms
$ chmod ug-x,ug+s ./perms; ls -l ./perms; sudo -u alice ./perms
-rwSr-Sr-x 1 ubuntu ubuntu 9302 Feb 24 21:22 ./perms*
ruid: alice:1001 group:1002
euid: ubuntu:1000 group:1002

Here u-x,u+s is respected, but g-x,g+s is not.

My question: why is capital S sgid ignored for executables?
g-x,g+s is respected on directories.
u-x,u+s is respected on executables.
But g-x,g+s is not respected on executables.

ANSWER: my research seems to have dead-ended at "because System V arbitrarily decided it means something else."


2 Answers 2


Alright, not much help from the one response that told me to RTFM. After digging for a few hours, I found these lines in the current linux kernel.


/* Be careful if suid/sgid is set */

/* reload atomically mode/uid/gid now that lock held */
mode = inode->i_mode;
uid = inode->i_uid;
gid = inode->i_gid;

/* We ignore suid/sgid if there are no mappings for them in the ns */
if (!kuid_has_mapping(bprm->cred->user_ns, uid) ||
     !kgid_has_mapping(bprm->cred->user_ns, gid))

if (mode & S_ISUID) {
    bprm->per_clear |= PER_CLEAR_ON_SETID;
    bprm->cred->euid = uid;

if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
    bprm->per_clear |= PER_CLEAR_ON_SETID;
    bprm->cred->egid = gid;

So clearly, this is intentional.

This dates back to the original upload to github in May 2005:


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) {
        current->personality &= ~PER_CLEAR_ON_SETID;
        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)) {
        current->personality &= ~PER_CLEAR_ON_SETID;
        bprm->e_gid = inode->i_gid;

Googling for the comment leads to:


  1. Marking a file for mandatory locking
    A file is marked as a candidate for mandatory locking by setting the group-id bit in its file mode but removing the group-execute bit. This is an otherwise meaningless combination, and was chosen by the System V implementors so as not to break existing user programs.
    Note that the group-id bit is usually automatically cleared by the kernel when a setgid file is written to. This is a security measure. The kernel has been modified to recognize the special case of a mandatory lock candidate and to refrain from clearing this bit. Similarly the kernel has been modified not to run mandatory lock candidates with setgid privileges.

So the answer seems to be "because it was chosen to mean something else."


As you have edited your question to include this:

My question: why is capital S sgid ignored for executables?

It's not being ignored. S in your case means that the file isn't executable by the group and so it's benign. If you want the executable file to run with the permissions of the group then it needs to be executable by the group. You took that away with g-x which is why you are getting S. It will run with permissions of whomever executes it and not with permissions of the group.

  • That wasnt my question. +s is working for directories. The file created belong's to the directory owner's group, not the process' group. That is the correct behavior. It is not working for the executable that is outside of the directory. the process should be running with the effective permissions of the program owner's group, but it is not
    – user211221
    Feb 24, 2018 at 19:22
  • I'll update my answer but it's already been given by Praveen Khumar. +s means nothing for directories because directories aren't executable so you statement that it's working for directories is false. Feb 24, 2018 at 19:54
  • No, +s on a directory does mean something for directories. It means that files created in that directory belong the the directory's group owner, not to the process's group. And again, I AM NOT ASKING ABOUT DIRECTORIES, I am asking about S (capital S) on the program file and how the process is not getting the program's owner's group permissions. And yes, I edited my question, because you ignored what I actually asked and instead you answered what you thought I asked.
    – user211221
    Feb 24, 2018 at 20:08
  • Your eddied answer seems to go against POSIX. Can you link me to an authoritative source stating that this is the correct behaviour?
    – user211221
    Feb 24, 2018 at 20:09
  • No, s does not mean that files created in the directory belong to the directory groups owner. In your case, setgid means that the file is executed with the permissions of the group. It does not affect the ownership of the file in any way, shape, or form. I did not ignore what you said. It's that you weren't being clear. As has been said several times, S, in your case, means that the file isn't executable by the group and hence it's benign. You don't seem to have much understanding of jpw setgid and setuid actually function. Feb 24, 2018 at 20:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy