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 /*
23 * Copyright (c) 1988 AT&T
24 * All Rights Reserved
25 *
26 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
27 */
28
29 /*
30 * Utility functions
31 */
32 #include <unistd.h>
33 #include <signal.h>
34 #include <locale.h>
35 #include <string.h>
36 #include "msg.h"
37 #include "_libld.h"
38
39 /*
40 * Exit after cleaning up.
41 */
42 int
ld_exit(Ofl_desc * ofl)43 ld_exit(Ofl_desc *ofl)
44 {
45 /*
46 * If we have created an output file remove it.
47 */
48 if ((ofl->ofl_fd > 0) && ((ofl->ofl_flags1 & FLG_OF1_NONREG) == 0))
49 (void) unlink(ofl->ofl_name);
50
51 /*
52 * Inform any support library that the link-edit has failed.
53 */
54 ld_sup_atexit(ofl, 1);
55
56 /*
57 * Wrap up debug output file if one is open
58 */
59 dbg_cleanup();
60
61 /* If any ERR_GUIDANCE messages were issued, add a summary */
62 if (ofl->ofl_guideflags & FLG_OFG_ISSUED)
63 ld_eprintf(ofl, ERR_GUIDANCE, MSG_INTL(MSG_GUIDE_SUMMARY));
64
65 return (1);
66 }
67
68 /*
69 * Establish the signals we're interested in, and the handlers that need to be
70 * reinstalled should any of these signals occur.
71 */
72 typedef struct {
73 int signo;
74 void (* defhdl)();
75 } Signals;
76
77 static Signals signals[] = {
78 { SIGHUP, SIG_DFL },
79 { SIGINT, SIG_IGN },
80 { SIGQUIT, SIG_DFL },
81 { SIGBUS, SIG_DFL },
82 { SIGTERM, SIG_IGN },
83 { 0, 0 } };
84
85 static Ofl_desc *Ofl = NULL;
86
87 /*
88 * Define our signal handler.
89 */
90 static void
91 /* ARGSUSED2 */
handler(int sig,siginfo_t * sip,void * utp)92 handler(int sig, siginfo_t *sip, void *utp)
93 {
94 struct sigaction nact;
95 Signals * sigs;
96
97 /*
98 * Reset all ignore handlers regardless of how we got here.
99 */
100 nact.sa_handler = SIG_IGN;
101 nact.sa_flags = 0;
102 (void) sigemptyset(&nact.sa_mask);
103
104 for (sigs = signals; sigs->signo; sigs++) {
105 if (sigs->defhdl == SIG_IGN)
106 (void) sigaction(sigs->signo, &nact, NULL);
107 }
108
109 /*
110 * The model for creating an output file is to ftruncate() it to the
111 * required size and mmap() a mapping into which the new contents are
112 * written. Neither of these operations guarantee that the required
113 * disk blocks exist, and should we run out of disk space a bus error
114 * is generated.
115 * Other situations have been reported to result in ld catching a bus
116 * error (one instance was a stale NFS handle from an unstable server).
117 * Thus we catch all bus errors and hope we can decode a better error.
118 */
119 if ((sig == SIGBUS) && sip && Ofl->ofl_name) {
120 ld_eprintf(Ofl, ERR_FATAL, MSG_INTL(MSG_FIL_INTERRUPT),
121 Ofl->ofl_name, strerror(sip->si_errno));
122 }
123 /*
124 * This assert(0) causes DEBUG enabled linkers to produce a core file.
125 */
126 if ((sig != SIGHUP) && (sig != SIGINT))
127 assert(0);
128
129 exit(ld_exit(Ofl));
130 }
131
132 /*
133 * Establish a signal handler for all signals we're interested in.
134 */
135 void
ld_init_sighandler(Ofl_desc * ofl)136 ld_init_sighandler(Ofl_desc *ofl)
137 {
138 struct sigaction nact, oact;
139 Signals * sigs;
140
141 Ofl = ofl;
142
143 /*
144 * Our heavy use of mmap() means that we are susceptible to
145 * receiving a SIGBUS in low diskspace situations. The main
146 * purpose of the signal handler is to handle that situation
147 * gracefully, so that out of disk errors don't drop a core file.
148 *
149 * In rare cases, this will prevent us from getting a core from a
150 * SIGBUS triggered by an internal alignment error in libld.
151 * If -znosighandler is set, return without registering the
152 * handler. This is primarily of use for debugging problems in
153 * the field, and is not of general interest.
154 */
155 if (ofl->ofl_flags1 & FLG_OF1_NOSGHND)
156 return;
157
158 /*
159 * For each signal we're interested in set up a signal handler that
160 * insures we clean up any output file we're in the middle of creating.
161 */
162 nact.sa_sigaction = handler;
163 (void) sigemptyset(&nact.sa_mask);
164
165 for (sigs = signals; sigs->signo; sigs++) {
166 if ((sigaction(sigs->signo, NULL, &oact) == 0) &&
167 (oact.sa_handler != SIG_IGN)) {
168 nact.sa_flags = SA_SIGINFO;
169 if (sigs->defhdl == SIG_DFL)
170 nact.sa_flags |= (SA_RESETHAND | SA_NODEFER);
171 (void) sigaction(sigs->signo, &nact, NULL);
172 }
173 }
174 }
175