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