1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  *	Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  *	Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate #include	<sys/types.h>
29*0Sstevel@tonic-gate #include	<stdio.h>
30*0Sstevel@tonic-gate #include	<errno.h>
31*0Sstevel@tonic-gate #include	<unistd.h>
32*0Sstevel@tonic-gate #include	<string.h>
33*0Sstevel@tonic-gate #include	<wait.h>
34*0Sstevel@tonic-gate #include	<limits.h>
35*0Sstevel@tonic-gate #include	"machdep.h"
36*0Sstevel@tonic-gate #include	"sgs.h"
37*0Sstevel@tonic-gate #include	"rtc.h"
38*0Sstevel@tonic-gate #include	"conv.h"
39*0Sstevel@tonic-gate #include	"_crle.h"
40*0Sstevel@tonic-gate #include	"msg.h"
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate /*
43*0Sstevel@tonic-gate  * Having gathered together any dependencies, dldump(3x) any necessary images.
44*0Sstevel@tonic-gate  *
45*0Sstevel@tonic-gate  * All dldump(3x) processing is carried out from the audit library.  The
46*0Sstevel@tonic-gate  * temporary configuration file is read and all alternative marked files are
47*0Sstevel@tonic-gate  * dumped.  If a -E application requires RTLD_REL_EXEC then that application
48*0Sstevel@tonic-gate  * acts as the new process, otherwise lddstub is used.
49*0Sstevel@tonic-gate  *
50*0Sstevel@tonic-gate  * Besides dldump(3x)'ing any images the audit library returns the address
51*0Sstevel@tonic-gate  * range of the images which will used to update the configuration file.
52*0Sstevel@tonic-gate  */
53*0Sstevel@tonic-gate int
54*0Sstevel@tonic-gate dump(Crle_desc * crle)
55*0Sstevel@tonic-gate {
56*0Sstevel@tonic-gate 	const char	*orgapp = (const char *)crle->c_app;
57*0Sstevel@tonic-gate 	int		fildes[2], pid;
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate 	if (orgapp == 0)
60*0Sstevel@tonic-gate 		orgapp = conv_lddstub(crle->c_class);
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	/*
63*0Sstevel@tonic-gate 	 * Set up a pipe through which the audit library will write the image
64*0Sstevel@tonic-gate 	 * address ranges.
65*0Sstevel@tonic-gate 	 */
66*0Sstevel@tonic-gate 	if (pipe(fildes) == -1) {
67*0Sstevel@tonic-gate 		int err = errno;
68*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_PIPE),
69*0Sstevel@tonic-gate 		    crle->c_name, strerror(err));
70*0Sstevel@tonic-gate 		return (1);
71*0Sstevel@tonic-gate 	}
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	/*
74*0Sstevel@tonic-gate 	 * Fork ourselves to run the application and collect its dependencies.
75*0Sstevel@tonic-gate 	 */
76*0Sstevel@tonic-gate 	if ((pid = fork()) == -1) {
77*0Sstevel@tonic-gate 		int err = errno;
78*0Sstevel@tonic-gate 		(void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK),
79*0Sstevel@tonic-gate 		    crle->c_name, strerror(err));
80*0Sstevel@tonic-gate 		return (1);
81*0Sstevel@tonic-gate 	}
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	if (pid) {
84*0Sstevel@tonic-gate 		/*
85*0Sstevel@tonic-gate 		 * Parent. Read memory range entries from the audit library.
86*0Sstevel@tonic-gate 		 * The read side of the pipe is attached to stdio to make
87*0Sstevel@tonic-gate 		 * obtaining the individual dependencies easier.
88*0Sstevel@tonic-gate 		 */
89*0Sstevel@tonic-gate 		int	error = 0, status;
90*0Sstevel@tonic-gate 		FILE	*fd;
91*0Sstevel@tonic-gate 		char	buffer[PATH_MAX];
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 		(void) close(fildes[1]);
94*0Sstevel@tonic-gate 		if ((fd = fdopen(fildes[0], MSG_ORIG(MSG_STR_READ))) != NULL) {
95*0Sstevel@tonic-gate 			char		*str;
96*0Sstevel@tonic-gate 			Rtc_head	*rtc = (Rtc_head *)crle->c_tempaddr;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 			while (fgets(buffer, PATH_MAX, fd) != NULL) {
99*0Sstevel@tonic-gate 				/*
100*0Sstevel@tonic-gate 				 * Make sure we recognize the message, remove
101*0Sstevel@tonic-gate 				 * the newline (which allowed fgets() use) and
102*0Sstevel@tonic-gate 				 * register the memory range entry;
103*0Sstevel@tonic-gate 				 */
104*0Sstevel@tonic-gate 				if (strncmp(MSG_ORIG(MSG_AUD_PRF), buffer,
105*0Sstevel@tonic-gate 				    MSG_AUD_PRF_SIZE))
106*0Sstevel@tonic-gate 					continue;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 				str = strrchr(buffer, '\n');
109*0Sstevel@tonic-gate 				*str = '\0';
110*0Sstevel@tonic-gate 				str = buffer + MSG_AUD_PRF_SIZE;
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 				if (strncmp(MSG_ORIG(MSG_AUD_RESBGN),
113*0Sstevel@tonic-gate 				    str, MSG_AUD_RESBGN_SIZE) == 0) {
114*0Sstevel@tonic-gate 					rtc->ch_resbgn =
115*0Sstevel@tonic-gate 					    strtoull(str + MSG_AUD_RESBGN_SIZE,
116*0Sstevel@tonic-gate 						(char **)NULL, 0);
117*0Sstevel@tonic-gate 				} else if (strncmp(MSG_ORIG(MSG_AUD_RESEND),
118*0Sstevel@tonic-gate 				    str, MSG_AUD_RESEND_SIZE) == 0) {
119*0Sstevel@tonic-gate 					rtc->ch_resend =
120*0Sstevel@tonic-gate 					    strtoull(str + MSG_AUD_RESEND_SIZE,
121*0Sstevel@tonic-gate 						(char **)NULL, 0);
122*0Sstevel@tonic-gate 				} else
123*0Sstevel@tonic-gate 					continue;
124*0Sstevel@tonic-gate 			}
125*0Sstevel@tonic-gate 			(void) fclose(fd);
126*0Sstevel@tonic-gate 		} else
127*0Sstevel@tonic-gate 			error = errno;
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 		while (wait(&status) != pid)
130*0Sstevel@tonic-gate 			;
131*0Sstevel@tonic-gate 		if (status) {
132*0Sstevel@tonic-gate 			if (WIFSIGNALED(status)) {
133*0Sstevel@tonic-gate 				(void) fprintf(stderr,
134*0Sstevel@tonic-gate 				    MSG_INTL(MSG_SYS_EXEC), crle->c_name,
135*0Sstevel@tonic-gate 				    orgapp, (WSIGMASK & status),
136*0Sstevel@tonic-gate 				    ((status & WCOREFLG) ?
137*0Sstevel@tonic-gate 				    MSG_INTL(MSG_SYS_CORE) :
138*0Sstevel@tonic-gate 				    MSG_ORIG(MSG_STR_EMPTY)));
139*0Sstevel@tonic-gate 			}
140*0Sstevel@tonic-gate 			return (status);
141*0Sstevel@tonic-gate 		}
142*0Sstevel@tonic-gate 		return (error);
143*0Sstevel@tonic-gate 	} else {
144*0Sstevel@tonic-gate 		char	efds[MSG_ENV_AUD_FD_SIZE + 10];
145*0Sstevel@tonic-gate 		char	eflg[MSG_ENV_AUD_FLAGS_SIZE + 10];
146*0Sstevel@tonic-gate 		char	ecnf[PATH_MAX];
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 		(void) close(fildes[0]);
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate 		/*
151*0Sstevel@tonic-gate 		 * Child. Set up environment variables to enable and identify
152*0Sstevel@tonic-gate 		 * auditing.
153*0Sstevel@tonic-gate 		 */
154*0Sstevel@tonic-gate 		(void) snprintf(efds, (MSG_ENV_AUD_FD_SIZE + 10),
155*0Sstevel@tonic-gate 		    MSG_ORIG(MSG_ENV_AUD_FD), fildes[1]);
156*0Sstevel@tonic-gate 		(void) snprintf(eflg, (MSG_ENV_AUD_FLAGS_SIZE + 10),
157*0Sstevel@tonic-gate 		    MSG_ORIG(MSG_ENV_AUD_FLAGS), crle->c_dlflags);
158*0Sstevel@tonic-gate 		(void) snprintf(ecnf, PATH_MAX, MSG_ORIG(MSG_ENV_LD_CONFIG),
159*0Sstevel@tonic-gate 		    crle->c_tempname);
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate 		/*
162*0Sstevel@tonic-gate 		 * Put strings in the environment for exec().
163*0Sstevel@tonic-gate 		 * NOTE, use of automatic variables for construction of the
164*0Sstevel@tonic-gate 		 * environment variables is legitimate here, as they are local
165*0Sstevel@tonic-gate 		 * to the child process and are established solely for exec().
166*0Sstevel@tonic-gate 		 */
167*0Sstevel@tonic-gate 		if ((putenv(efds) != 0) || (putenv(eflg) != 0) ||
168*0Sstevel@tonic-gate 		    (putenv(ecnf) != 0) || (putenv(crle->c_audit) != 0) ||
169*0Sstevel@tonic-gate 		    (putenv((char *)MSG_ORIG(MSG_ENV_LD_FLAGS)) != 0)) {
170*0Sstevel@tonic-gate 			int err = errno;
171*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_PUTENV),
172*0Sstevel@tonic-gate 			    crle->c_name, strerror(err));
173*0Sstevel@tonic-gate 			return (1);
174*0Sstevel@tonic-gate 		}
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 		if (execlp(orgapp, orgapp, 0) == -1) {
177*0Sstevel@tonic-gate 			int err = errno;
178*0Sstevel@tonic-gate 			(void) fprintf(stderr, MSG_INTL(MSG_SYS_EXECLP),
179*0Sstevel@tonic-gate 			    crle->c_name, orgapp, strerror(err));
180*0Sstevel@tonic-gate 			_exit(err);
181*0Sstevel@tonic-gate 			/* NOTREACHED */
182*0Sstevel@tonic-gate 		}
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 	/* NOTREACHED */
185*0Sstevel@tonic-gate }
186