On 03/27/2018 03:36 PM, Ian Jackson wrote:
> George Dunlap writes ("Re: [PATCH] docs/qemu-deprivilege: Revise and update 
> with status and future plans"):
>> On 03/27/2018 02:33 PM, Ian Jackson wrote:
>>> Anyway IMO we should set RLIMIT_NPROC after fork and before execve.
>>> If this causes setuid to fail in qemu, qemu will crash.  But this
>>> could only be the case if the new uid already has other processes,
>>> which it shouldn't do.  (If it does, the new uid is probably
>>> contaminated by a previous domain with the same domid.)
>>
>> I was more worried about the limit not having the expected effect after
>> the setuid().
> 
> I think we can safely rule that out.
> 
>>> I could find nothing in SuS explaining when process A may send signals
>>> to process B.  So I resorted to the BSD manpages:
>>>
>>>   https://www.unix.com/man-page/freebsd/2/kill/
>>>
>>>   For a process to have permission to send a signal to a process
>>>   designated by pid, the user must be the super-user, or the real or
>>>   saved user ID of the receiving process must match the real or
>>>   effective user ID of the sending process.
>>
>> The text of both the FreeBSD and Linux man pages looks to be copied
>> verbatim from [1].
>>
>> [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html
> 
> I don't know how I missed that.  It's the 2nd paragraph!
> 
>>> `pet' could be a uid associated with a reserved domid, eg dom0.
>>
>> Right -- it looks like that could work.  I hadn't initially noticed the
>> {RUID, SUID} => {RUID, EUID} distinction.
>>
>> It's kind of hard to believe this is so difficult to pull off.
> 
> Yes!
> 
>> Should we post this to that forum, for the benefit of other people who
>> end up finding the same discussion? :-)
> 
> Tempting.  Let's wait until we see if it works, first ...

Seems to work for me.  See the attached proof-of-concept programs.

If in the "reaper" program you change 'xuid' to DEFAULT_TARGET_UID
instead, then it does indeed die in usleep; with a separate 'real'
userid it survives and "runner" dies.

 -George
#ifndef COMMON_H

#define DEFAULT_TARGET_UID 32768
#define DEFAULT_REAPER_UID 32769

#endif /* COMMON_H */
#define _GNU_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>

#include "common.h"

int main(int argc, char * argv) {
    uid_t euid, tuid = DEFAULT_TARGET_UID, xuid = DEFAULT_REAPER_UID;
    int rc;

    /* Check to make sure we have enough permissions */
    euid = geteuid();

    if ( euid != 0 ) {
        fprintf(stderr, "Must run as euid 0 to set uid\n");
        return -1;
    }

    /* 
     * Set euid to TARGET_UID so that we can kill the 'runner'; but
     * set ruid to REAPER_UID so that the runner can't kill us.
     */
    if ( setresuid(xuid, tuid, 0) ) {
        perror("Setting uid to target");
        return -1;
    }

    printf("Sleeping for 1 second to get the runner a chance to kill me...\n");
    usleep(1000000);
    
    rc = kill(-1, 9);
    if ( rc )
        perror("No processes killed");
    else
        printf("At least one process killed successfully!\n");

    return 0;
}
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>

#include "common.h"

int main(int argc, char * argv) {
    uid_t euid, tuid = DEFAULT_TARGET_UID;

    /* Check to make sure we have enough permissions */
    euid = geteuid();

    if ( euid != 0 ) {
        fprintf(stderr, "Must run as euid 0 to set uid\n");
        return -1;
    }

    if(setuid(tuid)) {
        perror("Setting uid to target");
        return -1;
    }

    while(1) {
        if(!fork())
            kill(-1, 9);
        else
            _exit(0);
    }
}
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to