Merge commit '7d545233acf6c4d73a623c16ca96cb7d4b9f5db7' into honeycomb-release-to-dalvik-dev
This commit is contained in:
commit
c7703c481a
@ -398,6 +398,7 @@ libc_common_src_files += \
|
||||
arch-x86/bionic/_exit_with_stack_teardown.S \
|
||||
arch-x86/bionic/setjmp.S \
|
||||
arch-x86/bionic/_setjmp.S \
|
||||
arch-x86/bionic/sigsetjmp.S \
|
||||
arch-x86/bionic/vfork.S \
|
||||
arch-x86/bionic/syscall.S \
|
||||
arch-x86/string/bcopy_wrapper.S \
|
||||
|
92
libc/arch-x86/bionic/sigsetjmp.S
Normal file
92
libc/arch-x86/bionic/sigsetjmp.S
Normal file
@ -0,0 +1,92 @@
|
||||
/* $OpenBSD: sigsetjmp.S,v 1.7 2005/08/07 11:30:38 espie Exp $ */
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
ENTRY(sigsetjmp)
|
||||
movl 4(%esp),%ecx
|
||||
movl 8(%esp),%eax
|
||||
movl %eax,28(%ecx)
|
||||
testl %eax,%eax
|
||||
jz 1f
|
||||
|
||||
PIC_PROLOGUE
|
||||
pushl $0
|
||||
#ifdef PIC
|
||||
call PIC_PLT(_C_LABEL(sigblock))
|
||||
#else
|
||||
call _C_LABEL(sigblock)
|
||||
#endif
|
||||
addl $4,%esp
|
||||
PIC_EPILOGUE
|
||||
|
||||
movl 4(%esp),%ecx
|
||||
movl %eax,24(%ecx)
|
||||
1: movl 0(%esp),%edx
|
||||
movl %edx, 0(%ecx)
|
||||
movl %ebx, 4(%ecx)
|
||||
movl %esp, 8(%ecx)
|
||||
movl %ebp,12(%ecx)
|
||||
movl %esi,16(%ecx)
|
||||
movl %edi,20(%ecx)
|
||||
xorl %eax,%eax
|
||||
ret
|
||||
|
||||
ENTRY(siglongjmp)
|
||||
movl 4(%esp),%edx
|
||||
cmpl $0,28(%edx)
|
||||
jz 1f
|
||||
|
||||
PIC_PROLOGUE
|
||||
pushl 24(%edx)
|
||||
#ifdef PIC
|
||||
call PIC_PLT(_C_LABEL(sigsetmask))
|
||||
#else
|
||||
call _C_LABEL(sigsetmask)
|
||||
#endif
|
||||
addl $4,%esp
|
||||
PIC_EPILOGUE
|
||||
|
||||
1: movl 4(%esp),%edx
|
||||
movl 8(%esp),%eax
|
||||
movl 0(%edx),%ecx
|
||||
movl 4(%edx),%ebx
|
||||
movl 8(%edx),%esp
|
||||
movl 12(%edx),%ebp
|
||||
movl 16(%edx),%esi
|
||||
movl 20(%edx),%edi
|
||||
testl %eax,%eax
|
||||
jnz 2f
|
||||
incl %eax
|
||||
2: movl %ecx,0(%esp)
|
||||
ret
|
@ -31,14 +31,14 @@
|
||||
|
||||
#if defined(_KERNEL) && !defined(I386_CPU)
|
||||
#define __swap32md(x) ({ \
|
||||
u_int32_t __swap32md_x = (x); \
|
||||
uint32_t __swap32md_x = (x); \
|
||||
\
|
||||
__asm ("bswap %1" : "+r" (__swap32md_x)); \
|
||||
__swap32md_x; \
|
||||
})
|
||||
#else
|
||||
#define __swap32md(x) ({ \
|
||||
u_int32_t __swap32md_x = (x); \
|
||||
uint32_t __swap32md_x = (x); \
|
||||
\
|
||||
__asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" : \
|
||||
"+r" (__swap32md_x)); \
|
||||
@ -47,13 +47,13 @@
|
||||
#endif /* _KERNEL && !I386_CPU */
|
||||
|
||||
#define __swap64md(x) ({ \
|
||||
u_int64_t __swap64md_x = (x); \
|
||||
uint64_t __swap64md_x = (x); \
|
||||
\
|
||||
(u_int64_t)__swap32md(__swap64md_x >> 32) | \
|
||||
(u_int64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
|
||||
(uint64_t)__swap32md(__swap64md_x >> 32) | \
|
||||
(uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
|
||||
})
|
||||
#define __swap16md(x) ({ \
|
||||
u_int16_t __swap16md_x = (x); \
|
||||
uint16_t __swap16md_x = (x); \
|
||||
\
|
||||
__asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
|
||||
__swap16md_x; \
|
||||
|
@ -36,8 +36,8 @@
|
||||
#define _I386__TYPES_H_
|
||||
|
||||
/* the kernel defines size_t as unsigned int, but g++ wants it to be unsigned long */
|
||||
#ifndef _SIZE_T
|
||||
# define _SIZE_T
|
||||
#ifndef _SIZE_T_DEFINED_
|
||||
# define _SIZE_T_DEFINED_
|
||||
# ifdef ANDROID
|
||||
typedef unsigned int size_t;
|
||||
# else
|
||||
@ -54,9 +54,6 @@ typedef long int ssize_t;
|
||||
typedef long ptrdiff_t;
|
||||
#endif
|
||||
|
||||
#define _OFF_T_DEFINED_
|
||||
#define _SIZE_T_DEFINED_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types */
|
||||
|
@ -1858,7 +1858,13 @@ int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
|
||||
*/
|
||||
int ret, old_errno = errno;
|
||||
|
||||
ret = __rt_sigprocmask(how, set, oset, _NSIG / 8);
|
||||
/* Use NSIG which corresponds to the number of signals in
|
||||
* our 32-bit sigset_t implementation. As such, this function, or
|
||||
* anything that deals with sigset_t cannot manage real-time signals
|
||||
* (signo >= 32). We might want to introduce sigset_rt_t as an
|
||||
* extension to do so in the future.
|
||||
*/
|
||||
ret = __rt_sigprocmask(how, set, oset, NSIG / 8);
|
||||
if (ret < 0)
|
||||
ret = errno;
|
||||
|
||||
|
@ -16,6 +16,9 @@ Differences between current and Android 2.3:
|
||||
|
||||
- <unistd.h>: Add ftruncate64().
|
||||
|
||||
- <signal.h>: Changed the definition of SIGRTMAX to 64. However, note that
|
||||
sigset_t is only 32-bit and cannot deal with real-time signals.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Differences between Android 2.3 and Android 2.2:
|
||||
|
||||
|
@ -60,6 +60,10 @@
|
||||
#define IN6_IS_ADDR_SITELOCAL(a) \
|
||||
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
|
||||
|
||||
/* RFC 4193. */
|
||||
#define IN6_IS_ADDR_ULA(a) \
|
||||
(((a)->s6_addr[0] & 0xfe) == 0xfc)
|
||||
|
||||
#define IN6_IS_ADDR_MULTICAST(a) \
|
||||
(((__const uint8_t *) (a))[0] == 0xff)
|
||||
|
||||
|
@ -42,12 +42,15 @@ __BEGIN_DECLS
|
||||
|
||||
typedef int sig_atomic_t;
|
||||
|
||||
/* crepy NIG / _NSIG handling, just to be safe */
|
||||
#ifndef NSIG
|
||||
# define NSIG _NSIG
|
||||
#endif
|
||||
/* _NSIG is used by the SIGRTMAX definition under <asm/signal.h>, however
|
||||
* its definition is part of a #if __KERNEL__ .. #endif block in the original
|
||||
* kernel headers and is thus not part of our cleaned-up versions.
|
||||
*
|
||||
* Looking at the current kernel sources, it is defined as 64 for all
|
||||
* architectures except for the 'mips' one which set it to 128.
|
||||
*/
|
||||
#ifndef _NSIG
|
||||
# define _NSIG NSIG
|
||||
# define _NSIG 64
|
||||
#endif
|
||||
|
||||
extern const char * const sys_siglist[];
|
||||
|
@ -22,7 +22,7 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
|
||||
#ifndef __thumb__
|
||||
if (!__builtin_constant_p(x)) {
|
||||
|
||||
asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
|
||||
__asm__ ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
|
||||
} else
|
||||
#endif
|
||||
t = x ^ ((x << 16) | (x >> 16));
|
||||
|
@ -71,6 +71,7 @@ def cleanupFile( path ):
|
||||
list.removeEmptyLines()
|
||||
list.removeMacroDefines( kernel_ignored_macros )
|
||||
list.insertDisclaimer( kernel.kernel_disclaimer )
|
||||
list.replaceTokens( kernel_token_replacements )
|
||||
|
||||
out = StringOutput()
|
||||
list.write(out)
|
||||
|
@ -1863,6 +1863,16 @@ class BlockList:
|
||||
tokens = tokens[:-1] # remove trailing tokLN
|
||||
self.blocks = [ Block(tokens) ] + self.blocks
|
||||
|
||||
def replaceTokens(self,replacements=dict()):
|
||||
"""replace tokens according to the given dict
|
||||
"""
|
||||
for b in self.blocks:
|
||||
if not b.isDirective():
|
||||
for tok in b.tokens:
|
||||
if tok.id == tokIDENT:
|
||||
if tok.value in replacements:
|
||||
tok.value = replacements[tok.value]
|
||||
|
||||
class BlockParser:
|
||||
"""a class used to convert an input source file into a BlockList object"""
|
||||
|
||||
|
@ -43,6 +43,11 @@ kernel_default_arch_macros = {
|
||||
"x86": {"__i386__": "1"},
|
||||
}
|
||||
|
||||
# Replace tokens in the output according to this mapping
|
||||
kernel_token_replacements = {
|
||||
{"asm": "__asm__"},
|
||||
}
|
||||
|
||||
# this is the set of known static inline functions that we want to keep
|
||||
# in the final ARM headers. this is only used to keep optimized byteswapping
|
||||
# static functions and stuff like that.
|
||||
|
@ -1497,11 +1497,13 @@ _get_scope(const struct sockaddr *addr)
|
||||
if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */
|
||||
(na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */
|
||||
return IPV6_ADDR_SCOPE_LINKLOCAL;
|
||||
} else if ((na & 0xff000000) == 0x0a000000 || /* 10.0.0.0/8 */
|
||||
(na & 0xfff00000) == 0xac100000 || /* 172.16.0.0/12 */
|
||||
(na & 0xffff0000) == 0xc0a80000) { /* 192.168.0.0/16 */
|
||||
return IPV6_ADDR_SCOPE_SITELOCAL;
|
||||
} else {
|
||||
/*
|
||||
* According to draft-ietf-6man-rfc3484-revise-01 section 2.3,
|
||||
* it is best not to treat the private IPv4 ranges
|
||||
* (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) as being
|
||||
* in a special scope, so we don't.
|
||||
*/
|
||||
return IPV6_ADDR_SCOPE_GLOBAL;
|
||||
}
|
||||
} else {
|
||||
|
@ -1,316 +0,0 @@
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
100% Public Domain
|
||||
|
||||
-----------------
|
||||
Modified 7/98
|
||||
By James H. Brown <jbrown@burgoyne.com>
|
||||
Still 100% Public Domain
|
||||
|
||||
Corrected a problem which generated improper hash values on 16 bit machines
|
||||
Routine SHA1Update changed from
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
|
||||
len)
|
||||
to
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
|
||||
long len)
|
||||
|
||||
The 'len' parameter was declared an int which works fine on 32 bit machines.
|
||||
However, on 16 bit machines an int is too small for the shifts being done
|
||||
against
|
||||
it. This caused the hash function to generate incorrect values if len was
|
||||
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
|
||||
|
||||
Since the file IO in main() reads 16K at a time, any file 8K or larger would
|
||||
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
|
||||
"a"s).
|
||||
|
||||
I also changed the declaration of variables i & j in SHA1Update to
|
||||
unsigned long from unsigned int for the same reason.
|
||||
|
||||
These changes should make no difference to any 32 bit implementations since
|
||||
an
|
||||
int and a long are the same size in those environments.
|
||||
|
||||
--
|
||||
I also corrected a few compiler warnings generated by Borland C.
|
||||
1. Added #include <process.h> for exit() prototype
|
||||
2. Removed unused variable 'j' in SHA1Final
|
||||
3. Changed exit(0) to return(0) at end of main.
|
||||
|
||||
ALL changes I made can be located by searching for comments containing 'JHB'
|
||||
-----------------
|
||||
Modified 8/98
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
Still 100% public domain
|
||||
|
||||
1- Removed #include <process.h> and used return() instead of exit()
|
||||
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
|
||||
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
|
||||
|
||||
-----------------
|
||||
Modified 4/01
|
||||
By Saul Kravitz <Saul.Kravitz@celera.com>
|
||||
Still 100% PD
|
||||
Modified to run on Compaq Alpha hardware.
|
||||
|
||||
-----------------
|
||||
Modified 2/03
|
||||
By H. Peter Anvin <hpa@zytor.com>
|
||||
Still 100% PD
|
||||
Modified to run on any hardware with <inttypes.h> and <netinet/in.h>
|
||||
Changed the driver program
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
/* #define SHA1HANDSOFF */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <netinet/in.h> /* For htonl/ntohl/htons/ntohs */
|
||||
|
||||
/* #include <process.h> */ /* prototype for exit() - JHB */
|
||||
/* Using return() instead of exit() - SWR */
|
||||
|
||||
typedef struct {
|
||||
uint32_t state[5];
|
||||
uint32_t count[2];
|
||||
unsigned char buffer[64];
|
||||
} SHA1_CTX;
|
||||
|
||||
void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
|
||||
void SHA1Init(SHA1_CTX* context);
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /*
|
||||
JHB */
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#define blk0(i) (block->l[i] = ntohl(block->l[i]))
|
||||
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
||||
^block->l[(i+2)&15]^block->l[i&15],1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
||||
|
||||
|
||||
#ifdef VERBOSE /* SAK */
|
||||
void SHAPrintContext(SHA1_CTX *context, char *msg){
|
||||
printf("%s (%d,%d) %x %x %x %x %x\n",
|
||||
msg,
|
||||
context->count[0], context->count[1],
|
||||
context->state[0],
|
||||
context->state[1],
|
||||
context->state[2],
|
||||
context->state[3],
|
||||
context->state[4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
|
||||
{
|
||||
uint32_t a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
uint32_t l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
static unsigned char workspace[64];
|
||||
block = (CHAR64LONG16*)workspace;
|
||||
memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16*)buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(SHA1_CTX* context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /*
|
||||
JHB */
|
||||
{
|
||||
uint32_t i, j; /* JHB */
|
||||
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "before");
|
||||
#endif
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
memcpy(&context->buffer[j], &data[i], len - i);
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "after ");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||
{
|
||||
uint32_t i; /* JHB */
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *)"\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *)"\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = 0; /* JHB */
|
||||
memset(context->buffer, 0, 64);
|
||||
memset(context->state, 0, 20);
|
||||
memset(context->count, 0, 8);
|
||||
memset(finalcount, 0, 8); /* SWR */
|
||||
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
|
||||
/* This is not quite the MIME base64 algorithm: it uses _ instead of /,
|
||||
and instead of padding the output with = characters we just make the
|
||||
output shorter. */
|
||||
char *mybase64(uint8_t digest[20])
|
||||
{
|
||||
static const char charz[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
uint8_t input[21];
|
||||
static char output[28];
|
||||
int i, j;
|
||||
uint8_t *p;
|
||||
char *q;
|
||||
uint32_t bv;
|
||||
|
||||
memcpy(input, digest, 20);
|
||||
input[20] = 0; /* Pad to multiple of 3 bytes */
|
||||
|
||||
p = input; q = output;
|
||||
for ( i = 0 ; i < 7 ; i++ ) {
|
||||
bv = (p[0] << 16) | (p[1] << 8) | p[2];
|
||||
p += 3;
|
||||
for ( j = 0 ; j < 4 ; j++ ) {
|
||||
*q++ = charz[(bv >> 18) & 0x3f];
|
||||
bv <<= 6;
|
||||
}
|
||||
}
|
||||
*--q = '\0'; /* The last character is not significant */
|
||||
return output;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
SHA1_CTX context;
|
||||
uint8_t digest[20], buffer[16384];
|
||||
FILE* file;
|
||||
|
||||
if (argc < 2) {
|
||||
file = stdin;
|
||||
}
|
||||
else {
|
||||
if (!(file = fopen(argv[1], "rb"))) {
|
||||
fputs("Unable to open file.", stderr);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
SHA1Init(&context);
|
||||
while (!feof(file)) { /* note: what if ferror(file) */
|
||||
i = fread(buffer, 1, 16384, file);
|
||||
SHA1Update(&context, buffer, i);
|
||||
}
|
||||
SHA1Final(digest, &context);
|
||||
fclose(file);
|
||||
|
||||
puts(mybase64(digest));
|
||||
|
||||
return 0;
|
||||
}
|
@ -30,5 +30,5 @@
|
||||
|
||||
int raise(int signum)
|
||||
{
|
||||
return kill(getpid(), signum);
|
||||
return kill(gettid(), signum);
|
||||
}
|
||||
|
@ -131,7 +131,8 @@ feclearexcept(int __excepts)
|
||||
static __inline int
|
||||
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||
{
|
||||
int __mxcsr, __status;
|
||||
int __mxcsr;
|
||||
short __status;
|
||||
|
||||
__fnstsw(&__status);
|
||||
if (__HAS_SSE())
|
||||
|
@ -4,6 +4,7 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES:= \
|
||||
arch/$(TARGET_ARCH)/begin.S \
|
||||
linker.c \
|
||||
linker_environ.c \
|
||||
linker_format.c \
|
||||
rt.c \
|
||||
dlfcn.c \
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
#include "linker.h"
|
||||
#include "linker_debug.h"
|
||||
#include "linker_environ.h"
|
||||
#include "linker_format.h"
|
||||
|
||||
#include "ba.h"
|
||||
@ -123,6 +124,9 @@ static soinfo *preloads[LDPRELOAD_MAX + 1];
|
||||
int debug_verbosity;
|
||||
static int pid;
|
||||
|
||||
/* This boolean is set if the program being loaded is setuid */
|
||||
static int program_is_setuid;
|
||||
|
||||
#if STATS
|
||||
struct _link_stats linker_stats;
|
||||
#endif
|
||||
@ -286,7 +290,7 @@ static soinfo *alloc_info(const char *name)
|
||||
|
||||
/* Make sure we get a clean block of soinfo */
|
||||
memset(si, 0, sizeof(soinfo));
|
||||
strcpy((char*) si->name, name);
|
||||
strlcpy((char*) si->name, name, sizeof(si->name));
|
||||
sonext->next = si;
|
||||
si->ba_index = -1; /* by default, prelinked */
|
||||
si->next = NULL;
|
||||
@ -2033,7 +2037,7 @@ static int link_image(soinfo *si, unsigned wr_offset)
|
||||
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
|
||||
|
||||
*/
|
||||
if (getuid() != geteuid() || getgid() != getegid())
|
||||
if (program_is_setuid)
|
||||
nullify_closed_stdio ();
|
||||
call_constructors(si);
|
||||
notify_gdb_of_load(si);
|
||||
@ -2045,7 +2049,7 @@ fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void parse_library_path(char *path, char *delim)
|
||||
static void parse_library_path(const char *path, char *delim)
|
||||
{
|
||||
size_t len;
|
||||
char *ldpaths_bufp = ldpaths_buf;
|
||||
@ -2068,7 +2072,7 @@ static void parse_library_path(char *path, char *delim)
|
||||
}
|
||||
}
|
||||
|
||||
static void parse_preloads(char *path, char *delim)
|
||||
static void parse_preloads(const char *path, char *delim)
|
||||
{
|
||||
size_t len;
|
||||
char *ldpreloads_bufp = ldpreloads_buf;
|
||||
@ -2110,8 +2114,8 @@ unsigned __linker_init(unsigned **elfdata)
|
||||
unsigned *vecs = (unsigned*) (argv + argc + 1);
|
||||
soinfo *si;
|
||||
struct link_map * map;
|
||||
char *ldpath_env = NULL;
|
||||
char *ldpreload_env = NULL;
|
||||
const char *ldpath_env = NULL;
|
||||
const char *ldpreload_env = NULL;
|
||||
|
||||
/* Setup a temporary TLS area that is used to get a working
|
||||
* errno for system calls.
|
||||
@ -2135,20 +2139,32 @@ unsigned __linker_init(unsigned **elfdata)
|
||||
*/
|
||||
__tls_area[TLS_SLOT_BIONIC_PREINIT] = elfdata;
|
||||
|
||||
/* Are we setuid? */
|
||||
program_is_setuid = (getuid() != geteuid()) || (getgid() != getegid());
|
||||
|
||||
/* Initialize environment functions, and get to the ELF aux vectors table */
|
||||
vecs = linker_env_init(vecs);
|
||||
|
||||
/* Sanitize environment if we're loading a setuid program */
|
||||
if (program_is_setuid)
|
||||
linker_env_secure();
|
||||
|
||||
debugger_init();
|
||||
|
||||
/* skip past the environment */
|
||||
while(vecs[0] != 0) {
|
||||
if(!strncmp((char*) vecs[0], "DEBUG=", 6)) {
|
||||
debug_verbosity = atoi(((char*) vecs[0]) + 6);
|
||||
} else if(!strncmp((char*) vecs[0], "LD_LIBRARY_PATH=", 16)) {
|
||||
ldpath_env = (char*) vecs[0] + 16;
|
||||
} else if(!strncmp((char*) vecs[0], "LD_PRELOAD=", 11)) {
|
||||
ldpreload_env = (char*) vecs[0] + 11;
|
||||
/* Get a few environment variables */
|
||||
{
|
||||
const char* env;
|
||||
env = linker_env_get("DEBUG"); /* XXX: TODO: Change to LD_DEBUG */
|
||||
if (env)
|
||||
debug_verbosity = atoi(env);
|
||||
|
||||
/* Normally, these are cleaned by linker_env_secure, but the test
|
||||
* against program_is_setuid doesn't cost us anything */
|
||||
if (!program_is_setuid) {
|
||||
ldpath_env = linker_env_get("LD_LIBRARY_PATH");
|
||||
ldpreload_env = linker_env_get("LD_PRELOAD");
|
||||
}
|
||||
vecs++;
|
||||
}
|
||||
vecs++;
|
||||
|
||||
INFO("[ android linker & debugger ]\n");
|
||||
DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata);
|
||||
@ -2176,7 +2192,7 @@ unsigned __linker_init(unsigned **elfdata)
|
||||
* is. Don't use alloc_info(), because the linker shouldn't
|
||||
* be on the soinfo list.
|
||||
*/
|
||||
strcpy((char*) linker_soinfo.name, "/system/bin/linker");
|
||||
strlcpy((char*) linker_soinfo.name, "/system/bin/linker", sizeof linker_soinfo.name);
|
||||
linker_soinfo.flags = 0;
|
||||
linker_soinfo.base = 0; // This is the important part; must be zero.
|
||||
insert_soinfo_into_debug_map(&linker_soinfo);
|
||||
@ -2206,10 +2222,10 @@ unsigned __linker_init(unsigned **elfdata)
|
||||
si->refcount = 1;
|
||||
|
||||
/* Use LD_LIBRARY_PATH if we aren't setuid/setgid */
|
||||
if (ldpath_env && getuid() == geteuid() && getgid() == getegid())
|
||||
if (ldpath_env)
|
||||
parse_library_path(ldpath_env, ":");
|
||||
|
||||
if (ldpreload_env && getuid() == geteuid() && getgid() == getegid()) {
|
||||
if (ldpreload_env) {
|
||||
parse_preloads(ldpreload_env, " :");
|
||||
}
|
||||
|
||||
|
204
linker/linker_environ.c
Normal file
204
linker/linker_environ.c
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include "linker_environ.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static char** _envp;
|
||||
|
||||
/* Returns 1 if 'str' points to a valid environment variable definition.
|
||||
* For now, we check that:
|
||||
* - It is smaller than MAX_ENV_LEN (to detect non-zero terminated strings)
|
||||
* - It contains at least one equal sign that is not the first character
|
||||
*/
|
||||
static int
|
||||
_is_valid_definition(const char* str)
|
||||
{
|
||||
int pos = 0;
|
||||
int first_equal_pos = -1;
|
||||
|
||||
/* According to its sources, the kernel uses 32*PAGE_SIZE by default
|
||||
* as the maximum size for an env. variable definition.
|
||||
*/
|
||||
const int MAX_ENV_LEN = 32*4096;
|
||||
|
||||
if (str == NULL)
|
||||
return 0;
|
||||
|
||||
/* Parse the string, looking for the first '=' there, and its size */
|
||||
do {
|
||||
if (str[pos] == '\0')
|
||||
break;
|
||||
if (str[pos] == '=' && first_equal_pos < 0)
|
||||
first_equal_pos = pos;
|
||||
pos++;
|
||||
} while (pos < MAX_ENV_LEN);
|
||||
|
||||
if (pos >= MAX_ENV_LEN) /* Too large */
|
||||
return 0;
|
||||
|
||||
if (first_equal_pos < 1) /* No equal sign, or it is the first character */
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned*
|
||||
linker_env_init(unsigned* vecs)
|
||||
{
|
||||
/* Store environment pointer - can't be NULL */
|
||||
_envp = (char**) vecs;
|
||||
|
||||
/* Skip over all definitions */
|
||||
while (vecs[0] != 0)
|
||||
vecs++;
|
||||
/* The end of the environment block is marked by two NULL pointers */
|
||||
vecs++;
|
||||
|
||||
/* As a sanity check, we're going to remove all invalid variable
|
||||
* definitions from the environment array.
|
||||
*/
|
||||
{
|
||||
char** readp = _envp;
|
||||
char** writep = _envp;
|
||||
for ( ; readp[0] != NULL; readp++ ) {
|
||||
if (!_is_valid_definition(readp[0]))
|
||||
continue;
|
||||
writep[0] = readp[0];
|
||||
writep++;
|
||||
}
|
||||
writep[0] = NULL;
|
||||
}
|
||||
|
||||
/* Return the address of the aux vectors table */
|
||||
return vecs;
|
||||
}
|
||||
|
||||
/* Check if the environment variable definition at 'envstr'
|
||||
* starts with '<name>=', and if so return the address of the
|
||||
* first character after the equal sign. Otherwise return NULL.
|
||||
*/
|
||||
static char*
|
||||
env_match(char* envstr, const char* name)
|
||||
{
|
||||
size_t cnt = 0;
|
||||
|
||||
while (envstr[cnt] == name[cnt] && name[cnt] != '\0')
|
||||
cnt++;
|
||||
|
||||
if (name[cnt] == '\0' && envstr[cnt] == '=')
|
||||
return envstr + cnt + 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define MAX_ENV_LEN (16*4096)
|
||||
|
||||
const char*
|
||||
linker_env_get(const char* name)
|
||||
{
|
||||
char** readp = _envp;
|
||||
|
||||
if (name == NULL || name[0] == '\0')
|
||||
return NULL;
|
||||
|
||||
for ( ; readp[0] != NULL; readp++ ) {
|
||||
char* val = env_match(readp[0], name);
|
||||
if (val != NULL) {
|
||||
/* Return NULL for empty strings, or if it is too large */
|
||||
if (val[0] == '\0')
|
||||
val = NULL;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
linker_env_unset(const char* name)
|
||||
{
|
||||
char** readp = _envp;
|
||||
char** writep = readp;
|
||||
|
||||
if (name == NULL || name[0] == '\0')
|
||||
return;
|
||||
|
||||
for ( ; readp[0] != NULL; readp++ ) {
|
||||
if (env_match(readp[0], name))
|
||||
continue;
|
||||
writep[0] = readp[0];
|
||||
writep++;
|
||||
}
|
||||
/* end list with a NULL */
|
||||
writep[0] = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Remove unsafe environment variables. This should be used when
|
||||
* running setuid programs. */
|
||||
void
|
||||
linker_env_secure(void)
|
||||
{
|
||||
/* The same list than GLibc at this point */
|
||||
static const char* const unsec_vars[] = {
|
||||
"GCONV_PATH",
|
||||
"GETCONF_DIR",
|
||||
"HOSTALIASES",
|
||||
"LD_AUDIT",
|
||||
"LD_DEBUG",
|
||||
"LD_DEBUG_OUTPUT",
|
||||
"LD_DYNAMIC_WEAK",
|
||||
"LD_LIBRARY_PATH",
|
||||
"LD_ORIGIN_PATH",
|
||||
"LD_PRELOAD",
|
||||
"LD_PROFILE",
|
||||
"LD_SHOW_AUXV",
|
||||
"LD_USE_LOAD_BIAS",
|
||||
"LOCALDOMAIN",
|
||||
"LOCPATH",
|
||||
"MALLOC_TRACE",
|
||||
"MALLOC_CHECK_",
|
||||
"NIS_PATH",
|
||||
"NLSPATH",
|
||||
"RESOLV_HOST_CONF",
|
||||
"RES_OPTIONS",
|
||||
"TMPDIR",
|
||||
"TZDIR",
|
||||
"LD_AOUT_LIBRARY_PATH",
|
||||
"LD_AOUT_PRELOAD",
|
||||
};
|
||||
|
||||
const char* const* cp = unsec_vars;
|
||||
const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]);
|
||||
|
||||
while (cp < endp) {
|
||||
linker_env_unset(*cp);
|
||||
cp++;
|
||||
}
|
||||
}
|
54
linker/linker_environ.h
Normal file
54
linker/linker_environ.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef LINKER_ENVIRON_H
|
||||
#define LINKER_ENVIRON_H
|
||||
|
||||
/* Call this function before anything else. 'vecs' must be the pointer
|
||||
* to the environment block in the ELF data block. The function returns
|
||||
* the start of the aux vectors after the env block.
|
||||
*/
|
||||
extern unsigned* linker_env_init(unsigned* vecs);
|
||||
|
||||
/* Unset a given environment variable. In case the variable is defined
|
||||
* multiple times, unset all instances. This modifies the environment
|
||||
* block, so any pointer returned by linker_env_get() after this call
|
||||
* might become invalid */
|
||||
extern void linker_env_unset(const char* name);
|
||||
|
||||
|
||||
/* Returns the value of environment variable 'name' if defined and not
|
||||
* empty, or NULL otherwise. Note that the returned pointer may become
|
||||
* invalid if linker_env_unset() or linker_env_secure() are called
|
||||
* after this function. */
|
||||
extern const char* linker_env_get(const char* name);
|
||||
|
||||
/* Remove unsecure environment variables. This should be used when
|
||||
* running setuid programs. */
|
||||
extern void linker_env_secure(void);
|
||||
|
||||
#endif /* LINKER_ENVIRON_H */
|
Loading…
Reference in New Issue
Block a user