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