Beispiel #1
0
/* copy the page tables, and set both pte's flag. 
 * note: on Copy On Write, both parent and child process will be marked 
 * write-protected, and increase the reference count of each shared physical 
 * page. 
 * */
int pt_copy(struct pde *npgd, struct pde *opgd){
    struct pde *opde, *npde;
    struct pte *opte, *npte, *old_pt, *new_pt;
    struct page *pg;
    uint pdn, pn;

    for(pdn=PDX(KMEM_END); pdn<1024; pdn++) {
        opde = &opgd[pdn];
        npde = &npgd[pdn];
        npde->pd_flag = opde->pd_flag;
        if (opde->pd_flag & PTE_P) {
            old_pt = (struct pte*)(opde->pd_off * PAGE);
            new_pt = (struct pte*)kmalloc(PAGE);
            npde->pd_off = PPN(new_pt);
            for(pn=0; pn<1024; pn++){
                opte = &old_pt[pn];
                npte = &new_pt[pn];
                npte->pt_off  = opte->pt_off;
                npte->pt_flag = opte->pt_flag;
                if (opte->pt_flag & PTE_P) {
                    // turn off each pte's PTE_W
                    npte->pt_flag &= ~PTE_W;
                    opte->pt_flag &= ~PTE_W;
                    // increase the ref count
                    pg = pgfind(opte->pt_off);
                    pg->pg_count++;
                }
            }
        }
    }
    return 0;
}
Beispiel #2
0
/*
 * set process group (setpgid/old setpgrp)
 *
 * caller does setpgid(targpid, targpgid)
 *
 * pid must be caller or child of caller (ESRCH)
 * if a child
 *	pid must be in same session (EPERM)
 *	pid can't have done an exec (EACCES)
 * if pgid != pid
 * 	there must exist some pid in same session having pgid (EPERM)
 * pid must not be session leader (EPERM)
 */
int
sys_setpgid(struct setpgid_args *uap)
{
	struct proc *curp = curproc;
	struct proc *targp;		/* target process */
	struct pgrp *pgrp = NULL;	/* target pgrp */
	int error;

	if (uap->pgid < 0)
		return (EINVAL);

	if (uap->pid != 0 && uap->pid != curp->p_pid) {
		if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
			if (targp)
				PRELE(targp);
			error = ESRCH;
			targp = NULL;
			goto done;
		}
		lwkt_gettoken(&targp->p_token);
		/* targp now referenced and its token is held */

		if (targp->p_pgrp == NULL ||
		    targp->p_session != curp->p_session) {
			error = EPERM;
			goto done;
		}
		if (targp->p_flags & P_EXEC) {
			error = EACCES;
			goto done;
		}
	} else {
		targp = curp;
		PHOLD(targp);
		lwkt_gettoken(&targp->p_token);
	}
	if (SESS_LEADER(targp)) {
		error = EPERM;
		goto done;
	}
	if (uap->pgid == 0) {
		uap->pgid = targp->p_pid;
	} else if (uap->pgid != targp->p_pid) {
		if ((pgrp = pgfind(uap->pgid)) == NULL ||
	            pgrp->pg_session != curp->p_session) {
			error = EPERM;
			goto done;
		}
	}
	error = enterpgrp(targp, uap->pgid, 0);
