- if (uap->rgid == -1)
- (error = suser(u.u_cred, &u.u_acflag)))
- return (error);
- if (uap->egid == -1)
- egid != p->p_svgid && (error = suser(u.u_cred, &u.u_acflag)))
- return (error);
- u.u_cred = crcopy(u.u_cred);
- p->p_rgid = rgid;
- u.u_cred->cr_groups[0] = egid;
- return (0);
+ /*
+ * If ruid == euid then setreuid is being used to emulate setuid,
+ * just do it.
+ */
+ if (SCARG(uap, ruid) != -1 && SCARG(uap, ruid) == SCARG(uap, euid)) {
+ SCARG(&args.sa, uid) = SCARG(uap, ruid);
+ return (setuid(p, &args.sa, retval));
+ }
+ /*
+ * Otherwise we assume that the intent of setting ruid is to be
+ * able to get back ruid priviledge (i.e. swapping ruid and euid).
+ * So we make sure that we will be able to do so, but do not
+ * actually set the ruid.
+ */
+ if (SCARG(uap, ruid) != (uid_t)-1 && SCARG(uap, ruid) != pc->p_ruid &&
+ SCARG(uap, ruid) != pc->p_svuid)
+ return (EPERM);
+ if (SCARG(uap, euid) == (uid_t)-1)
+ return (0);
+ SCARG(&args.ea, euid) = SCARG(uap, euid);
+ return (seteuid(p, &args.ea, retval));