On Mon, 7 Nov 2022, Mouse wrote:
used in new code". But I must be missing something, because I can't see any way to exploit the functionality described there, including the saved IDs, to get the effect I want...short of creating an executable
I don't use seteuid(), but, it looks like you can just re-swap the (uid, euid) in a child binary and regain the parent's privileges. Compile with and without -DRELINQUISH. ``` cc -o /tmp/x x.c cc -o /tmp/y y.c sudo sh -c 'chown root:wheel /tmp/x; chmod 4555 /tmp/x' /tmp/x ``` ---START x.c--- #include <err.h> #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { uid_t uid, euid; uid = getuid(); euid = geteuid(); if (uid == euid) errx(1, "UID == EUID--won't proceed."); printf("%s: UID=%d, EUID=%d\n", *argv, uid, euid); if (setreuid(euid, uid) != 0) err(1, "setreuid(%d, %d) failed", euid, uid); printf("%s: UID=%d, EUID=%d\n", *argv, getuid(), geteuid()); #ifdef RELINQUISH /* * Need to do this to safely execute any binary, */ #if defined(__FreeBSD__) || defined(__OpenBSD__) /* * This works only on FreeBSD (13.1-RELEASE-p3) and * OpenBSD (6.9). */ if (setuid(uid) != 0) err(1, "setuid(%d) failed", uid); #else /* * On NetBSD (9.99.106), setuid() fails. * On Linux (5.0.0-38), the call succeeds, but has no effect. * So, we use setreuid(). */ if (setreuid(uid, uid) != 0) err(1, "setreuid(%d, %d) failed", uid, uid); #endif #endif execl("/tmp/y", "y", NULL); err(1, "execl(/tmp/y) failed"); } ---END x.c--- ---START y.c--- #include <err.h> #include <stdio.h> #include <unistd.h> int main(int argc, char* argv[]) { uid_t uid, euid; uid = getuid(); euid = geteuid(); printf("%s: UID=%d, EUID=%d\n", *argv, uid, euid); fflush(stdout); if (setreuid(uid, uid) != 0) err(1, "setreuid(%d, %d) failed", uid, uid); printf("%s: UID=%d, EUID=%d\n", *argv, getuid(), geteuid()); return 0; } ---END y.c--- -RVP