posix_spawn and new used ID - Unix

This is a discussion on posix_spawn and new used ID - Unix ; Hello, I was looking into using posix_spawn in a context where I need to start a process with an other uid. I found this page: http://www.opengroup.org/onlinepubs/...sh_chap03.html which suggests the following code outline: Save = getuid(); setuid(newid); posix_spawn(...); setuid(Save); First I ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: posix_spawn and new used ID

  1. posix_spawn and new used ID

    Hello,

    I was looking into using posix_spawn in a context where I need to start a
    process with an other uid. I found this page:
    http://www.opengroup.org/onlinepubs/...sh_chap03.html

    which suggests the following code outline:
    Save = getuid();
    setuid(newid);
    posix_spawn(...);
    setuid(Save);

    First I guess setuid was only written as an informal indication, as
    setuid(Save) is likely not to work.

    Most importantly, this is very unsafe in a multi-threaded context. You
    need to get some kind of lock and make sure the other threads can't do
    anything where the uid matters (safest would be to suspend them all).

    It seems like this change of uid is really something that should be part
    of posix_spawn so its implementation would be responsible for taking all
    the precautions.

    Am I missing something?

  2. Re: posix_spawn and new used ID

    On Sep 19, 9:16*am, Marc wrote:

    > which suggests the following code outline:
    > Save = getuid();
    > setuid(newid);
    > posix_spawn(...);
    > setuid(Save);
    >
    > First I guess setuid was only written as an informal indication, as
    > setuid(Save) is likely not to work.


    That is correct. If we assume the original process is not root, the
    first 'setuid' will not work (assuming we're not setting it to what
    was already our effective user ID or something like that). If we
    assume it is root, the second 'setuid' will not work. It will work if
    and only if the process' effective and current user ID are different
    and the effective ID is not root.

    The correct way for a root process to change its user ID such that it
    can regain root privileges is with 'seteuid'. Sadly, this is not a
    POSIX function.

    > Most importantly, this is very unsafe in a multi-threaded context. You
    > need to get some kind of lock and make sure the other threads can't do
    > anything where the uid matters (safest would be to suspend them all).


    Right. Programs that change UID need to do so in a coordinated way.

    > It seems like this change of uid is really something that should be part
    > of posix_spawn so its implementation would be responsible for taking all
    > the precautions.


    POSIX does not assume it's possible for a non-root process to change
    its user ID, nor does it assume it's possible for a root process to
    change its user ID and then change back to root.

    > Am I missing something?


    Are you suggesting POSIX should add some capability that could only be
    used in root processes?

    DS

  3. Re: posix_spawn and new used ID

    On Sep 19, 9:56 am, David Schwartz wrote:
    > On Sep 19, 9:16 am, Marc wrote:
    >
    > > which suggests the following code outline:
    > > Save = getuid();
    > > setuid(newid);
    > > posix_spawn(...);
    > > setuid(Save);

    >
    > > First I guess setuid was only written as an informal indication, as
    > > setuid(Save) is likely not to work.

    >
    > That is correct. If we assume the original process is not root, the
    > first 'setuid' will not work (assuming we're not setting it to what
    > was already our effective user ID or something like that). If we
    > assume it is root, the second 'setuid' will not work. It will work if
    > and only if the process' effective and current user ID are different
    > and the effective ID is not root.


    Yep.


    > The correct way for a root process to change its user ID such that it
    > can regain root privileges is with 'seteuid'. Sadly, this is not a
    > POSIX function.


    It was added to POSIX in the 2001 revision. Oddly, setreuid() appears
    to have a longer history of standardization, along the X/Open line.


    > > Most importantly, this is very unsafe in a multi-threaded context.
    > > You need to get some kind of lock and make sure the other threads
    > > can't do anything where the uid matters (safest would be to
    > > suspend them all).

    >
    > Right. Programs that change UID need to do so in a coordinated way.


    In the specific case above, the POSIX_SPAWN_RESETIDS flag may be
    sufficient. As David pointed out above, the code only makes sense if
    it's changing between the effective and real user ids. If it's there
    to run the process as the real user id, then passing posix_spawn() an
    attribute object with the POSIX_SPAWN_RESETIDS flag set should be
    sufficient (assuming there aren't simultaneous group id issues
    involved...). The major case that doesn't work is if the process
    spends the bulk of its time running as its real id and the setuid()
    calls were there to switch to the effective user id just for the
    spawn. There's no posix_spawn() flag for running the new process as
    the saved user id....


    > > It seems like this change of uid is really something that should be
    > > part of posix_spawn so its implementation would be responsible
    > > for taking all the precautions.


    You did notice POSIX_SPAWN_RESETIDS, right?


    > POSIX does not assume it's possible for a non-root process to change
    > its user ID, nor does it assume it's possible for a root process to
    > change its user ID and then change back to root.


    With the addition of seteuid() (and setreuid() for XSI systems),
    that's not true...


    > > Am I missing something?

    >
    > Are you suggesting POSIX should add some capability that could
    > only be used in root processes?


    It wouldn't be the first. Obvious "root only" inclusions include the
    second argument to chown(), mlock(), perhaps clock_settime(), and some
    of the scheduling calls. (Yes, the first of those obviously has
    historical weight over doing a new chgrp() call.)

    Of course, POSIX just says "appropriate privileges" and does not
    actually require that the calls be restricted to those with an
    effective user id of zero. The various systems with fine-grained
    capability setups expand on that distinction to make them accessible
    without giving away the store.


    Philip Guenther

  4. Re: posix_spawn and new used ID

    On Sep 19, 11:33 pm, "guent...@gmail.com" wrote:
    > On Sep 19, 9:56 am, David Schwartz wrote:
    > > On Sep 19, 9:16 am, Marc wrote:
    > > > which suggests the following code outline:
    > > > Save = getuid();
    > > > setuid(newid);
    > > > posix_spawn(...);
    > > > setuid(Save);


    Grr. The original code snippet above shows that it uses getuid() to
    find the uid that it'll be returning to after the spawn, which means
    it's running as its real user id and doing the spawn as its saved user
    id, so this bit from my previous post applies:

    > The major case that [using POSIX_SPAWN_RESETIDS] doesn't work
    > is if the process spends the bulk of its time running as its real id and
    > the setuid() calls were there to switch to the effective user id just
    > for the spawn. There's no posix_spawn() flag for running the new
    > process as the saved user id....


    Darn. Perhaps you should encourage your OS vendor to extend the
    posix_spawn attributes object with fine-grained uid+gid support.

    In the mean time, calling fork, and then setuid and execle in the
    child, is apparently the only thread-safe way to achieve this.


    Philip Guenther


  5. Re: posix_spawn and new used ID

    "guenther@gmail.com" wrote:

    >> > which suggests the following code outline:
    >> > Save = getuid();
    >> > setuid(newid);
    >> > posix_spawn(...);
    >> > setuid(Save);

    [...]

    > In the specific case above, the POSIX_SPAWN_RESETIDS flag may be
    > sufficient. As David pointed out above, the code only makes sense if
    > it's changing between the effective and real user ids. If it's there
    > to run the process as the real user id, then passing posix_spawn() an
    > attribute object with the POSIX_SPAWN_RESETIDS flag set should be
    > sufficient (assuming there aren't simultaneous group id issues
    > involved...).


    Actually, my goal is to have a priviledged process that spawns processes
    under various other uids (and I am not going to use setuid but more
    likely seteuid).

    > You did notice POSIX_SPAWN_RESETIDS, right?


    Yes. And that is part of what makes me wonder why "they" did not make
    this mechanism more powerful.

    >> Are you suggesting POSIX should add some capability that could
    >> only be used in root processes?

    >
    > It wouldn't be the first. Obvious "root only" inclusions include the
    > second argument to chown(), mlock(), perhaps clock_settime(), and some
    > of the scheduling calls. (Yes, the first of those obviously has
    > historical weight over doing a new chgrp() call.)
    >
    > Of course, POSIX just says "appropriate privileges" and does not
    > actually require that the calls be restricted to those with an
    > effective user id of zero. The various systems with fine-grained
    > capability setups expand on that distinction to make them accessible
    > without giving away the store.


    Thank you both for the answers. Yes, I believe that would be a useful
    extension.

+ Reply to Thread