done:
	if (pgrp)
		pgrel(pgrp);
	if (targp) {
		lwkt_reltoken(&targp->p_token);
		PRELE(targp);
	}
	return (error);
}
Beispiel #3
0
/* ARGSUSED */
int
sys_setpgid(struct proc *curp, void *v, register_t *retval)
{
	struct sys_setpgid_args /* {
		syscallarg(pid_t) pid;
		syscallarg(int) pgid;
	} */ *uap = v;
	struct process *curpr = curp->p_p;
	struct process *targpr;		/* target process */
	struct pgrp *pgrp, *newpgrp;	/* target pgrp */
	pid_t pid;
	int pgid, error;

	pid = SCARG(uap, pid);
	pgid = SCARG(uap, pgid);

	if (pgid < 0)
		return (EINVAL);

	newpgrp = pool_get(&pgrp_pool, PR_WAITOK);

	if (pid != 0 && pid != curpr->ps_pid) {
		if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) {
			error = ESRCH;
			goto out;
		}
		if (targpr->ps_session != curpr->ps_session) {
			error = EPERM;
			goto out;
		}
		if (targpr->ps_flags & PS_EXEC) {
			error = EACCES;
			goto out;
		}
	} else
		targpr = curpr;
	if (SESS_LEADER(targpr)) {
		error = EPERM;
		goto out;
	}
	if (pgid == 0)
		pgid = targpr->ps_pid;
	else if (pgid != targpr->ps_pid)
		if ((pgrp = pgfind(pgid)) == 0 ||
		    pgrp->pg_session != curpr->ps_session) {
			error = EPERM;
			goto out;
		}
	return (enterpgrp(targpr, pgid, newpgrp, NULL));
out:
	pool_put(&pgrp_pool, newpgrp);
	return (error);
}
Beispiel #4
0
static int
sigqkill(pid_t pid, sigsend_t *sigsend)
{
	proc_t *p;
	int error;

	if ((uint_t)sigsend->sig >= NSIG)
		return (EINVAL);

	if (pid == -1) {
		procset_t set;

		setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID);
		error = sigsendset(&set, sigsend);
	} else if (pid > 0) {
		mutex_enter(&pidlock);
		if ((p = prfind(pid)) == NULL || p->p_stat == SIDL)
			error = ESRCH;
		else {
			error = sigsendproc(p, sigsend);
			if (error == 0 && sigsend->perm == 0)
				error = EPERM;
		}
		mutex_exit(&pidlock);
	} else {
		int nfound = 0;
		pid_t pgid;

		if (pid == 0)
			pgid = ttoproc(curthread)->p_pgrp;
		else
			pgid = -pid;

		error = 0;
		mutex_enter(&pidlock);
		for (p = pgfind(pgid); p && !error; p = p->p_pglink) {
			if (p->p_stat != SIDL) {
				nfound++;
				error = sigsendproc(p, sigsend);
			}
		}
		mutex_exit(&pidlock);
		if (nfound == 0)
			error = ESRCH;
		else if (error == 0 && sigsend->perm == 0)
			error = EPERM;
	}

	return (error);
}
Beispiel #5
0
/*
 * Checks for current use of a pid, either as a pid or pgid.
 */
int
pidtaken(pid_t pid)
{
	struct proc *p;

	if (pfind(pid) != NULL)
		return (1);
	if (pgfind(pid) != NULL)
		return (1);
	LIST_FOREACH(p, &zombproc, p_list)
		if (p->p_pid == pid || p->p_pgid == pid)
			return (1);
	return (0);
}
Beispiel #6
0
int
sys_setsid(struct setsid_args *uap)
{
	struct proc *p = curproc;
	struct pgrp *pg = NULL;
	int error;

	lwkt_gettoken(&p->p_token);
	if (p->p_pgid == p->p_pid || (pg = pgfind(p->p_pid)) != NULL) {
		error = EPERM;
		if (pg)
			pgrel(pg);
	} else {
		enterpgrp(p, p->p_pid, 1);
		uap->sysmsg_result = p->p_pid;
		error = 0;
	}
	lwkt_reltoken(&p->p_token);
	return (error);
}
Beispiel #7
0
/* ARGSUSED */
int
sys_setsid(struct proc *p, void *v, register_t *retval)
{
	struct session *newsess;
	struct pgrp *newpgrp;
	struct process *pr = p->p_p;
	pid_t pid = pr->ps_pid;

	newsess = pool_get(&session_pool, PR_WAITOK);
	newpgrp = pool_get(&pgrp_pool, PR_WAITOK);

	if (pr->ps_pgid == pid || pgfind(pid)) {
		pool_put(&pgrp_pool, newpgrp);
		pool_put(&session_pool, newsess);
		return (EPERM);
	} else {
		(void) enterpgrp(pr, pid, newpgrp, newsess);
		*retval = pid;
		return (0);
	}
}
Beispiel #8
0
/* decrease all the pages' reference count, and free the page tables. */
int pt_free(struct pde *pgd){
    struct pde *pde;
    struct pte *pte, *pt;
    struct page *pg;
    uint pdn, pn;

    for(pdn=PDX(KMEM_END); pdn<1024; pdn++) {
        pde = &pgd[pdn];
        if (pde->pd_flag & PTE_P) {
            pt = (struct pte*)(pde->pd_off * PAGE);
            for(pn=0; pn<1024; pn++) {
                pte = &pt[pn];
                if (pte->pt_flag & PTE_P) {
                    pg = pgfind(pte->pt_off);
                    pgfree(pg);
                }
            }
            kfree(pt, PAGE);
        }
    }
    return 0;
}
Beispiel #9
0
/*
 * Move p to a new or existing process group (and session)
 */
