Why ptrace doesn't attach to process after setuid?
Asked Answered
T

1

7

I have a problem with my Linux daemon program. It starts with root privileges, does some configuration, then permanently drops privileges by switching to some user and group and continues working. The switch to the non-privileged user is done like this:

void switch_to_user_group(std::string const& username, std::string const& groupname)
{
    // Switch to user/group
    gid_t gid = getgid();
    if (!groupname.empty())
    {
        gid = get_group_id(groupname);
        if (0 != setgid(gid))
        {
            std::cout << "Failed to switch to group " << gid << std::endl;
            std::abort();
        }
    }

    if (!username.empty())
    {
        uid_t uid = get_user_id(username);
        if (initgroups(username.c_str(), gid) != 0)
        {
            std::cout << "initgroups failed" << std::endl;
            std::abort();
        }
        if (0 != setuid(uid))
        {
            std::cout << "Failed to switch to user " << uid << std::endl;
            std::abort();
        }
    }
}

The switch performs correctly, I can see the process in ps and top running under my user. The problem is that I can't attach to this process from gdb, even after it has dropped the privileges. The output is:

Attaching to process 15716
Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.

I'm running gdb under the same user the process switched to, and I am able to attach to other processes that were initially started under under that user. I tried this on Kubuntu 13.10 (YAMA is disabled), Debian 6 and 7 with the same result.

So my questions are:

  1. Why can't ptrace attach to a process that has the same effective and real UID as gdb?
  2. Is it possible to drop privileges of my program in a way so that I can attach to it from the unprivileged gdb? How?

Thanks.

Talyah answered 24/1, 2014 at 16:43 Comment(0)
T
10

I found the solution on my own.

There is a 'dumpable' flag in the kernel for every process. When the process performs setuid or setgid (at least, in my case, when the process drops privileges) this flag gets cleared and normal users can't attach to this process with a debugger, and the process crashes also do not produce a crash dump. This is done for security reasons to protect any sensitive data obtained with elevated privileges that may be in the process memory.

To solve the problem the process can explicitly allow debugging by setting the 'dumpable' flag to 1.

prctl(PR_SET_DUMPABLE, 1);

This has to be done after the setgid/setuid calls.

Talyah answered 27/1, 2014 at 9:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.