setresuid() patch for 2.1.20

Marek Michalkiewicz (marekm@i17linuxb.ists.pwr.wroc.pl)
Sat, 11 Jan 1997 01:52:01 +0100 (MET)


The patch below is for 2.1.20 and does the following:

- setresuid() works as documented in the HP-UX man page (if any of the
three current uids is zero, allow setting any ruid/euid/suid)
- if setresuid() changes euid, it also resets fsuid to the new euid,
and clears the dumpable flag (to keep /proc and ptrace secure)
- added similar syscalls for group ids: setresgid(), getresgid()
(setresgid() exists on HP-UX)

I added the new syscall numbers (setresgid() - 168, getresgid() - 169)
for the i386 architecture only. Please do it for other architectures
as well.

Happy hacking,

Marek

diff -urN v2.1.20/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.20/linux/arch/i386/kernel/entry.S Fri Dec 27 11:03:19 1996
+++ linux/arch/i386/kernel/entry.S Sat Jan 11 00:50:43 1997
@@ -630,6 +630,8 @@
.long SYMBOL_NAME(sys_getresuid) /* 165 */
.long SYMBOL_NAME(sys_vm86)
.long SYMBOL_NAME(sys_query_module)
- .rept NR_syscalls-167
+ .long SYMBOL_NAME(sys_setresgid)
+ .long SYMBOL_NAME(sys_getresgid)
+ .rept NR_syscalls-169
.long SYMBOL_NAME(sys_ni_syscall)
.endr
diff -urN v2.1.20/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.1.20/linux/include/asm-i386/unistd.h Tue Dec 31 12:16:02 1996
+++ linux/include/asm-i386/unistd.h Sat Jan 11 00:48:39 1997
@@ -173,6 +173,8 @@
#define __NR_getresuid 165
#define __NR_vm86 166
#define __NR_query_module 167
+#define __NR_setresgid 168
+#define __NR_getresgid 169

/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */

diff -urN v2.1.20/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.20/linux/kernel/sys.c Thu Dec 19 10:03:37 1996
+++ linux/kernel/sys.c Sat Jan 11 00:44:05 1997
@@ -531,25 +531,25 @@
*/
asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{
- uid_t old_ruid, old_euid, old_suid;
-
- old_ruid = current->uid;
- old_euid = current->euid;
- old_suid = current->suid;
-
- if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
- (ruid != current->euid) && (ruid != current->suid))
- return -EPERM;
- if ((euid != (uid_t) -1) && (euid != current->uid) &&
- (euid != current->euid) && (euid != current->suid))
- return -EPERM;
- if ((suid != (uid_t) -1) && (suid != current->uid) &&
- (suid != current->euid) && (suid != current->suid))
- return -EPERM;
+ if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+ if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
+ (ruid != current->euid) && (ruid != current->suid))
+ return -EPERM;
+ if ((euid != (uid_t) -1) && (euid != current->uid) &&
+ (euid != current->euid) && (euid != current->suid))
+ return -EPERM;
+ if ((suid != (uid_t) -1) && (suid != current->uid) &&
+ (suid != current->euid) && (suid != current->suid))
+ return -EPERM;
+ }
if (ruid != (uid_t) -1)
current->uid = ruid;
- if (euid != (uid_t) -1)
+ if (euid != (uid_t) -1) {
+ if (euid != current->euid)
+ current->dumpable = 0;
current->euid = euid;
+ current->fsuid = euid;
+ }
if (suid != (uid_t) -1)
current->suid = suid;
return 0;
@@ -562,6 +562,42 @@
if (!(retval = put_user(current->uid, ruid)) &&
!(retval = put_user(current->euid, euid)))
retval = put_user(current->suid, suid);
+ return retval;
+}
+
+asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
+{
+ if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+ if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
+ (rgid != current->egid) && (rgid != current->sgid))
+ return -EPERM;
+ if ((egid != (gid_t) -1) && (egid != current->gid) &&
+ (egid != current->egid) && (egid != current->sgid))
+ return -EPERM;
+ if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
+ (sgid != current->egid) && (sgid != current->sgid))
+ return -EPERM;
+ }
+ if (rgid != (gid_t) -1)
+ current->gid = rgid;
+ if (egid != (gid_t) -1) {
+ if (egid != current->egid)
+ current->dumpable = 0;
+ current->egid = egid;
+ current->fsgid = egid;
+ }
+ if (sgid != (gid_t) -1)
+ current->sgid = sgid;
+ return 0;
+}
+
+asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
+{
+ int retval;
+
+ if (!(retval = put_user(current->gid, rgid)) &&
+ !(retval = put_user(current->egid, egid)))
+ retval = put_user(current->sgid, sgid);
return retval;
}