You know "rwx", but what is "rws" when run `ls -l` - Linux Tips
Tags: linux, bash, ubuntu
Published: 2020-01-21 21:22:56

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

```bash
$ ls -l /usr/bin/curl
-rwxr-xr-x 1 root root 223304 Sep  6 01:27 /usr/bin/curl
```

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

```bash
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59640 Jan 25  2018 /usr/bin/passwd
```

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](https://dev.to/0xbf/how-linux-stores-user-s-password-linux-tips-nm5) 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:

```bash
$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1104 Oct 15  2018 /etc/shadow
```

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:

```bash
$ whoami
john
$ passwd
Changing password for john.
(current) UNIX password:
```

After we typed our password, this password will be [hashed](https://dev.to/0xbf/how-linux-stores-user-s-password-linux-tips-nm5) 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:

```bash
ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59640 Jan 25  2018 /usr/bin/passwd
```

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:

```bash
$ whoami
john
$ passwd
Changing password for john.
(current) UNIX password:
```

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

```bash
$ ps axu | grep passwd
root   2397  0.0  0.3  52736  3612 pts/0    S+   14:50   0:00 passwd
```

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":

```c
#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;
}
```

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

```bash
$ ls -l ./example
-rwxrwxr-x 1 vagrant vagrant 8400 Jan 21 15:48 ./example
```

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

```bash
$ su coder
$ ./example
```

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
```

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

```bash
$ chmod u+s ./example
$ ls -l ./example
-rwsrwxr-x 1 vagrant vagrant 8400 Jan 21 15:48 ./example
```

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
```

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:

```bash
$ echo "" > a.txt
$ chmod u+s a.txt
$ ls -l a.txt
-rwSrw-r-- 1 vagrant vagrant 1 Jan 21 16:02 a.txt
```

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":

```bash
$ chmod +x a.txt
$ ls -l a.txt
-rwsrwxr-x 1 vagrant vagrant 1 Jan 21 16:02 a.txt
```

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
* https://en.wikipedia.org/wiki/Setuid
* http://man7.org/linux/man-pages/man2/setuid.2.html