issuser =1 ; } else if (!(p->p_flag & P_SUGID)) {
issuser = 1; } else if (!ISSET(p->p_flag, P_SUGID) && !ISSET(p->p_flag, P_SUGIDEXEC)) {
systrace_redirect(int code, struct proc *p, void *v, register_t *retval){	struct sysent *callp;	struct str_process *strp;	struct str_policy *strpolicy;	struct fsystrace *fst = NULL;	struct emul *oldemul;	struct pcred *pc;	uid_t olduid;	gid_t oldgid;	int policy, error = 0, report = 0, maycontrol = 0, issuser = 0;	systrace_lock();	strp = p->p_systrace;	if (strp == NULL) {		systrace_unlock();		return (EINVAL);	}	if (code < 0 || code >= p->p_emul->e_nsysent) {		systrace_unlock();		return (EINVAL);	}	KASSERT(strp->proc == p);	fst = strp->parent;	lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p);	systrace_unlock();	/*	 * We can not monitor a SUID process unless we are root,	 * but we wait until it executes something unprivileged.	 * A non-root user may only monitor if the real uid and	 * real gid match the monitored process.  Changing the	 * uid or gid causes P_SUGID to be set.	 */	if (fst->issuser) {		maycontrol = 1;		issuser =1 ;	} else if (!(p->p_flag & P_SUGID)) {		maycontrol = fst->p_ruid == p->p_cred->p_ruid &&		    fst->p_rgid == p->p_cred->p_rgid;	}	if (!maycontrol) {		policy = SYSTR_POLICY_PERMIT;	} else {		/* Find out current policy */		if ((strpolicy = strp->policy) == NULL)			policy = SYSTR_POLICY_ASK;		else {			if (code >= strpolicy->nsysent)				policy = SYSTR_POLICY_NEVER;			else				policy = strpolicy->sysent[code];		}	}	callp = p->p_emul->e_sysent + code;	/* Fast-path */	if (policy != SYSTR_POLICY_ASK) {		if (policy != SYSTR_POLICY_PERMIT) {			if (policy > 0)				error = policy;			else				error = EPERM;		}		systrace_replacefree(strp);		lockmgr(&fst->lock, LK_RELEASE, NULL, p);		if (policy == SYSTR_POLICY_PERMIT)			error = (*callp->sy_call)(p, v, retval);		return (error);	}	/* Puts the current process to sleep, return unlocked */	error = systrace_msg_ask(fst, strp, code, callp->sy_argsize, v);	/* lock has been released in systrace_msg_ask() */	if (error)		return (error);	/* We might have detached by now for some reason */	systrace_lock();	if ((strp = p->p_systrace) == NULL) {		systrace_unlock();		return (error);	}	fst = strp->parent;	lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p);	systrace_unlock();	if (strp->answer == SYSTR_POLICY_NEVER) {		error = strp->error;		systrace_replacefree(strp);		goto out_unlock;	}	if (ISSET(strp->flags, STR_PROC_SYSCALLRES)) {		CLR(strp->flags, STR_PROC_SYSCALLRES);		report = 1;	}	/* Replace the arguments if necessary */	if (strp->replace != NULL) {		error = systrace_replace(strp, callp->sy_argsize, v);		if (error)			goto out_unlock;	}	oldemul = p->p_emul;	pc = p->p_cred;	olduid = pc->p_ruid;	oldgid = pc->p_rgid;			/* Elevate privileges as desired */	if (issuser) {		if (ISSET(strp->flags, STR_PROC_SETEUID))			strp->saveuid = systrace_seteuid(p, strp->seteuid);		if (ISSET(strp->flags, STR_PROC_SETEGID))			strp->savegid = systrace_setegid(p, strp->setegid);	} else		CLR(strp->flags, STR_PROC_SETEUID|STR_PROC_SETEGID);	lockmgr(&fst->lock, LK_RELEASE, NULL, curproc);					error = (*callp->sy_call)(p, v, retval);	/* Return to old privileges */	systrace_lock();	if ((strp = p->p_systrace) == NULL) {		systrace_unlock();		return (error);	}	if (issuser) {		if (ISSET(strp->flags, STR_PROC_SETEUID)) {			if (pc->pc_ucred->cr_uid == strp->seteuid)				systrace_seteuid(p, strp->saveuid);			CLR(strp->flags, STR_PROC_SETEUID);		}		if (ISSET(strp->flags, STR_PROC_SETEGID)) {			if (pc->pc_ucred->cr_gid == strp->setegid)				systrace_setegid(p, strp->savegid);			CLR(strp->flags, STR_PROC_SETEGID);		}	}	systrace_replacefree(strp);	if (p->p_flag & P_SUGID) {		if ((fst = strp->parent) == NULL || !fst->issuser) {			systrace_unlock();			return (error);		}	}	/* Report change in emulation */	/* See if we should force a report */	if (ISSET(strp->flags, STR_PROC_REPORT)) {		CLR(strp->flags, STR_PROC_REPORT);		oldemul = NULL;	}	/* Acquire lock */	fst = strp->parent;	lockmgr(&fst->lock, LK_EXCLUSIVE, NULL, p);	systrace_unlock();	if (p->p_emul != oldemul) {		/* Old policy is without meaning now */		if (strp->policy) {			systrace_closepolicy(fst, strp->policy);			strp->policy = NULL;		}		systrace_msg_emul(fst, strp);		REACQUIRE_LOCK;	}	/* Report if effective uid or gid changed */	if (olduid != p->p_cred->p_ruid ||	    oldgid != p->p_cred->p_rgid) {		systrace_msg_ugid(fst, strp);		REACQUIRE_LOCK;	}	/* Report result from system call */	if (report) {		systrace_msg_result(fst, strp, error, code,		    callp->sy_argsize, v, retval);		/* not locked */		goto out;	} out_unlock:	lockmgr(&fst->lock, LK_RELEASE, NULL, curproc); out:	return (error);}