LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   setuid on different pid or child-process (http://www.linuxquestions.org/questions/programming-9/setuid-on-different-pid-or-child-process-826989/)

thelogix 08-18-2010 07:55 AM

setuid on different pid or child-process
 
Hia all.

I have a root process (on linux) that forks a child and the child process then drops privileges by doing a setuid() to a normal user.

After the child setuid()'s, it is of course impossible for it to gain root again by itself. But since the main process is still running as root, i was wondering if there was a simple/smart way of getting the root-master-process to elevate the child back to root (or maybe just to another non-privi uid).

Is there some way to do a setuid() on another pid? or maybe something can be done through /proc/<pid>/?

Any idea's?

Killing the child is not an option (because its what it does today and im trying to find a smarter way).

(The program is apache2's mpm-itk worker and the "child" is the actual apache2 process serving a page.)

unSpawn 08-18-2010 12:34 PM

Quote:

Originally Posted by thelogix (Post 4070194)
(..) since the main process is still running as root, i was wondering if there was a (..) way (..) to elevate the child back to root (..) The program is apache2's mpm-itk worker and the "child" is the actual apache2 process (..)

In this specific case understanding the reasons why privileges are separated between the root-owned master and unprivileged children should show you the question is not about a "simple/smart way" of doing things but doing things the right or the wrong way. Unless you're smarter than the Apache devs of course.

wje_lq 08-18-2010 12:38 PM

Quote:

Originally Posted by thelogix (Post 4070194)
Is there some way to do a setuid() on another pid? or maybe something can be done through /proc/<pid>/?

Any idea's?

Absolutely none (other than losing the gratuitous apostrophe). Can't be done.

thelogix 08-19-2010 08:10 AM

Quote:

Originally Posted by unSpawn (Post 4070448)
In this specific case understanding the reasons why privileges are separated between the root-owned master and unprivileged children should show you the question is not about a "simple/smart way" of doing things but doing things the right or the wrong way. Unless you're smarter than the Apache devs of course.

Apparently you dont know what mpm-itk is. (Which is not made by the Apache devs, of course.)
I understand all the reasons perfectly. This was not a "please-explain-to me-the-basics-of-privilege-separation"-post and im sorry if the post title gave you that idea. Ill post that question in the "Linux - Newbie" forum if i ever need your guidance on that ;)

wje_lq 08-19-2010 09:49 AM

Quote:

Originally Posted by thelogix (Post 4071200)
Apparently you dont know what mpm-itk is. (Which is not made by the Apache devs, of course.)

I didn't know what it was until you mentioned its name, but I just googled it, and, um, it seems to be a short name for apache2-mpm-itk. I found this, and I would assume that it's brought to us by the Apache developers.

What am I missing?

thelogix 08-20-2010 06:42 AM

Quote:

Originally Posted by wje_lq (Post 4071319)
I didn't know what it was until you mentioned its name, but I just googled it, and, um, it seems to be a short name for apache2-mpm-itk. I found this, and I would assume that it's brought to us by the Apache developers.

Well.. I guess that depends on the definition of an Apache Developer. I have patches in the official linux-kernel, but that doesnt really make me a "Kernel Developer". :).

(Of course, for the purpose of my post, it was irrelevant what product it was for and i added simply because it is polite to do so :))

mpm-itk however, is an third-party, experimental, MPM module and it is pretty widely used around the globe.
(More about MPM's here: http://httpd.apache.org/docs/2.0/mpm.html)

mpm-itk is (yet-another) attempt to solve the issues that arise, due to apache2 running everything under one user (ie. on debian, user "www-data").
It does so, by running as root and upon receiving the "Host: " header with the hostname of the site, it looks in the config to find what username to setuid to for that specific host.
So basically isolating each website to one specific user (usually the same as the FTP user for the site).

Works pretty well, but there is a known caveat, which is (so far) unsolved. If you try to get a page from a different hostname on the SAME TCP connection, the process wont have access to the other users pages. So far, the solution is to kill the child, having the client (browser) simply reconnect. This is, of course, not very fast on very busy sites.

So im just investigating 2 different routes around this. The one here, is the idea of having the master (root owned) process, grant the child a new setuid() to a different user.
The other is handing over existing connections between childs, which im told is rather hairy. But so is my setuid() idea, it would seem :)

estabroo 08-20-2010 10:30 AM

Instead of using setuid how about using seteuid. This would reduce the privs but still allow the process to use seteuid again to regain full privs.

Code:

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>

int main(int argc, char* argv[]) {
        int err;
        int fd;
        err = seteuid(1000);

        fd = open ("/tmp/test1", O_RDWR|O_CREAT, 0600);
        write(fd, "test\n", 5);
        close(fd);
        seteuid(0);
        fd = open ("/tmp/test2", O_RDWR|O_CREAT, 0600);
        write(fd, "test\n", 5);
        close(fd);
}


thelogix 08-21-2010 05:13 AM

estabroo:

Thanks for the idea. Though it would actually work, it defeats the purpose i think, to allow the process itself to regain root. Also, wouldn't any child of this process also be able to seteuid(0)?

estabroo 08-21-2010 08:50 AM

any child process that you didn't explicity set the real user id on would be able to seteuid(0), but you could set that id after a fork and before exec'ing mitigating most of the risk

estabroo 08-25-2010 08:13 PM

ran across something interesting today in line with this question. You might be able to do exactly what you what using a couple of deprecated functions and capabilities (depends on what your kernel is setup for)

capgetp and capsetp are for getting and setting various capabilities on other processes, so you could give them what they would need to do what you want, CAP_SETUID in particular for just allowing them to change their uid.

thelogix 08-26-2010 05:29 AM

Quote:

Originally Posted by estabroo (Post 4077843)
ran across something interesting today in line ....
capgetp and capsetp are for getting and setting various capabilities on other processes, so you could give them what they would need to do what you want, CAP_SETUID in particular for just allowing them to change their uid.

That is actually VERY interesting. Almost excactly what i was hoping for.. Though, when you call them "deprecated" it does send a small chill down my spine. Are you certain they are deprecated?

Also, this does gives rise to an alternative idea. If its all a question of temporarily granting CAP_SETUID it might be possible to make an LSM module for the kernel, or even a patch to AppArmor, that allows a single process to grant & revoke capabillities on other processes.

Great find estabroo.. Ill look into it.

estabroo 08-26-2010 06:32 PM

pretty sure. excerpt from the cap_get_proc man page

NOTES
The library also supports the deprecated functions:

int capgetp(pid_t pid, cap_t cap_d);

int capsetp(pid_t pid, cap_t cap_d);

capgetp() attempts to obtain the capabilities of some other process; storing the capabilities in a
pre-allocated cap_d.See cap_init() for information on allocating an empty capability set. This
function, capgetp(), is deprecated, you should use cap_get_pid().

capsetp() attempts to set the capabilities of some other process(es), pid. If pid is positive it
refers to a specific process; if it is zero, it refers to the current process; -1 refers to all
processes other than the current process and process '1' (typically init(8)); other negative val-
ues refer to the -pid process group. In order to use this function, the kernel must support it
and the current process must have CAP_SETPCAP raised in its Effective capability set. The capabil-
ities set in the target process(es) are those contained in cap_d.


All times are GMT -5. The time now is 10:20 PM.