⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcontrol.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 5 页
字号:
		default:			dprintf("Pgrab: failed to open %s: %s\n",			    procname, strerror(errno));			rc = G_STRANGE;			break;		}		goto err;	}	P->asfd = fd;	(void) strcpy(fname, "status");	if ((fd = open(procname, O_RDONLY)) < 0 ||	    (fd = dupfd(fd, 0)) < 0) {		switch (errno) {		case ENOENT:			rc = G_NOPROC;			break;		default:			dprintf("Pgrab: failed to open %s: %s\n",			    procname, strerror(errno));			rc = G_STRANGE;			break;		}		goto err;	}	P->statfd = fd;	if (!(flags & PGRAB_RDONLY)) {		(void) strcpy(fname, "ctl");		if ((fd = open(procname, O_WRONLY)) < 0 ||		    (fd = dupfd(fd, 0)) < 0) {			switch (errno) {			case ENOENT:				rc = G_NOPROC;				break;			default:				dprintf("Pgrab: failed to open %s: %s\n",				    procname, strerror(errno));				rc = G_STRANGE;				break;			}			goto err;		}		P->ctlfd = fd;	}	P->state = PS_RUN;	P->pid = pid;	/*	 * We are now in the Window of Vulnerability (WoV).  The process may	 * exec() a setuid/setgid or unreadable object file between the open()	 * and the PCSTOP.  We will get EAGAIN in this case and must start over.	 * As Pstopstatus will trigger the first read() from a /proc file,	 * we also need to handle EOVERFLOW here when 32-bit as an indicator	 * that this process is 64-bit.  Finally, if the process has become	 * a zombie (PS_UNDEAD) while we were trying to grab it, just remain	 * silent about this and pretend there was no process.	 */	if (Pstopstatus(P, PCNULL, 0) != 0) {#ifndef _LP64		if (errno == EOVERFLOW) {			rc = G_LP64;			goto err;		}#endif		if (P->state == PS_LOST) {	/* WoV */			(void) mutex_destroy(&P->proc_lock);			goto again;		}		if (P->state == PS_UNDEAD)			rc = G_NOPROC;		else			rc = G_STRANGE;		goto err;	}	/*	 * If the process is a system process, we can't control it even as root	 */	if (P->status.pr_flags & PR_ISSYS) {		rc = G_SYS;		goto err;	}#ifndef _LP64	/*	 * We must be a 64-bit process to deal with a 64-bit process	 */	if (P->status.pr_dmodel == PR_MODEL_LP64) {		rc = G_LP64;		goto err;	}#endif	/*	 * Remember the status for use by Prelease().	 */	P->orig_status = P->status;	/* structure copy */	/*	 * Before stopping the process, make sure we are not grabbing ourselves.	 * If we are, make sure we are doing it PGRAB_RDONLY.	 */	if (pid == getpid()) {		/*		 * Verify that the process is really ourself:		 * Set a magic number, read it through the		 * /proc file and see if the results match.		 */		uint32_t magic1 = 0;		uint32_t magic2 = 2;		errno = 0;		if (Pread(P, &magic2, sizeof (magic2), (uintptr_t)&magic1)		    == sizeof (magic2) &&		    magic2 == 0 &&		    (magic1 = 0xfeedbeef) &&		    Pread(P, &magic2, sizeof (magic2), (uintptr_t)&magic1)		    == sizeof (magic2) &&		    magic2 == 0xfeedbeef &&		    !(flags & PGRAB_RDONLY)) {			rc = G_SELF;			goto err;		}	}	/*	 * If the process is already stopped or has been directed	 * to stop via /proc, do not set run-on-last-close.	 */	if (!(P->status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP)) &&	    !(flags & PGRAB_RDONLY)) {		/*		 * Mark the process run-on-last-close so		 * it runs even if we die from SIGKILL.		 */		if (Psetflags(P, PR_RLC) != 0) {			if (errno == EAGAIN) {	/* WoV */				(void) mutex_destroy(&P->proc_lock);				goto again;			}			if (errno == ENOENT)	/* No complaint about zombies */				rc = G_ZOMB;			else {				dprintf("Pgrab: failed to set RLC\n");				rc = G_STRANGE;			}			goto err;		}	}	/*	 * If a stop directive is pending and the process has not yet stopped,	 * then synchronously wait for the stop directive to take effect.	 * Limit the time spent waiting for the process to stop by iterating	 * at most 10 times. The time-out of 20 ms corresponds to the time	 * between sending the stop directive and the process actually stopped	 * as measured by DTrace on a slow, busy system. If the process doesn't	 * stop voluntarily, clear the PR_DSTOP flag so that the code below	 * forces the process to stop.	 */	if (!(flags & PGRAB_RDONLY)) {		int niter = 0;		while ((P->status.pr_lwp.pr_flags & (PR_STOPPED|PR_DSTOP)) ==		    PR_DSTOP && niter < 10 &&		    Pstopstatus(P, PCTWSTOP, 20) != 0) {			niter++;			if (flags & PGRAB_NOSTOP)				break;		}		if (niter == 10 && !(flags & PGRAB_NOSTOP)) {			/* Try it harder down below */			P->status.pr_lwp.pr_flags &= ~PR_DSTOP;		}	}	/*	 * If the process is not already stopped or directed to stop	 * and PGRAB_NOSTOP was not specified, stop the process now.	 */	if (!(P->status.pr_lwp.pr_flags & (PR_ISTOP|PR_DSTOP)) &&	    !(flags & PGRAB_NOSTOP)) {		/*		 * Stop the process, get its status and signal/syscall masks.		 */		if (((P->status.pr_lwp.pr_flags & PR_STOPPED) &&		    Pstopstatus(P, PCDSTOP, 0) != 0) ||		    Pstopstatus(P, PCSTOP, 2000) != 0) {#ifndef _LP64			if (errno == EOVERFLOW) {				rc = G_LP64;				goto err;			}#endif			if (P->state == PS_LOST) {	/* WoV */				(void) mutex_destroy(&P->proc_lock);				goto again;			}			if ((errno != EINTR && errno != ERESTART) ||			    (P->state != PS_STOP &&			    !(P->status.pr_flags & PR_DSTOP))) {				if (P->state != PS_RUN && errno != ENOENT) {					dprintf("Pgrab: failed to PCSTOP\n");					rc = G_STRANGE;				} else {					rc = G_ZOMB;				}				goto err;			}		}		/*		 * Process should now either be stopped via /proc or there		 * should be an outstanding stop directive.		 */		if (!(P->status.pr_flags & (PR_ISTOP|PR_DSTOP))) {			dprintf("Pgrab: process is not stopped\n");			rc = G_STRANGE;			goto err;		}#ifndef _LP64		/*		 * Test this again now because the 32-bit victim process may		 * have exec'd a 64-bit process in the meantime.		 */		if (P->status.pr_dmodel == PR_MODEL_LP64) {			rc = G_LP64;			goto err;		}#endif	}	/*	 * Cancel all tracing flags unless the PGRAB_RETAIN flag is set.	 */	if (!(flags & PGRAB_RETAIN)) {		(void) Psysentry(P, 0, FALSE);		(void) Psysexit(P, 0, FALSE);		(void) Psignal(P, 0, FALSE);		(void) Pfault(P, 0, FALSE);		Psync(P);	}	*perr = 0;	return (P);err:	Pfree(P);	*perr = rc;	return (NULL);}/* * Return a printable string corresponding to a Pgrab() error return. */const char *Pgrab_error(int error){	const char *str;	switch (error) {	case G_NOPROC:		str = "no such process";		break;	case G_NOCORE:		str = "no such core file";		break;	case G_NOPROCORCORE:		str = "no such process or core file";		break;	case G_NOEXEC:		str = "cannot find executable file";		break;	case G_ZOMB:		str = "zombie process";		break;	case G_PERM:		str = "permission denied";		break;	case G_BUSY:		str = "process is traced";		break;	case G_SYS:		str = "system process";		break;	case G_SELF:		str = "attempt to grab self";		break;	case G_INTR:		str = "operation interrupted";		break;	case G_LP64:		str = "program is _LP64, self is not";		break;	case G_FORMAT:		str = "file is not an ELF core file";		break;	case G_ELF:		str = "libelf error";		break;	case G_NOTE:		str = "core file is corrupt or missing required data";		break;	case G_STRANGE:		str = "unanticipated system error";		break;	case G_ISAINVAL:		str = "wrong ELF machine type";		break;	case G_BADLWPS:		str = "bad lwp specification";		break;	default:		str = "unknown error";		break;	}	return (str);}/* * Free a process control structure. * Close the file descriptors but don't do the Prelease logic. */voidPfree(struct ps_prochandle *P){	uint_t i;	if (P->core != NULL) {		extern void __priv_free_info(void *);		lwp_info_t *nlwp, *lwp = list_next(&P->core->core_lwp_head);		for (i = 0; i < P->core->core_nlwp; i++, lwp = nlwp) {			nlwp = list_next(lwp);#ifdef __sparc			if (lwp->lwp_gwins != NULL)				free(lwp->lwp_gwins);			if (lwp->lwp_xregs != NULL)				free(lwp->lwp_xregs);			if (lwp->lwp_asrs != NULL)				free(lwp->lwp_asrs);#endif			free(lwp);		}		if (P->core->core_platform != NULL)			free(P->core->core_platform);		if (P->core->core_uts != NULL)			free(P->core->core_uts);		if (P->core->core_cred != NULL)			free(P->core->core_cred);		if (P->core->core_priv != NULL)			free(P->core->core_priv);		if (P->core->core_privinfo != NULL)			__priv_free_info(P->core->core_privinfo);		if (P->core->core_ppii != NULL)			free(P->core->core_ppii);		if (P->core->core_zonename != NULL)			free(P->core->core_zonename);#if defined(__i386) || defined(__amd64)		if (P->core->core_ldt != NULL)			free(P->core->core_ldt);#endif		free(P->core);	}	if (P->ucaddrs != NULL) {		free(P->ucaddrs);		P->ucaddrs = NULL;		P->ucnelems = 0;	}	(void) mutex_lock(&P->proc_lock);	if (P->hashtab != NULL) {		struct ps_lwphandle *L;		for (i = 0; i < HASHSIZE; i++) {			while ((L = P->hashtab[i]) != NULL)				Lfree_internal(P, L);		}		free(P->hashtab);	}	(void) mutex_unlock(&P->proc_lock);	(void) mutex_destroy(&P->proc_lock);	if (P->agentctlfd >= 0)		(void) close(P->agentctlfd);	if (P->agentstatfd >= 0)		(void) close(P->agentstatfd);	if (P->ctlfd >= 0)		(void) close(P->ctlfd);	if (P->asfd >= 0)		(void) close(P->asfd);	if (P->statfd >= 0)		(void) close(P->statfd);	Preset_maps(P);	/* clear out the structure as a precaution against reuse */	(void) memset(P, 0, sizeof (*P));	P->ctlfd = -1;	P->asfd = -1;	P->statfd = -1;	P->agentctlfd = -1;	P->agentstatfd = -1;	free(P);}/* * Return the state of the process, one of the PS_* values. */intPstate(struct ps_prochandle *P){	return (P->state);}/* * Return the open address space file descriptor for the process. * Clients must not close this file descriptor, not use it * after the process is freed. */intPasfd(struct ps_prochandle *P){	return (P->asfd);}/* * Return the open control file descriptor for the process. * Clients must not close this file descriptor, not use it * after the process is freed. */intPctlfd(struct ps_prochandle *P){	return (P->ctlfd);}/* * Return a pointer to the process psinfo structure. * Clients should not hold on to this pointer indefinitely. * It will become invalid on Prelease(). */const psinfo_t *Ppsinfo(struct ps_prochandle *P){	if (P->state == PS_IDLE) {		errno = ENODATA;		return (NULL);	}	if (P->state != PS_DEAD && proc_get_psinfo(P->pid, &P->psinfo) == -1)		return (NULL);	return (&P->psinfo);}/* * Return a pointer to the process status structure. * Clients should not hold on to this pointer indefinitely. * It will become invalid on Prelease(). */const pstatus_t *Pstatus(struct ps_prochandle *P){	return (&P->status);}/* * Fill in a pointer to a process credentials structure.  The ngroups parameter * is the number of supplementary group entries allocated in the caller's cred * structure.  It should equal zero or one unless extra space has been * allocated for the group list by the caller. */intPcred(struct ps_prochandle *P, prcred_t *pcrp, int ngroups){	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD)		return (proc_get_cred(P->pid, pcrp, ngroups));	if (P->core->core_cred != NULL) {		/*		 * Avoid returning more supplementary group data than the		 * caller has allocated in their buffer.  We expect them to		 * check pr_ngroups afterward and potentially call us again.		 */		ngroups = MIN(ngroups, P->core->core_cred->pr_ngroups);		(void) memcpy(pcrp, P->core->core_cred,		    sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t));		return (0);	}	errno = ENODATA;	return (-1);}#if defined(__i386) || defined(__amd64)/* * Fill in a pointer to a process LDT structure. * The caller provides a buffer of size 'nldt * sizeof (struct ssd)'; * If pldt == NULL or nldt == 0, we return the number of existing LDT entries. * Otherwise we return the actual number of LDT entries fetched (<= nldt). */intPldt(struct ps_prochandle *P, struct ssd *pldt, int nldt){	if (P->state == PS_IDLE) {		errno = ENODATA;		return (-1);	}	if (P->state != PS_DEAD)		return (proc_get_ldt(P->pid, pldt, nldt));	if (pldt == NULL || nldt == 0)		return (P->core->core_nldt);	if (P->core->core_ldt != NULL) {		nldt = MIN(nldt, P->core->core_nldt);		(void) memcpy(pldt, P->core->core_ldt,		    nldt * sizeof (struct ssd));		return (nldt);	}	errno = ENODATA;	return (-1);}#endif	/* __i386 *//* * Fill in a pointer to a process privilege structure. */ssize_tPpriv(struct ps_prochandle *P, prpriv_t *pprv, size_t size){	if (P->state != PS_DEAD) {		prpriv_t *pp = proc_get_priv(P->pid);		if (pp != NULL) {			size = MIN(size, PRIV_PRPRIV_SIZE(pp));			(void) memcpy(pprv, pp, size);			free(pp);			return (size);		}		return (-1);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -