Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect the agent running in a non-root PID namespace #1993

Merged
merged 1 commit into from
Sep 11, 2023

Conversation

javierhonduco
Copy link
Contributor

In Linux resources such as users, processes, mounts, time, etc. can be isolated with namespaces 0. They are used in tamden with cgroups to implement resource control in containers.

Both namespaces and cgroups are conceptually a hierarchy, where the first namespace is the root of the tree and the common ancestor for all the other slices of the machine.

The Agent requires to be run in the 'root' (this has nothing to do with permissions or users, necessarily) PID namespace, where all the other processes for every single namespace can be queried.

While the kernel does not provide a facility for this check, this commit aims to bring a reliable check to see whether we are inside of a PID namespace or not. It does it with a BPF program that retrieves the pid of the Agent and then we compare it with the pid that the OS gives us in userspace via getpid(2). As the BPF program always gives the PID from the PoV of the root PID namespace, we can tell if we are in the root namespace or not.

This uses code from this PoC 1.

Test Plan

running the Agent normally, in the root PID namespace

[root@fedora parca-agent]# dist/parca-agent
[works]

under a non-root PID namespace

[javierhonduco@fedora parca-agent]$ sudo unshare --fork --pid --mount-proc
[root@fedora parca-agent]# dist/parca-agent
ooooooooo.                                                  .o.                                            .
`888   `Y88.                                               .888.                                         .o8
 888   .d88'  .oooo.   oooo d8b  .ooooo.   .oooo.         .8"888.      .oooooooo  .ooooo.  ooo. .oo.   .o888oo
 888ooo88P'  `P  )88b  `888""8P d88' `"Y8 `P  )88b       .8' `888.    888' `88b  d88' `88b `888P"Y88b    888
 888          .oP"888   888     888        .oP"888      .88ooo8888.   888   888  888ooo888  888   888    888
 888         d8(  888   888     888   .o8 d8(  888     .8'     `888.  `88bod8P'  888    .o  888   888    888 .
o888o        `Y888""8o d888b    `Y8bod8P' `Y888""8o   o88o     o8888o `8oooooo.  `Y8bod8P' o888o o888o   "888"
                                                                      d"     YD
                                                                      "Y88888P'

level=info name=parca-agent ts=2023-09-07T10:42:25.892675407Z caller=main.go:345 msg="maxprocs: Leaving GOMAXPROCS=12: CPU quota undefined"
level=error name=parca-agent ts=2023-09-07T10:42:25.925707031Z caller=main.go:374 msg="the agent must be run in the 'root' PID namespace"

@javierhonduco javierhonduco requested a review from a team as a code owner September 7, 2023 10:46
@@ -283,6 +287,12 @@ func main() {
os.Exit(1)
}

bpf.SetLoggerCbs(bpf.Callbacks{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the libbpf logger setter here to ensure that we do this before loading any BPF program

Copy link
Member

@kakkoyun kakkoyun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@javierhonduco javierhonduco force-pushed the root-namespace-detector branch 4 times, most recently from b246f67 to d7198b6 Compare September 11, 2023 10:13
In Linux resources such as users, processes, mounts, time, etc. can be
isolated with namespaces [0]. They are used in tamden with cgroups to implement
resource control in containers.

Both namespaces and cgroups are conceptually a hierarchy, where the first
namespace is the root of the tree and the common ancestor for all the
other slices of the machine.

The Agent requires to be run in the 'root' (this has nothing to do with
permissions or users, necessarily) PID namespace, where all the other
processes for every single namespace can be queried.

While the kernel does not provide a facility for this check, this commit
aims to bring a reliable check to see whether we are inside
of a PID namespace or not. It does it with a BPF program that retrieves
the pid of the Agent and then we compare it with the pid that the OS
gives us in userspace via `getpid(2)`. As the BPF program always gives
the PID from the PoV of the root PID namespace, we can tell if we are in
the root namespace or not.

This uses code from this PoC [1].

Test Plan
=========

**running the Agent normally, in the root PID namespace**

```
[root@fedora parca-agent]# dist/parca-agent
[works]
```

**under a non-root PID namespace**

```
[javierhonduco@fedora parca-agent]$ sudo unshare --fork --pid --mount-proc
[root@fedora parca-agent]# dist/parca-agent
ooooooooo.                                                  .o.                                            .
`888   `Y88.                                               .888.                                         .o8
 888   .d88'  .oooo.   oooo d8b  .ooooo.   .oooo.         .8"888.      .oooooooo  .ooooo.  ooo. .oo.   .o888oo
 888ooo88P'  `P  )88b  `888""8P d88' `"Y8 `P  )88b       .8' `888.    888' `88b  d88' `88b `888P"Y88b    888
 888          .oP"888   888     888        .oP"888      .88ooo8888.   888   888  888ooo888  888   888    888
 888         d8(  888   888     888   .o8 d8(  888     .8'     `888.  `88bod8P'  888    .o  888   888    888 .
o888o        `Y888""8o d888b    `Y8bod8P' `Y888""8o   o88o     o8888o `8oooooo.  `Y8bod8P' o888o o888o   "888"
                                                                      d"     YD
                                                                      "Y88888P'

level=info name=parca-agent ts=2023-09-07T10:42:25.892675407Z caller=main.go:345 msg="maxprocs: Leaving GOMAXPROCS=12: CPU quota undefined"
level=error name=parca-agent ts=2023-09-07T10:42:25.925707031Z caller=main.go:374 msg="the agent must be run in the 'root' PID namespace"
```

[0]: https://man7.org/linux/man-pages/man7/namespaces.7.html
[1]: https://github.com/javierhonduco/am-i-contained/tree/main
Copy link
Member

@kakkoyun kakkoyun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: it!

@kakkoyun kakkoyun merged commit 67f3fec into parca-dev:main Sep 11, 2023
22 checks passed
@javierhonduco javierhonduco deleted the root-namespace-detector branch September 11, 2023 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants