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

[Question/Information]: Use of process_vm_readv on linux requires ptrace capability #578

Closed
Forbinn opened this issue Jul 16, 2021 · 3 comments · Fixed by #641
Closed

[Question/Information]: Use of process_vm_readv on linux requires ptrace capability #578

Forbinn opened this issue Jul 16, 2021 · 3 comments · Fixed by #641

Comments

@Forbinn
Copy link

Forbinn commented Jul 16, 2021

Hello,

I use docker in order to build the sentry-native SDK on Linux and until the version 0.4.11 everything was fine. But from this version, the unit test included inside the SDK starts to fail with the following error:

Test buildid_fallback...                        [ FAILED ]
  test_modulefinder.c:148: Check strcmp(sentry_value_as_string(sentry_value_get_by_key(with_id_val, "code_id")), "1c304742f114215453a8a777f6cdb3a2b8505e11") == 0... failed
    Expected: 1c304742f114215453a8a777f6cdb3a2b8505e11
    Received: 
  test_modulefinder.c:151: Check strcmp(sentry_value_as_string(sentry_value_get_by_key( with_id_val, "debug_id")), "4247301c-14f1-5421-53a8-a777f6cdb3a2") == 0... failed
    Expected: 4247301c-14f1-5421-53a8-a777f6cdb3a2
    Received: 00000000-0000-0000-0000-000000000000
  test_modulefinder.c:165: Check strcmp(sentry_value_as_string(sentry_value_get_by_key(x86_exe_val, "code_id")), "b4c24a6cc995c17fb18a65184a65863cfc01c673") == 0... failed
    Expected: b4c24a6cc995c17fb18a65184a65863cfc01c673
    Received: 
  test_modulefinder.c:168: Check strcmp(sentry_value_as_string(sentry_value_get_by_key( x86_exe_val, "debug_id")), "6c4ac2b4-95c9-7fc1-b18a-65184a65863c") == 0... failed
    Expected: 6c4ac2b4-95c9-7fc1-b18a-65184a65863c
    Received: 00000000-0000-0000-0000-000000000000
  test_modulefinder.c:184: Check strcmp(sentry_value_as_string(sentry_value_get_by_key( without_id_val, "debug_id")), "29271919-a2ef-129d-9aac-be85a0948d9c") == 0... failed
    Expected: 29271919-a2ef-129d-9aac-be85a0948d9c
    Received: 00000000-0000-0000-0000-000000000000
  test_modulefinder.c:200: Check strcmp(sentry_value_as_string(sentry_value_get_by_key( x86_lib_val, "debug_id")), "7fa824da-38f1-b87c-04df-718fda64990c") == 0... failed
    Expected: 7fa824da-38f1-b87c-04df-718fda64990c
    Received: 00000000-0000-0000-0000-000000000000

Because this was not happening when I wasn't using docker I started investigating the issue and I found the problem.
The process_vm_readv syscall was causing the issue because it returned an EPERM error and of course of subsequent call will also fail resulting in the previous error.

This syscall is used to safely read data from a certain region in memory and making sure you have the right to (So this is a good thing). Its uses was introduced in commit 959b81e and this why the problem didn't occur before.

The man page of process_vm_readv precise that Permission to read from or write to another process is governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS check; see ptrace(2). and the docker page precise Restrict process inspection capabilities, already blocked by dropping CAP_SYS_PTRACE. (https://docs.docker.com/engine/security/seccomp/).
So you can easily fix the issue by adding the --cap-add=CAP_SYS_PTRACE to your docker container and after that everything runs fine.

Because the code that uses process_vm_readv is in the SDK it-self and not in the unit test, I tough that it would we wise to inform you of this as some people may have problem if they use your SDK inside a docker.

@Swatinem
Copy link
Member

Thanks for the report!

I wasn’t really aware this was blocked by ptrace/seccomp permissions. The change was in response to reports specifically from android where the previous modulefinder was causing segfaults (presumably). So being able to poke safely at random memory addresses is the only way around that right now that I can think of.
Do you have any idea on how to work around this limitation?

@Forbinn
Copy link
Author

Forbinn commented Jul 16, 2021

Well, to be honest, no I don't have a solution that works perfectly and efficiently. But after digging and avoiding all people that tells you that you cannot do that I found a "solution".

Before giving it to you, I want to tell that I don't really like it but since I haven't been able to find anything else, here it is:

static bool
read_safely(void *dst, void *src, size_t size)
{
    int fd = open("/dev/random", O_WRONLY);
    bool res = write(fd, src, size) != -1; 
    close(fd);

    if (!res)
        return false;

    memcpy(dst, src, size);
    return true;
}

(Some sources I used: https://www.generacodice.com/en/articolo/601717/isbadreadptr-analogue-on-unix, https://stackoverflow.com/questions/4611776/isbadreadptr-analogue-on-unix)

In the stackoverflow source, some people talk about using an anonymous pipe instead of /dev/random in case it doesn't exists or isn't writable.

I have tested it on a docker container without the cap-add flag and it works (i.e. all unit tests passes) but from a performance (and clarity, and weird tricks) point of view I think this is not the best solution you can find. And I cannot confirm that it will work on Android platform. But maybe this will give you an idea about how to do it properly.

@GenuineAster
Copy link
Contributor

Any way this could be prioritized? We have been missing reports of several critical server crashes as a result of this. Could we revert the change on Linux systems and just call the safe read on Android systems? In the meantime we will revert to 0.4.10, I guess.

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 a pull request may close this issue.

3 participants