xref: /illumos-gate/usr/src/cmd/sgs/libconv/common/lddstub.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 
29 #include	<unistd.h>
30 #include	<strings.h>
31 #include	<limits.h>
32 #include	<dlfcn.h>
33 #include	"_conv.h"
34 #include	"lddstub_msg.h"
35 
36 static char	orgstub[PATH_MAX];
37 static char	orgstub64[PATH_MAX];
38 static int	orgflag;
39 static int	orgflag64;
40 
41 #ifdef NEED_OWN_STRLCAT
42 /*
43  * Appends src to the dstsize buffer at dst. The append will never
44  * overflow the destination buffer and the buffer will always be null
45  * terminated. Never reference beyond &bst[dstsize-1] when computing
46  * the length of the pre-existing string.
47  */
48 size_t
49 strlcat(char *dst, const char *src, size_t dstsize)
50 {
51 	char *df = dst;
52 	size_t left = dstsize;
53 	size_t l1;
54 	size_t l2 = strlen(src);
55 	size_t copied;
56 
57 	while (left-- != 0 && *df != '\0')
58 		df++;
59 	l1 = df - dst;
60 	if (dstsize == l1)
61 		return (l1 + l2);
62 
63 	copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2;
64 	memcpy(dst + l1, src, copied);
65 	dst[l1+copied] = '\0';
66 	return (l1 + l2);
67 }
68 #endif
69 
70 static int
71 originlddstub(char *buffer, const char *orgfile)
72 {
73 	int	len;
74 
75 	if (dlinfo(RTLD_SELF, RTLD_DI_ORIGIN, (void *)buffer) == -1)
76 		return (-1);
77 	if (strlcat(buffer, orgfile, PATH_MAX) >= PATH_MAX)
78 		return (-1);
79 	if ((len = resolvepath(buffer, buffer, (PATH_MAX - 1))) == -1)
80 		return (-1);
81 	buffer[len] = '\0';
82 	if (access(orgstub, X_OK) == -1)
83 		return (-1);
84 
85 	return (0);
86 }
87 
88 /*
89  * Determine what lddstub to run.
90  */
91 const char *
92 conv_lddstub(int class)
93 {
94 	const char *stub;
95 
96 	/*
97 	 * Establish defaults.
98 	 */
99 	if (class == ELFCLASS32)
100 		stub = MSG_ORIG(MSG_PTH_LDDSTUB);
101 	else
102 		stub = MSG_ORIG(MSG_PTH_LDDSTUB_64);
103 
104 	/*
105 	 * Provided we're not secure, determine lddstub's location from our
106 	 * own origin.
107 	 */
108 	if (geteuid()) {
109 		if ((class == ELFCLASS32) && (orgflag != -1)) {
110 			if (orgflag == 0) {
111 				if ((orgflag = originlddstub(orgstub,
112 				    MSG_ORIG(MSG_ORG_LDDSTUB))) == -1)
113 					return (stub);
114 			}
115 			stub = (const char *)orgstub;
116 		}
117 		if ((class == ELFCLASS64) && (orgflag64 != -1)) {
118 			if (orgflag64 == 0) {
119 				if ((orgflag64 = originlddstub(orgstub64,
120 				    MSG_ORIG(MSG_ORG_LDDSTUB_64))) == -1)
121 					return (stub);
122 			}
123 			stub = (const char *)orgstub64;
124 		}
125 	}
126 	return (stub);
127 }
128