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