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
26 #include <sys/types.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <wait.h>
32 #include <limits.h>
33 #include "machdep.h"
34 #include "sgs.h"
35 #include "rtc.h"
36 #include "conv.h"
37 #include "_crle.h"
38 #include "msg.h"
39
40 /*
41 * Having gathered together any dependencies, dldump(3x) any necessary images.
42 *
43 * All dldump(3x) processing is carried out from the audit library. The
44 * temporary configuration file is read and all alternative marked files are
45 * dumped. If a -E application requires RTLD_REL_EXEC then that application
46 * acts as the new process, otherwise lddstub is used.
47 *
48 * Besides dldump(3x)'ing any images the audit library returns the address
49 * range of the images which will used to update the configuration file.
50 */
51 int
dump(Crle_desc * crle)52 dump(Crle_desc * crle)
53 {
54 const char *orgapp = (const char *)crle->c_app;
55 int fildes[2], pid;
56
57 if (orgapp == 0)
58 orgapp = conv_lddstub(M_CLASS);
59
60 /*
61 * Set up a pipe through which the audit library will write the image
62 * address ranges.
63 */
64 if (pipe(fildes) == -1) {
65 int err = errno;
66 (void) fprintf(stderr, MSG_INTL(MSG_SYS_PIPE),
67 crle->c_name, strerror(err));
68 return (1);
69 }
70
71 /*
72 * Fork ourselves to run the application and collect its dependencies.
73 */
74 if ((pid = fork()) == -1) {
75 int err = errno;
76 (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK),
77 crle->c_name, strerror(err));
78 return (1);
79 }
80
81 if (pid) {
82 /*
83 * Parent. Read memory range entries from the audit library.
84 * The read side of the pipe is attached to stdio to make
85 * obtaining the individual dependencies easier.
86 */
87 int error = 0, status;
88 FILE *fd;
89 char buffer[PATH_MAX];
90
91 (void) close(fildes[1]);
92 if ((fd = fdopen(fildes[0], MSG_ORIG(MSG_STR_READ))) != NULL) {
93 char *str;
94 Rtc_head *rtc = (Rtc_head *)crle->c_tempheadaddr;
95
96 while (fgets(buffer, PATH_MAX, fd) != NULL) {
97 /*
98 * Make sure we recognize the message, remove
99 * the newline (which allowed fgets() use) and
100 * register the memory range entry;
101 */
102 if (strncmp(MSG_ORIG(MSG_AUD_PRF), buffer,
103 MSG_AUD_PRF_SIZE))
104 continue;
105
106 str = strrchr(buffer, '\n');
107 *str = '\0';
108 str = buffer + MSG_AUD_PRF_SIZE;
109
110 if (strncmp(MSG_ORIG(MSG_AUD_RESBGN),
111 str, MSG_AUD_RESBGN_SIZE) == 0) {
112 rtc->ch_resbgn =
113 strtoull(str + MSG_AUD_RESBGN_SIZE,
114 (char **)NULL, 0);
115 } else if (strncmp(MSG_ORIG(MSG_AUD_RESEND),
116 str, MSG_AUD_RESEND_SIZE) == 0) {
117 rtc->ch_resend =
118 strtoull(str + MSG_AUD_RESEND_SIZE,
119 (char **)NULL, 0);
120 } else {
121 continue;
122 }
123 }
124 (void) fclose(fd);
125 } else
126 error = errno;
127
128 while (wait(&status) != pid)
129 ;
130 if (status) {
131 if (WIFSIGNALED(status)) {
132 (void) fprintf(stderr,
133 MSG_INTL(MSG_SYS_EXEC), crle->c_name,
134 orgapp, (WSIGMASK & status),
135 ((status & WCOREFLG) ?
136 MSG_INTL(MSG_SYS_CORE) :
137 MSG_ORIG(MSG_STR_EMPTY)));
138 }
139 return (status);
140 }
141 return (error);
142 } else {
143 char efds[MSG_ENV_AUD_FD_SIZE + 10];
144 char eflg[MSG_ENV_AUD_FLAGS_SIZE + 10];
145 char ecnf[PATH_MAX];
146
147 (void) close(fildes[0]);
148
149 /*
150 * Child. Set up environment variables to enable and identify
151 * auditing.
152 */
153 (void) snprintf(efds, (MSG_ENV_AUD_FD_SIZE + 10),
154 MSG_ORIG(MSG_ENV_AUD_FD), fildes[1]);
155 (void) snprintf(eflg, (MSG_ENV_AUD_FLAGS_SIZE + 10),
156 MSG_ORIG(MSG_ENV_AUD_FLAGS), crle->c_dlflags);
157 (void) snprintf(ecnf, PATH_MAX, MSG_ORIG(MSG_ENV_LD_CONFIG),
158 crle->c_tempname);
159
160 /*
161 * Put strings in the environment for exec().
162 * NOTE, use of automatic variables for construction of the
163 * environment variables is legitimate here, as they are local
164 * to the child process and are established solely for exec().
165 */
166 if ((putenv(efds) != 0) || (putenv(eflg) != 0) ||
167 (putenv(ecnf) != 0) || (putenv(crle->c_audit) != 0) ||
168 (putenv((char *)MSG_ORIG(MSG_ENV_LD_FLAGS)) != 0)) {
169 int err = errno;
170 (void) fprintf(stderr, MSG_INTL(MSG_SYS_PUTENV),
171 crle->c_name, strerror(err));
172 return (1);
173 }
174
175 if (execlp(orgapp, orgapp, 0) == -1) {
176 int err = errno;
177 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXECLP),
178 crle->c_name, orgapp, strerror(err));
179 _exit(err);
180 /* NOTREACHED */
181 }
182 }
183 return (0);
184 }
185