LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Why can a simple daemon get root permissions, apparently violating security model? (https://www.linuxquestions.org/questions/linux-software-2/why-can-a-simple-daemon-get-root-permissions-apparently-violating-security-model-4175536331/)

mjl3434 03-10-2015 08:07 PM

Why can a simple daemon get root permissions, apparently violating security model?
 
I'm writing a C++ based Linux software daemon for a project that I am working on. Rather than use the system call daemon() defined in <unistd.h> "man 3 daemon", as a learning exercise and for more control I decided to do all of the system calls myself. I found several examples, but ultimately decided to follow the sequence of systems calls given in Richard Stevens' famous tome "UNIX Network Programming, Volume 1". Specifically second 13.4 in chapter 13. Stevens' has the following calls listed:

fork();
setsid();
fork();
umask(0);
chdir("/");
close();

When I follow this sequence it does appear to successfully create a daemon. To my surprise however the daemon is running as the root user! This is annoying because it is running on an Ubuntu 13.04 server which I don't have sudo on.

Code:

larwillm@ubuntu1304$ ps -ef|grep MyDaemon
root    26040    1  0 17:06 ?        00:00:00 MyDaemon
larwillm 26750 18288  0 17:32 pts/14  00:00:00 grep --color=always MyDaemon

My user "larwillm" does not have root permissions, or sudo. The daemon I created however "MyDaemon" is running as the root user with PID of 26040, and a Parent PID of 1, meaning init is it's parent. This confuses me, how is such a thing possible? Doesn't this totally violate user permissions? If it truly is running as root, it seems like it would not take much extra work to write a daemon, which listens on some localhost UDP socket, awaiting commands I send it, and then the daemon could simply spawn a system("command received on UDP socket") system call which can then execute any command I want.

Can someone please explain what is going on here?
How was I able to run a process with root permissions even though I'm not root?
Is this process truly running as root? Does it have full root permissions?
Does this violate the Linux user permissions security model?
Could a properly configured SELinux prevent me from doing this?

The full code is below, even though I have attempted to comment the reasons behind each step it does not mean I understand them. All of the process group / session / setsid / umask stuff is new to me (hence the learning exercise).

Code:

static void daemonize()
{
    pid_t pid;

    // Fork so that the child isn't a process group leader, required for setsid
    pid = fork();

    // An error occured
    if (pid < 0)
    {
        std::cerr << appName << __FUNCTION__ << ":" << __LINE__
                  << " : Could not fork first child process: "
                  << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    }

    // Success, let the parent terminate
    if (pid > 0)
    {
        exit(EXIT_SUCCESS);
    }

    // Become a session leader
    if (setsid() < 0)
    { 
        std::cerr << appName << __FUNCTION__ << ":" << __LINE__
                  << " : Could not become session leader: "
                  << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    } 

    // Fork for a second time
    pid = fork();

    // An error occured
    if (pid < 0)
    { 
        std::cerr << appName << __FUNCTION__ << ":" << __LINE__
                  << " : Could not fork second child process: "
                  << strerror(errno) << std::endl;
        exit(EXIT_FAILURE);
    } 

    // Success, let the parent terminate
    if (pid > 0)
    { 
        exit(EXIT_SUCCESS);
    } 

    // Set file permissions to everything
    umask(0);

    // Change the working directory
    if (chdir(workingDirectory) < 0)
    {
        std::cerr << appName << __FUNCTION__ << ":" << __LINE__
                  << " : Could not change working directory to "
                  << workingDirectory << std::endl;
    }

    // Close all open file descriptors
    int max = sysconf(_SC_OPEN_MAX);
    for (int i = 0; i < max; i++)
    {
        close(i);
    }
}


mjl3434 03-10-2015 08:18 PM

This was just a coincidence. My process was not actually named "MyDaemon", it was actually named "NetworkManager", which I confused with an existing daemon running on the Ubuntu server. My daemon does not appear to get root permissions.


All times are GMT -5. The time now is 08:27 PM.