int
enterpgrp(proc_p p, pid_t pgid, int mksess) {
  register pgrp_p pgrp = pgfind(pgid);
#ifdef DIAGNOSTIC
  if (pgrp != NULL && mksess)	/* firewalls */
    panic("enterpgrp: setsid into non-empty pgrp");
  if (SESS_LEADER(p))
    panic("enterpgrp: session leader attempted setpgrp");
#endif
  {
    extern int getpid();
    dprintf("%d enterpgrp(p %p (pid: %d),pgid %d,mksess %d) (pgrp = %p pgid: %d)\n",
	    getpid(),p,p ? p->p_pid : -1,pgid,mksess, pgrp,pgrp ? pgrp->pg_id : -1);
  }
  if (pgrp == NULL) {
    pid_t savepid = p->p_pid;
    proc_p np;
    /*
     * new process group
     */
#ifdef DIAGNOSTIC
    if (p->p_pid != pgid)
      panic("enterpgrp: new pgrp and pid != pgid");
#endif

    if ((np = __pd_pfind(savepid)) == NULL || np != p)
      return (ESRCH);

    pgrp = pgrp_alloc();

    if (mksess) {
      session_p sess;
      /*
       * new session
       */
      sess = session_alloc();

      sess->s_leader = p;
      sess->s_count = 1;
      sess->s_ttyp = (struct tty *)0;
      bcopy(p->p_session->s_login, sess->s_login,
	    sizeof(sess->s_login));
      p->p_flag &= ~P_CONTROLT;
      pgrp->pg_session = sess;
    } else {
      pgrp->pg_session = p->p_session;
      pgrp->pg_session->s_count++;
    }
    pgrp->pg_id = pgid;
    LIST_INIT(&pgrp->pg_members);
    pgrp->pg_jobc = 0;
  } else if (pgrp == p->p_pgrp)
    return (0);
  
  /*
   * Adjust eligibility of affected pgrps to participate in job control.
   * Increment eligibility counts before decrementing, otherwise we
   * could reach 0 spuriously during the first call.
   */
  fixjobc(p, pgrp, 1);
  fixjobc(p, p->p_pgrp, 0);
  
  LIST_REMOVE(p, p_pglist);
  if (p->p_pgrp->pg_members.lh_first == 0)
    pgdelete(p->p_pgrp);
  p->p_pgrp = pgrp;
  LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
  return (0);
}
Beispiel #10
0
/* ARGSUSED */
int
setpgrp(int flag, int pid, int pgid)
{
	register proc_t *p =  ttoproc(curthread);
	register int	retval = 0;

	switch (flag) {

	case 1: /* setpgrp() */
		mutex_enter(&pidlock);
		if (p->p_sessp->s_sidp != p->p_pidp && !pgmembers(p->p_pid)) {
			mutex_exit(&pidlock);
			sess_create();
		} else
			mutex_exit(&pidlock);
		return (p->p_sessp->s_sid);

	case 3: /* setsid() */
		mutex_enter(&pidlock);
		if (p->p_pgidp == p->p_pidp || pgmembers(p->p_pid)) {
			mutex_exit(&pidlock);
			return (set_errno(EPERM));
		}
		mutex_exit(&pidlock);
		sess_create();
		return (p->p_sessp->s_sid);

	case 5: /* setpgid() */
	{
		mutex_enter(&pidlock);
		if (pid == 0)
			pid = p->p_pid;
		else if (pid < 0 || pid >= maxpid) {
			mutex_exit(&pidlock);
			return (set_errno(EINVAL));
		} else if (pid != p->p_pid) {
			for (p = p->p_child; /* empty */; p = p->p_sibling) {
				if (p == NULL) {
					mutex_exit(&pidlock);
					return (set_errno(ESRCH));
				}
				if (p->p_pid == pid)
					break;
			}
			if (p->p_flag & SEXECED) {
				mutex_exit(&pidlock);
				return (set_errno(EACCES));
			}
			if (p->p_sessp != ttoproc(curthread)->p_sessp) {
				mutex_exit(&pidlock);
				return (set_errno(EPERM));
			}
		}

		if (p->p_sessp->s_sid == pid) {
			mutex_exit(&pidlock);
			return (set_errno(EPERM));
		}

		if (pgid == 0)
			pgid = p->p_pid;
		else if (pgid < 0 || pgid >= maxpid) {
			mutex_exit(&pidlock);
			return (set_errno(EINVAL));
		}

		if (p->p_pgrp == pgid) {
			mutex_exit(&pidlock);
			break;
		} else if (p->p_pid == pgid) {
			/*
			 * We need to protect p_pgidp with p_lock because
			 * /proc looks at it while holding only p_lock.
			 */
			mutex_enter(&p->p_lock);
			pgexit(p);
			pgjoin(p, p->p_pidp);
			mutex_exit(&p->p_lock);
		} else {
			register proc_t *q;

			if ((q = pgfind(pgid)) == NULL ||
			    q->p_sessp != p->p_sessp) {
				mutex_exit(&pidlock);
				return (set_errno(EPERM));
			}
			/*
			 * See comment above about p_lock and /proc
			 */
			mutex_enter(&p->p_lock);
			pgexit(p);
			pgjoin(p, q->p_pgidp);
			mutex_exit(&p->p_lock);
		}
		mutex_exit(&pidlock);
		break;
	}

	case 0: /* getpgrp() */
		mutex_enter(&pidlock);
		retval = p->p_pgrp;
		mutex_exit(&pidlock);
		break;

	case 2: /* getsid() */
	case 4: /* getpgid() */
		if (pid < 0 || pid >= maxpid) {
			return (set_errno(EINVAL));
		}
		mutex_enter(&pidlock);
		if (pid != 0 && p->p_pid != pid &&
		    ((p = prfind(pid)) == NULL || p->p_stat == SIDL)) {
			mutex_exit(&pidlock);
			return (set_errno(ESRCH));
		}
		if (flag == 2)
			retval = p->p_sessp->s_sid;
		else
			retval = p->p_pgrp;
		mutex_exit(&pidlock);
		break;

	}
	return (retval);
}
Beispiel #11
0
/* ARGSUSED */
int
sys_ktrace(struct proc *curp, void *v, register_t *retval)
{
	struct sys_ktrace_args /* {
		syscallarg(const char *) fname;
		syscallarg(int) ops;
		syscallarg(int) facs;
		syscallarg(pid_t) pid;
	} */ *uap = v;
	struct vnode *vp = NULL;
	struct proc *p = NULL;
	struct pgrp *pg;
	int facs = SCARG(uap, facs) & ~((unsigned) KTRFAC_ROOT);
	int ops = KTROP(SCARG(uap, ops));
	int descend = SCARG(uap, ops) & KTRFLAG_DESCEND;
	int ret = 0;
	int error = 0;
	struct nameidata nd;

	curp->p_traceflag |= KTRFAC_ACTIVE;
	if (ops != KTROP_CLEAR) {
		/*
		 * an operation which requires a file argument.
		 */
		NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, fname),
		    curp);
		if ((error = vn_open(&nd, FREAD|FWRITE|O_NOFOLLOW, 0)) != 0) {
			curp->p_traceflag &= ~KTRFAC_ACTIVE;
			return (error);
		}
		vp = nd.ni_vp;

		VOP_UNLOCK(vp, 0, curp);
		if (vp->v_type != VREG) {
			(void) vn_close(vp, FREAD|FWRITE, curp->p_ucred, curp);
			curp->p_traceflag &= ~KTRFAC_ACTIVE;
			return (EACCES);
		}
	}
	/*
	 * Clear all uses of the tracefile
	 */
	if (ops == KTROP_CLEARFILE) {
		for (p = LIST_FIRST(&allproc); p; p = LIST_NEXT(p, p_list)) {
			if (p->p_tracep == vp) {
				if (ktrcanset(curp, p)) {
					p->p_traceflag = 0;
					ktrsettracevnode(p, NULL);
				} else
					error = EPERM;
			}
		}
		goto done;
	}
	/*
	 * need something to (un)trace (XXX - why is this here?)
	 */
	if (!facs) {
		error = EINVAL;
		goto done;
	}
	/* 
	 * do it
	 */
	if (SCARG(uap, pid) < 0) {
		/*
		 * by process group
		 */
		pg = pgfind(-SCARG(uap, pid));
		if (pg == NULL) {
			error = ESRCH;
			goto done;
		}
		LIST_FOREACH(p, &pg->pg_members, p_pglist)
			if (descend)
				ret |= ktrsetchildren(curp, p, ops, facs, vp);
			else 
				ret |= ktrops(curp, p, ops, facs, vp);
					
	} else {
static int
set_proc_info(pid_t pid, const char *path, core_content_t content)
{
	proc_t *p;
	counter_t counter;
	int error = 0;

	counter.cc_count = 0;
	/*
	 * Only one of the core file path or content can be set at a time.
	 */
	if (path != NULL) {
		counter.cc_path = corectl_path_alloc(path);
		counter.cc_content = NULL;
	} else {
		counter.cc_path = NULL;
		counter.cc_content = corectl_content_alloc(content);
	}

	if (pid == -1) {
		procset_t set;

		setprocset(&set, POP_AND, P_ALL, P_MYID, P_ALL, P_MYID);
		error = dotoprocs(&set, set_one_proc_info, (char *)&counter);
		if (error == 0 && counter.cc_count == 0)
			error = EPERM;
	} else if (pid > 0) {
		mutex_enter(&pidlock);
		if ((p = prfind(pid)) == NULL || p->p_stat == SIDL) {
			error = ESRCH;
		} else {
			(void) set_one_proc_info(p, &counter);
			if (counter.cc_count == 0)
				error = EPERM;
		}
		mutex_exit(&pidlock);
	} else {
		int nfound = 0;
		pid_t pgid;

		if (pid == 0)
			pgid = curproc->p_pgrp;
		else
			pgid = -pid;

		mutex_enter(&pidlock);
		for (p = pgfind(pgid); p != NULL; p = p->p_pglink) {
			if (p->p_stat != SIDL) {
				nfound++;
				(void) set_one_proc_info(p, &counter);
			}
		}
		mutex_exit(&pidlock);
		if (nfound == 0)
			error = ESRCH;
		else if (counter.cc_count == 0)
			error = EPERM;
	}

	if (path != NULL)
		corectl_path_rele(counter.cc_path);
	else
		corectl_content_rele(counter.cc_content);

	if (error)
		return (set_errno(error));
	return (0);
}