alice and bob both belong to the staff group.

I've got the following folder:

drwxrwxr-x 2 alice staff 4096 Oct 30 14:45 share

with the following files inside the folder:

-rwsr-xr-x 1 alice alice 8768 Oct 30 14:45 display-foo
-rw------- 1 alice alice 24 Oct 30 14:45 foo.txt

display-foo is a binary file that essentially displays the contents of foo.txt using the cat command.

When alice runs ./display-foo, the binary file executes successfully and the contents of foo.txt are displayed. However, when bob runs ./display-foo, the binary file executes successfully but the contents of the foo.txt are not displayed, yielding the error /bin/cat: /home/alice/share/foo.txt: Permission denied.

From my understanding, setting the setuid bit allows the binary executable to be executed with the privileges of the file's owner (in this case, alice). Why, then, was bob not allowed to view the contents of foo.txt?

ADDENDUM: I have recompiled my binary file with the geteuid() function so that it prints out the effective user ID (EUID). Indeed, when bob executes the binary file, the EUID is that of alice. Yet, permission is denied. Here's a snippet of the source code:

printf("%d", geteuid());
system("/bin/cat /home/alice/share/foo.txt");
  • @SatōKatsura Yup, it is a binary file (compiled using gcc from a .c program). – JTJM Oct 30 '17 at 7:35
  • 4
    Commands run with system() don't inherit the privileged UID. Try fopen() etc. instead. – Satō Katsura Oct 30 '17 at 7:38
  • Thank you @SatōKatsura , it works like a charm. I'm guessing this is some sort of security feature by Ubuntu. – JTJM Oct 30 '17 at 8:12
  • 1
    Nope, it's standard UNIX semantics. – Satō Katsura Oct 30 '17 at 8:13
  • I can't reproduce this (running Debian 9, GCC 6.3.0). The setuid bit seems to be doing its job, even with the system call. Any thoughts? – igal Nov 4 '17 at 16:45

I read through the manual page for the system function and came across the following passage which offers an explanation:

Do not use system() from a program with set-user-ID or set-group-ID
privileges, because strange values for some environment variables
might be used to subvert system integrity.  Use the exec(3) family of
functions instead, but not execlp(3) or execvp(3).  system() will
not, in fact, work properly from programs with set-user-ID or set-
group-ID privileges on systems on which /bin/sh is bash version 2,
since bash 2 drops privileges on startup.  (Debian uses a modified
bash which does not do this when invoked as sh.)

Here are some other StackExchange posts that I read through on my way to that passage:

For posterity, and because the given example might be useful for diagnosing this or similar issues in other contexts, I've kept my original below.

Is it possible that you're running into a bug? I was unable to reproduce your problem in a Docker container running Debian 9 with gcc 6.3. Here is how I went about trying to recreate the scenario described in your post.

First create the "alice" and "bob" users and them to the "staff" group:

useradd -m -G staff alice
useradd -m -G staff bob

Next create the file and set its ownership and permissions:

# Create a subdirectory to hold the text file
sudo -u alice mkdir -p /home/alice/share/

# Create the text file
sudo -u alice bash -c 'echo "This is foo.txt" > /home/alice/share/foo.txt'

# Set restrictive permissions on the text file
chmod u=rw,g=,o= /home/alice/share/foo.txt

Let's check the results:

$ ls -l /home/alice/share/foo.txt
-rw------- 1 alice alice 16 Nov  4 15:33 /home/alice/share/foo.txt

Now let's create a version of display-foo which uses the system function:

$ cat <<HEREDOC > /usr/local/src/display-foo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>

int main(int argc, char **argv) {

    struct passwd *r_pwd = getpwuid(getuid());
    printf("Real user: %s\n", r_pwd->pw_name);

    struct passwd *e_pwd = getpwuid(geteuid());
    printf("Effective user: %s\n", e_pwd->pw_name);

    system("/bin/cat /home/alice/share/foo.txt");

$ gcc /usr/local/src/display-foo.c -o /usr/local/bin/display-foo

And let's set ownership and permissions on display-foo, including setting the setuid bit:

chown alice:alice /usr/local/bin/display-foo
chmod u=rwx,g=rx,o=rx /usr/local/bin/display-foo
chmod u+s /usr/local/bin/display-foo

Let's also check the result:

$ ls -l /usr/local/bin/display-foo
-rwsr-xr-x 1 alice alice 8640 Nov  4 15:40 /usr/local/bin/display-foo

Now we run the program both as alice and as bob:

$ sudo -u alice display-foo

Real user: alice
Effective user: alice
This is foo.txt

$ sudo -u bob display-foo

Real user: bob
Effective user: alice
This is foo.txt

As you can see, it looks like everything is working as expected.

| improve this answer | |
  • 1
    I've replicated every single step listed above. Same result. Running the binary as alice prints (Real user: alice, Effective user: alice, This is foo.txt). Running the binary as bob prints (Real user: bob, Effective user: alice, /bin/cat: /home/alice/share/foo.txt: Permission denied). In other words, bob had the permission to run the binary, but somehow was unable to execute the system() instruction, as mentioned by Sato. Very very peculiar. – JTJM Nov 6 '17 at 5:43
  • @JTJM I think I figured it out. See the update to my solution. – igal Nov 6 '17 at 12:21

The foo.txt file is in a share directory in Alice home directory,so Bob can not access the files in Alice home directory because of permissions. you can create a shared directory in home, and givin both permissions to access this directory.

or, you can create a shared directory with groupowner of staff and set SGID bit with this command:

chmod 2777 sharedDir

when the SGID bit is set on a directory, new files or sub-directories created in the original directory will inherit the group ownership of the directory rather than be based on the user's current default group.

so when Alice create a file here, group ownership of the file will be STAFF and all of the member of this gorup can access these files base on staff group permission.

| improve this answer | |
  • Correct in that bob can't read foo.txt. But ./display-foo is setuid alice, which means it runs with alice's permissions and access rights, and the OP is asking why this program still can't read foo.txt. – roaima Aug 22 '18 at 14:26
  • @roaima my post has been updated – anis Aug 26 '18 at 13:31

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.