xref: /titanic_52/usr/src/lib/libtnfctl/prb_child.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1994, by Sun Microsytems, Inc.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate 
26*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * interfaces to exec a command and run it till all loadobjects have
30*7c478bd9Sstevel@tonic-gate  * been loaded (rtld sync point).
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <unistd.h>
34*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
35*7c478bd9Sstevel@tonic-gate #include <string.h>
36*7c478bd9Sstevel@tonic-gate #include <errno.h>
37*7c478bd9Sstevel@tonic-gate #include <limits.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "prb_proc_int.h"
42*7c478bd9Sstevel@tonic-gate #include "dbg.h"
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate /*
45*7c478bd9Sstevel@tonic-gate  * Defines
46*7c478bd9Sstevel@tonic-gate  */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #define	PRELOAD		"LD_PRELOAD"
49*7c478bd9Sstevel@tonic-gate #define	LIBPROBE	"libtnfprobe.so.1"
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate /*
52*7c478bd9Sstevel@tonic-gate  * Local declarations
53*7c478bd9Sstevel@tonic-gate  */
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate static prb_status_t sync_child(int pid, volatile shmem_msg_t *smp,
56*7c478bd9Sstevel@tonic-gate 					prb_proc_ctl_t **proc_pp);
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate /*
59*7c478bd9Sstevel@tonic-gate  * prb_child_create()  - this routine instantiates and rendevous with the
60*7c478bd9Sstevel@tonic-gate  * target child process.  This routine returns an opaque handle for the
61*7c478bd9Sstevel@tonic-gate  * childs /proc entry.
62*7c478bd9Sstevel@tonic-gate  */
63*7c478bd9Sstevel@tonic-gate prb_status_t
64*7c478bd9Sstevel@tonic-gate prb_child_create(const char *cmdname, char * const *cmdargs,
65*7c478bd9Sstevel@tonic-gate 		const char *loption, const char *libtnfprobe_path,
66*7c478bd9Sstevel@tonic-gate 		char * const *envp, prb_proc_ctl_t **ret_val)
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	prb_status_t	prbstat;
69*7c478bd9Sstevel@tonic-gate 	pid_t		childpid;
70*7c478bd9Sstevel@tonic-gate 	char		executable_name[PATH_MAX + 2];
71*7c478bd9Sstevel@tonic-gate 	extern char 	**environ;
72*7c478bd9Sstevel@tonic-gate 	char * const *	env_to_use;
73*7c478bd9Sstevel@tonic-gate 	size_t		loptlen, probepathlen;
74*7c478bd9Sstevel@tonic-gate 	volatile shmem_msg_t *smp;
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate 	/* initialize shmem communication buffer to cause child to wait */
77*7c478bd9Sstevel@tonic-gate 	prbstat = prb_shmem_init(&smp);
78*7c478bd9Sstevel@tonic-gate 	if (prbstat)
79*7c478bd9Sstevel@tonic-gate 		return (prbstat);
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	/* fork to create the child process */
82*7c478bd9Sstevel@tonic-gate 	childpid = fork();
83*7c478bd9Sstevel@tonic-gate 	if (childpid == (pid_t) - 1) {
84*7c478bd9Sstevel@tonic-gate 		DBG(perror("prb_child_create: fork failed"));
85*7c478bd9Sstevel@tonic-gate 		return (prb_status_map(errno));
86*7c478bd9Sstevel@tonic-gate 	}
87*7c478bd9Sstevel@tonic-gate 	if (childpid == 0) {
88*7c478bd9Sstevel@tonic-gate 		char		   *oldenv;
89*7c478bd9Sstevel@tonic-gate 		char		   *newenv;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 		/* ---- CHILD PROCESS ---- */
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 		DBG_TNF_PROBE_1(prb_child_create_1, "libtnfctl",
94*7c478bd9Sstevel@tonic-gate 			"sunw%verbosity 1; sunw%debug 'child process created'",
95*7c478bd9Sstevel@tonic-gate 			tnf_long, pid, getpid());
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 		if (envp) {
98*7c478bd9Sstevel@tonic-gate 			env_to_use = envp;
99*7c478bd9Sstevel@tonic-gate 			goto ContChild;
100*7c478bd9Sstevel@tonic-gate 		}
101*7c478bd9Sstevel@tonic-gate 
102*7c478bd9Sstevel@tonic-gate 		/* append libtnfprobe.so to the LD_PRELOAD environment */
103*7c478bd9Sstevel@tonic-gate 		loptlen = (loption) ? strlen(loption) : 0;
104*7c478bd9Sstevel@tonic-gate 		/* probepathlen has a "/" added in ("+ 1") */
105*7c478bd9Sstevel@tonic-gate 		probepathlen = (libtnfprobe_path) ?
106*7c478bd9Sstevel@tonic-gate 				(strlen(libtnfprobe_path) + 1) : 0;
107*7c478bd9Sstevel@tonic-gate 		oldenv = getenv(PRELOAD);
108*7c478bd9Sstevel@tonic-gate 		if (oldenv) {
109*7c478bd9Sstevel@tonic-gate 			newenv = (char *) malloc(strlen(PRELOAD) +
110*7c478bd9Sstevel@tonic-gate 				1 +	/* "=" */
111*7c478bd9Sstevel@tonic-gate 				strlen(oldenv) +
112*7c478bd9Sstevel@tonic-gate 				1 +	/* " " */
113*7c478bd9Sstevel@tonic-gate 				probepathlen +
114*7c478bd9Sstevel@tonic-gate 				strlen(LIBPROBE) +
115*7c478bd9Sstevel@tonic-gate 				1 +	/* " " */
116*7c478bd9Sstevel@tonic-gate 				loptlen +
117*7c478bd9Sstevel@tonic-gate 				1);	/* NULL */
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 			if (!newenv)
120*7c478bd9Sstevel@tonic-gate 				goto ContChild;
121*7c478bd9Sstevel@tonic-gate 			(void) strcpy(newenv, PRELOAD);
122*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, "=");
123*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, oldenv);
124*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, " ");
125*7c478bd9Sstevel@tonic-gate 			if (probepathlen) {
126*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, libtnfprobe_path);
127*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, "/");
128*7c478bd9Sstevel@tonic-gate 			}
129*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, LIBPROBE);
130*7c478bd9Sstevel@tonic-gate 			if (loptlen) {
131*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, " ");
132*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, loption);
133*7c478bd9Sstevel@tonic-gate 			}
134*7c478bd9Sstevel@tonic-gate 		} else {
135*7c478bd9Sstevel@tonic-gate 			newenv = (char *) malloc(strlen(PRELOAD) +
136*7c478bd9Sstevel@tonic-gate 				1 +	/* "=" */
137*7c478bd9Sstevel@tonic-gate 				probepathlen +
138*7c478bd9Sstevel@tonic-gate 				strlen(LIBPROBE) +
139*7c478bd9Sstevel@tonic-gate 				1 +	/* " " */
140*7c478bd9Sstevel@tonic-gate 				loptlen +
141*7c478bd9Sstevel@tonic-gate 				1);	/* NULL */
142*7c478bd9Sstevel@tonic-gate 			if (!newenv)
143*7c478bd9Sstevel@tonic-gate 				goto ContChild;
144*7c478bd9Sstevel@tonic-gate 			(void) strcpy(newenv, PRELOAD);
145*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, "=");
146*7c478bd9Sstevel@tonic-gate 			if (probepathlen) {
147*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, libtnfprobe_path);
148*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, "/");
149*7c478bd9Sstevel@tonic-gate 			}
150*7c478bd9Sstevel@tonic-gate 			(void) strcat(newenv, LIBPROBE);
151*7c478bd9Sstevel@tonic-gate 			if (loptlen) {
152*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, " ");
153*7c478bd9Sstevel@tonic-gate 				(void) strcat(newenv, loption);
154*7c478bd9Sstevel@tonic-gate 			}
155*7c478bd9Sstevel@tonic-gate 		}
156*7c478bd9Sstevel@tonic-gate 		(void) putenv((char *) newenv);
157*7c478bd9Sstevel@tonic-gate 		env_to_use = environ;
158*7c478bd9Sstevel@tonic-gate 		/*
159*7c478bd9Sstevel@tonic-gate 		 * We don't check the return value of putenv because the
160*7c478bd9Sstevel@tonic-gate 		 * desired libraries might already be in the target, even
161*7c478bd9Sstevel@tonic-gate 		 * if our effort to change the environment fails.  We
162*7c478bd9Sstevel@tonic-gate 		 * should continue either way ...
163*7c478bd9Sstevel@tonic-gate 		 */
164*7c478bd9Sstevel@tonic-gate ContChild:
165*7c478bd9Sstevel@tonic-gate 		/* wait until the parent releases us */
166*7c478bd9Sstevel@tonic-gate 		(void) prb_shmem_wait(smp);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 		DBG_TNF_PROBE_1(prb_child_create_2, "libtnfctl",
169*7c478bd9Sstevel@tonic-gate 			"sunw%verbosity 2; "
170*7c478bd9Sstevel@tonic-gate 			"sunw%debug 'child process about to exec'",
171*7c478bd9Sstevel@tonic-gate 			tnf_string, cmdname, cmdname);
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 		/*
174*7c478bd9Sstevel@tonic-gate 		 * make the child it's own process group.
175*7c478bd9Sstevel@tonic-gate 		 * This is so that signals delivered to parent are not
176*7c478bd9Sstevel@tonic-gate 		 * also delivered to child.
177*7c478bd9Sstevel@tonic-gate 		 */
178*7c478bd9Sstevel@tonic-gate 		(void) setpgrp();
179*7c478bd9Sstevel@tonic-gate 		prbstat = find_executable(cmdname, executable_name);
180*7c478bd9Sstevel@tonic-gate 		if (prbstat) {
181*7c478bd9Sstevel@tonic-gate 			DBG((void) fprintf(stderr, "prb_child_create: %s\n",
182*7c478bd9Sstevel@tonic-gate 					prb_status_str(prbstat)));
183*7c478bd9Sstevel@tonic-gate 			/* parent waits for exit */
184*7c478bd9Sstevel@tonic-gate 			_exit(1);
185*7c478bd9Sstevel@tonic-gate 		}
186*7c478bd9Sstevel@tonic-gate 		if (execve(executable_name, cmdargs, env_to_use) == -1) {
187*7c478bd9Sstevel@tonic-gate 			DBG(perror("prb_child_create: exec failed"));
188*7c478bd9Sstevel@tonic-gate 			_exit(1);
189*7c478bd9Sstevel@tonic-gate 		}
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 		/* Never reached */
192*7c478bd9Sstevel@tonic-gate 		_exit(1);
193*7c478bd9Sstevel@tonic-gate 	}
194*7c478bd9Sstevel@tonic-gate 	/* ---- PARENT PROCESS ---- */
195*7c478bd9Sstevel@tonic-gate 	/* child is waiting for us */
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 	prbstat = sync_child(childpid, smp, ret_val);
198*7c478bd9Sstevel@tonic-gate 	if (prbstat) {
199*7c478bd9Sstevel@tonic-gate 		return (prbstat);
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	return (PRB_STATUS_OK);
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate }
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate /*
207*7c478bd9Sstevel@tonic-gate  * interface that registers the address of the debug structure
208*7c478bd9Sstevel@tonic-gate  * in the target process.  This is where the linker maintains all
209*7c478bd9Sstevel@tonic-gate  * the information about the loadobjects
210*7c478bd9Sstevel@tonic-gate  */
211*7c478bd9Sstevel@tonic-gate void
212*7c478bd9Sstevel@tonic-gate prb_dbgaddr(prb_proc_ctl_t *proc_p, uintptr_t dbgaddr)
213*7c478bd9Sstevel@tonic-gate {
214*7c478bd9Sstevel@tonic-gate 	proc_p->dbgaddr = dbgaddr;
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate /*
218*7c478bd9Sstevel@tonic-gate  * continue the child until the run time linker has loaded in all
219*7c478bd9Sstevel@tonic-gate  * the loadobjects (rtld sync point)
220*7c478bd9Sstevel@tonic-gate  */
221*7c478bd9Sstevel@tonic-gate static prb_status_t
222*7c478bd9Sstevel@tonic-gate sync_child(int childpid, volatile shmem_msg_t *smp, prb_proc_ctl_t **proc_pp)
223*7c478bd9Sstevel@tonic-gate {
224*7c478bd9Sstevel@tonic-gate 	prb_proc_ctl_t		*proc_p, *oldproc_p;
225*7c478bd9Sstevel@tonic-gate 	prb_status_t		prbstat = PRB_STATUS_OK;
226*7c478bd9Sstevel@tonic-gate 	prb_status_t		tempstat;
227*7c478bd9Sstevel@tonic-gate 	prb_proc_state_t	pstate;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_open(childpid, proc_pp);
230*7c478bd9Sstevel@tonic-gate 	if (prbstat)
231*7c478bd9Sstevel@tonic-gate 		return (prbstat);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	proc_p = *proc_pp;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_stop(proc_p);
236*7c478bd9Sstevel@tonic-gate 	if (prbstat)
237*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	/*
240*7c478bd9Sstevel@tonic-gate 	 * default is to kill-on-last-close.  In case we cannot sync with
241*7c478bd9Sstevel@tonic-gate 	 * target, we don't want the target to continue.
242*7c478bd9Sstevel@tonic-gate 	 */
243*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_setrlc(proc_p, B_FALSE);
244*7c478bd9Sstevel@tonic-gate 	if (prbstat)
245*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_setklc(proc_p, B_TRUE);
248*7c478bd9Sstevel@tonic-gate 	if (prbstat)
249*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	/* REMIND: do we have to wait on SYS_exec also ? */
252*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_exit(proc_p, SYS_execve, PRB_SYS_ADD);
253*7c478bd9Sstevel@tonic-gate 	if (prbstat)
254*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, SYS_exit, PRB_SYS_ADD);
257*7c478bd9Sstevel@tonic-gate 	if (prbstat)
258*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	prbstat = prb_shmem_clear(smp);
261*7c478bd9Sstevel@tonic-gate 	if (prbstat)
262*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_cont(proc_p);
265*7c478bd9Sstevel@tonic-gate 	if (prbstat)
266*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_wait(proc_p, B_FALSE, NULL);
269*7c478bd9Sstevel@tonic-gate 	switch (prbstat) {
270*7c478bd9Sstevel@tonic-gate 	case PRB_STATUS_OK:
271*7c478bd9Sstevel@tonic-gate 		break;
272*7c478bd9Sstevel@tonic-gate 	case EAGAIN:
273*7c478bd9Sstevel@tonic-gate 		/*
274*7c478bd9Sstevel@tonic-gate 		 * If we had exec'ed a setuid/setgid program PIOCWSTOP
275*7c478bd9Sstevel@tonic-gate 		 * will return EAGAIN.  Reopen the 'fd' and try again.
276*7c478bd9Sstevel@tonic-gate 		 * Read the last section of /proc man page - we reopen first
277*7c478bd9Sstevel@tonic-gate 		 * and then close the old fd.
278*7c478bd9Sstevel@tonic-gate 		 */
279*7c478bd9Sstevel@tonic-gate 		oldproc_p = proc_p;
280*7c478bd9Sstevel@tonic-gate 		tempstat = prb_proc_reopen(childpid, proc_pp);
281*7c478bd9Sstevel@tonic-gate 		proc_p = *proc_pp;
282*7c478bd9Sstevel@tonic-gate 		if (tempstat) {
283*7c478bd9Sstevel@tonic-gate 			/* here EACCES means exec'ed a setuid/setgid program */
284*7c478bd9Sstevel@tonic-gate 			(void) prb_proc_close(oldproc_p);
285*7c478bd9Sstevel@tonic-gate 			return (tempstat);
286*7c478bd9Sstevel@tonic-gate 		}
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 		(void) prb_proc_close(oldproc_p);
289*7c478bd9Sstevel@tonic-gate 		break;
290*7c478bd9Sstevel@tonic-gate 	default:
291*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	prbstat = prb_shmem_free(smp);
295*7c478bd9Sstevel@tonic-gate 	if (prbstat)
296*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_state(proc_p, &pstate);
299*7c478bd9Sstevel@tonic-gate 	if (prbstat)
300*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 	if (pstate.ps_issysexit && (pstate.ps_syscallnum == SYS_execve)) {
303*7c478bd9Sstevel@tonic-gate 		/* expected condition */
304*7c478bd9Sstevel@tonic-gate 		prbstat = PRB_STATUS_OK;
305*7c478bd9Sstevel@tonic-gate 	} else {
306*7c478bd9Sstevel@tonic-gate 		prbstat = prb_status_map(ENOENT);
307*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	/* clear old interest mask */
311*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_exit(proc_p, 0, PRB_SYS_NONE);
312*7c478bd9Sstevel@tonic-gate 	if (prbstat)
313*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	prbstat = prb_proc_entry(proc_p, 0, PRB_SYS_NONE);
316*7c478bd9Sstevel@tonic-gate 	if (prbstat)
317*7c478bd9Sstevel@tonic-gate 		goto ret_failure;
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate 	/* Successful return */
320*7c478bd9Sstevel@tonic-gate 	return (PRB_STATUS_OK);
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate ret_failure:
323*7c478bd9Sstevel@tonic-gate 	(void) prb_proc_close(proc_p);
324*7c478bd9Sstevel@tonic-gate 	return (prbstat);
325*7c478bd9Sstevel@tonic-gate }
326