From e28feda227597a27ddcbf341d5e1370d7f54c46a Mon Sep 17 00:00:00 2001 From: Trung Date: Wed, 15 Jul 2026 09:20:37 +0700 Subject: [PATCH] sys: guard saved ID update in setreuid or setregid with euid or egid != -1 Modify DEFINE_SETRE macro to ensure that the saved-set-ID is only updated by the effective ID change check when the new effective ID is actually being set (i.e. e != -1). This prevents setreuid(-1, -1) and setregid(-1, -1) from spuriously clobbering the saved-set-ID when the current effective ID differs from the real ID, matching Linux behavior. Fix #140 --- src/syscall/proc-identity.c | 38 +++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/syscall/proc-identity.c b/src/syscall/proc-identity.c index 079849e0..ea187565 100644 --- a/src/syscall/proc-identity.c +++ b/src/syscall/proc-identity.c @@ -131,22 +131,28 @@ int64_t proc_sys_setgid(uint32_t gid) return 0; } -#define DEFINE_SETRE(suffix, real, eff, saved, perm_fn) \ - int64_t proc_sys_setre##suffix(uint32_t r, uint32_t e) \ - { \ - uint32_t old_real = real; \ - if (r != (uint32_t) -1 && r != real && r != eff) \ - return -LINUX_EPERM; \ - if (e != (uint32_t) -1 && !perm_fn(e)) \ - return -LINUX_EPERM; \ - if (r != (uint32_t) -1) \ - real = r; \ - if (e != (uint32_t) -1) { \ - eff = e; \ - if (r != (uint32_t) -1 || e != old_real) \ - saved = e; \ - } \ - return 0; \ +#define DEFINE_SETRE(suffix, real, eff, saved, perm_fn) \ + int64_t proc_sys_setre##suffix(uint32_t r, uint32_t e) \ + { \ + uint32_t old_real = real; \ + if (r != (uint32_t) -1 && r != real && r != eff) \ + return -LINUX_EPERM; \ + if (e != (uint32_t) -1 && !perm_fn(e)) \ + return -LINUX_EPERM; \ + if (r != (uint32_t) -1) \ + real = r; \ + if (e != (uint32_t) -1) \ + eff = e; \ + /* Linux setreuid(2): saved-set-ID is updated to \ + * the new effective ID when the real ID is set \ + * (r != -1) OR when the new effective ID differs \ + * from the old real ID. Both conditions use the \ + * *new* effective value (eff, which may be \ + * unchanged if e == -1). \ + */ \ + if (r != (uint32_t) -1 || (e != (uint32_t) -1 && eff != old_real)) \ + saved = eff; \ + return 0; \ } DEFINE_SETRE(uid, emu_uid, emu_euid, emu_suid, uid_is_permitted)