DEV Community

BC
BC

Posted on • Edited on

You know "rwx", but what is "rws" when run `ls -l` - Linux Tips

You already know what "rwx" is when run ls -l: readable, writable and executable. For example:

$ ls -l /usr/bin/curl
-rwxr-xr-x 1 root root 223304 Sep  6 01:27 /usr/bin/curl
Enter fullscreen mode Exit fullscreen mode

Occasionally, you will see the a "s" in rws instead of "x", for example:

ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59640 Jan 25  2018 /usr/bin/passwd
Enter fullscreen mode Exit fullscreen mode

Do you notice the "s" in the first part "rws"? So what is this "s"?

Before we answer it, let's check another problem:

Who can modify /etc/shadow?

In a previous post I explained how linux store user's password - it will hash user's password and store it in file /etc/shadow. Let's check this file's permission:

$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1104 Oct 15  2018 /etc/shadow
Enter fullscreen mode Exit fullscreen mode

Ok, so clearly only root user can change the file content. Now let's say we logged in as user "john" and wants to change our password using the passwd cli:

$ whoami
john
$ passwd
Changing password for john.
(current) UNIX password:
Enter fullscreen mode Exit fullscreen mode

After we typed our password, this password will be hashed and saved to /etc/shadow file. But in this process, we never su to root user, and we know only root user can change the content of /etc/shadow. So why the set-password process as "john" still succeeded?

The "s" in "rws"

The answer lays on the "s" in "rws". It means "set-uid" when run this program: the program doesn't run with the privilege of user who ran it, instead, with the privilege of file owner. For example:

ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59640 Jan 25  2018 /usr/bin/passwd
Enter fullscreen mode Exit fullscreen mode

The passwd cli belongs to the root user and because of this "s", anyone run the passwd program will be run as the root user. That's why as a non-root user, we can still call passwd to change the /etc/shadow file.

Let's prove it:

$ whoami
john
$ passwd
Changing password for john.
(current) UNIX password:
Enter fullscreen mode Exit fullscreen mode

Don't set the password, now open another terminal window, run:

$ ps axu | grep passwd
root   2397  0.0  0.3  52736  3612 pts/0    S+   14:50   0:00 passwd
Enter fullscreen mode Exit fullscreen mode

You can see the actual user who runs passwd is root!

How to set this "set-uid" flag?

In Linux we can simply use chmod u+s to set the "set-uid" flag. Let's have a try. First we write a program as a non-root user "vagrant":

#include <stdio.h>

int main() {
    int answer = 0;
    printf("1+1=?\n");
    scanf("%d", &answer);
    if (answer ==2 ) {
        printf("Correct!\n");
    } else {
        printf("Try again!\n");
    }
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Compile it: gcc example.c -o example, if we run ls -l, we see "rwx":

$ ls -l ./example
-rwxrwxr-x 1 vagrant vagrant 8400 Jan 21 15:48 ./example
Enter fullscreen mode Exit fullscreen mode

Now let's switch to another user coder and run this program:

$ su coder
$ ./example
Enter fullscreen mode Exit fullscreen mode

In another terminal run ps axu | grep example, we can see the program runs under coder (remember we haven't set the set-uid flag yet):

coder   2468  0.0  0.0  4508   820 pts/0  S+  15:49   0:00 ./example
Enter fullscreen mode Exit fullscreen mode

Now let's switch back to user "vagrant" and add the "set-uid" flag with chmod u+s:

$ chmod u+s ./example
$ ls -l ./example
-rwsrwxr-x 1 vagrant vagrant 8400 Jan 21 15:48 ./example
Enter fullscreen mode Exit fullscreen mode

We can see the "s" is set. Now switch back to user "coder", run this program ./example again. In the other terminal run ps axu | grep example:

vagrant  2493  0.0  0.0   4508   744 pts/0  S+   15:57   0:00 ./example
Enter fullscreen mode Exit fullscreen mode

You can see although current user is "coder", now the program runs under user "vagrant", which is the file owner.

But what is "rwS"?

Very rarely you will see an uppercase "S" in "rwS". If we do this:

$ echo "" > a.txt
$ chmod u+s a.txt
$ ls -l a.txt
-rwSrw-r-- 1 vagrant vagrant 1 Jan 21 16:02 a.txt
Enter fullscreen mode Exit fullscreen mode

Do you notice the uppercase "S" here? It indicates that this file's "set-uid" flag is set, but the executable flag "x" is not set. If we set this file to be executable, it will show the lowercase "s":

$ chmod +x a.txt
$ ls -l a.txt
-rwsrwxr-x 1 vagrant vagrant 1 Jan 21 16:02 a.txt
Enter fullscreen mode Exit fullscreen mode

The point is, the "set-uid" flag and the "executable" flag are separated. Set "+s" doesn't mean it will be auto set with "+x".

Caveat

You should be careful on using this "set-uid" flag. Imagine a program's owner is root and has this "set-uid" flag set, means any non-root user will be promoted to the root user to run this program, which might be dangerous. So only set this flag when it is really necessary.

Reference

Top comments (2)

Collapse
 
deciduously profile image
Ben Lovy

Huh, TIL. Thanks.

Collapse
 
moopet profile image
Ben Sinclair

TIL capital S.