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/_exit_with_stack_teardown.S \
|
||||||
arch-x86/bionic/setjmp.S \
|
arch-x86/bionic/setjmp.S \
|
||||||
arch-x86/bionic/_setjmp.S \
|
arch-x86/bionic/_setjmp.S \
|
||||||
|
arch-x86/bionic/sigsetjmp.S \
|
||||||
arch-x86/bionic/vfork.S \
|
arch-x86/bionic/vfork.S \
|
||||||
arch-x86/bionic/syscall.S \
|
arch-x86/bionic/syscall.S \
|
||||||
arch-x86/string/bcopy_wrapper.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)
|
#if defined(_KERNEL) && !defined(I386_CPU)
|
||||||
#define __swap32md(x) ({ \
|
#define __swap32md(x) ({ \
|
||||||
u_int32_t __swap32md_x = (x); \
|
uint32_t __swap32md_x = (x); \
|
||||||
\
|
\
|
||||||
__asm ("bswap %1" : "+r" (__swap32md_x)); \
|
__asm ("bswap %1" : "+r" (__swap32md_x)); \
|
||||||
__swap32md_x; \
|
__swap32md_x; \
|
||||||
})
|
})
|
||||||
#else
|
#else
|
||||||
#define __swap32md(x) ({ \
|
#define __swap32md(x) ({ \
|
||||||
u_int32_t __swap32md_x = (x); \
|
uint32_t __swap32md_x = (x); \
|
||||||
\
|
\
|
||||||
__asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" : \
|
__asm ("rorw $8, %w1; rorl $16, %1; rorw $8, %w1" : \
|
||||||
"+r" (__swap32md_x)); \
|
"+r" (__swap32md_x)); \
|
||||||
@ -47,13 +47,13 @@
|
|||||||
#endif /* _KERNEL && !I386_CPU */
|
#endif /* _KERNEL && !I386_CPU */
|
||||||
|
|
||||||
#define __swap64md(x) ({ \
|
#define __swap64md(x) ({ \
|
||||||
u_int64_t __swap64md_x = (x); \
|
uint64_t __swap64md_x = (x); \
|
||||||
\
|
\
|
||||||
(u_int64_t)__swap32md(__swap64md_x >> 32) | \
|
(uint64_t)__swap32md(__swap64md_x >> 32) | \
|
||||||
(u_int64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
|
(uint64_t)__swap32md(__swap64md_x & 0xffffffff) << 32; \
|
||||||
})
|
})
|
||||||
#define __swap16md(x) ({ \
|
#define __swap16md(x) ({ \
|
||||||
u_int16_t __swap16md_x = (x); \
|
uint16_t __swap16md_x = (x); \
|
||||||
\
|
\
|
||||||
__asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
|
__asm ("rorw $8, %w1" : "+r" (__swap16md_x)); \
|
||||||
__swap16md_x; \
|
__swap16md_x; \
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
#define _I386__TYPES_H_
|
#define _I386__TYPES_H_
|
||||||
|
|
||||||
/* the kernel defines size_t as unsigned int, but g++ wants it to be unsigned long */
|
/* the kernel defines size_t as unsigned int, but g++ wants it to be unsigned long */
|
||||||
#ifndef _SIZE_T
|
#ifndef _SIZE_T_DEFINED_
|
||||||
# define _SIZE_T
|
# define _SIZE_T_DEFINED_
|
||||||
# ifdef ANDROID
|
# ifdef ANDROID
|
||||||
typedef unsigned int size_t;
|
typedef unsigned int size_t;
|
||||||
# else
|
# else
|
||||||
@ -54,9 +54,6 @@ typedef long int ssize_t;
|
|||||||
typedef long ptrdiff_t;
|
typedef long ptrdiff_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _OFF_T_DEFINED_
|
|
||||||
#define _SIZE_T_DEFINED_
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
/* 7.18.1.1 Exact-width integer types */
|
/* 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;
|
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)
|
if (ret < 0)
|
||||||
ret = errno;
|
ret = errno;
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ Differences between current and Android 2.3:
|
|||||||
|
|
||||||
- <unistd.h>: Add ftruncate64().
|
- <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:
|
Differences between Android 2.3 and Android 2.2:
|
||||||
|
|
||||||
|
@ -60,6 +60,10 @@
|
|||||||
#define IN6_IS_ADDR_SITELOCAL(a) \
|
#define IN6_IS_ADDR_SITELOCAL(a) \
|
||||||
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
|
(((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) \
|
#define IN6_IS_ADDR_MULTICAST(a) \
|
||||||
(((__const uint8_t *) (a))[0] == 0xff)
|
(((__const uint8_t *) (a))[0] == 0xff)
|
||||||
|
|
||||||
|
@ -42,12 +42,15 @@ __BEGIN_DECLS
|
|||||||
|
|
||||||
typedef int sig_atomic_t;
|
typedef int sig_atomic_t;
|
||||||
|
|
||||||
/* crepy NIG / _NSIG handling, just to be safe */
|
/* _NSIG is used by the SIGRTMAX definition under <asm/signal.h>, however
|
||||||
#ifndef NSIG
|
* its definition is part of a #if __KERNEL__ .. #endif block in the original
|
||||||
# define NSIG _NSIG
|
* kernel headers and is thus not part of our cleaned-up versions.
|
||||||
#endif
|
*
|
||||||
|
* 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
|
#ifndef _NSIG
|
||||||
# define _NSIG NSIG
|
# define _NSIG 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char * const sys_siglist[];
|
extern const char * const sys_siglist[];
|
||||||
|
@ -22,7 +22,7 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x)
|
|||||||
#ifndef __thumb__
|
#ifndef __thumb__
|
||||||
if (!__builtin_constant_p(x)) {
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
t = x ^ ((x << 16) | (x >> 16));
|
t = x ^ ((x << 16) | (x >> 16));
|
||||||
|
@ -71,6 +71,7 @@ def cleanupFile( path ):
|
|||||||
list.removeEmptyLines()
|
list.removeEmptyLines()
|
||||||
list.removeMacroDefines( kernel_ignored_macros )
|
list.removeMacroDefines( kernel_ignored_macros )
|
||||||
list.insertDisclaimer( kernel.kernel_disclaimer )
|
list.insertDisclaimer( kernel.kernel_disclaimer )
|
||||||
|
list.replaceTokens( kernel_token_replacements )
|
||||||
|
|
||||||
out = StringOutput()
|
out = StringOutput()
|
||||||
list.write(out)
|
list.write(out)
|
||||||
|
@ -1863,6 +1863,16 @@ class BlockList:
|
|||||||
tokens = tokens[:-1] # remove trailing tokLN
|
tokens = tokens[:-1] # remove trailing tokLN
|
||||||
self.blocks = [ Block(tokens) ] + self.blocks
|
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:
|
class BlockParser:
|
||||||
"""a class used to convert an input source file into a BlockList object"""
|
"""a class used to convert an input source file into a BlockList object"""
|
||||||
|
|
||||||
|
@ -43,6 +43,11 @@ kernel_default_arch_macros = {
|
|||||||
"x86": {"__i386__": "1"},
|
"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
|
# 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
|
# in the final ARM headers. this is only used to keep optimized byteswapping
|
||||||
# static functions and stuff like that.
|
# 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 */
|
if (IN_LOOPBACK(na) || /* 127.0.0.0/8 */
|
||||||
(na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */
|
(na & 0xffff0000) == 0xa9fe0000) { /* 169.254.0.0/16 */
|
||||||
return IPV6_ADDR_SCOPE_LINKLOCAL;
|
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 {
|
} 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;
|
return IPV6_ADDR_SCOPE_GLOBAL;
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
int raise(int signum)
|
||||||
{
|
{
|
||||||
return kill(getpid(), signum);
|
return kill(gettid(), signum);
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,8 @@ feclearexcept(int __excepts)
|
|||||||
static __inline int
|
static __inline int
|
||||||
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
fegetexceptflag(fexcept_t *__flagp, int __excepts)
|
||||||
{
|
{
|
||||||
int __mxcsr, __status;
|
int __mxcsr;
|
||||||
|
short __status;
|
||||||
|
|
||||||
__fnstsw(&__status);
|
__fnstsw(&__status);
|
||||||
if (__HAS_SSE())
|
if (__HAS_SSE())
|
||||||
|
@ -4,6 +4,7 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
arch/$(TARGET_ARCH)/begin.S \
|
arch/$(TARGET_ARCH)/begin.S \
|
||||||
linker.c \
|
linker.c \
|
||||||
|
linker_environ.c \
|
||||||
linker_format.c \
|
linker_format.c \
|
||||||
rt.c \
|
rt.c \
|
||||||
dlfcn.c \
|
dlfcn.c \
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include "linker.h"
|
#include "linker.h"
|
||||||
#include "linker_debug.h"
|
#include "linker_debug.h"
|
||||||
|
#include "linker_environ.h"
|
||||||
#include "linker_format.h"
|
#include "linker_format.h"
|
||||||
|
|
||||||
#include "ba.h"
|
#include "ba.h"
|
||||||
@ -123,6 +124,9 @@ static soinfo *preloads[LDPRELOAD_MAX + 1];
|
|||||||
int debug_verbosity;
|
int debug_verbosity;
|
||||||
static int pid;
|
static int pid;
|
||||||
|
|
||||||
|
/* This boolean is set if the program being loaded is setuid */
|
||||||
|
static int program_is_setuid;
|
||||||
|
|
||||||
#if STATS
|
#if STATS
|
||||||
struct _link_stats linker_stats;
|
struct _link_stats linker_stats;
|
||||||
#endif
|
#endif
|
||||||
@ -286,7 +290,7 @@ static soinfo *alloc_info(const char *name)
|
|||||||
|
|
||||||
/* Make sure we get a clean block of soinfo */
|
/* Make sure we get a clean block of soinfo */
|
||||||
memset(si, 0, sizeof(soinfo));
|
memset(si, 0, sizeof(soinfo));
|
||||||
strcpy((char*) si->name, name);
|
strlcpy((char*) si->name, name, sizeof(si->name));
|
||||||
sonext->next = si;
|
sonext->next = si;
|
||||||
si->ba_index = -1; /* by default, prelinked */
|
si->ba_index = -1; /* by default, prelinked */
|
||||||
si->next = NULL;
|
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
|
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 ();
|
nullify_closed_stdio ();
|
||||||
call_constructors(si);
|
call_constructors(si);
|
||||||
notify_gdb_of_load(si);
|
notify_gdb_of_load(si);
|
||||||
@ -2045,7 +2049,7 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_library_path(char *path, char *delim)
|
static void parse_library_path(const char *path, char *delim)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *ldpaths_bufp = ldpaths_buf;
|
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;
|
size_t len;
|
||||||
char *ldpreloads_bufp = ldpreloads_buf;
|
char *ldpreloads_bufp = ldpreloads_buf;
|
||||||
@ -2110,8 +2114,8 @@ unsigned __linker_init(unsigned **elfdata)
|
|||||||
unsigned *vecs = (unsigned*) (argv + argc + 1);
|
unsigned *vecs = (unsigned*) (argv + argc + 1);
|
||||||
soinfo *si;
|
soinfo *si;
|
||||||
struct link_map * map;
|
struct link_map * map;
|
||||||
char *ldpath_env = NULL;
|
const char *ldpath_env = NULL;
|
||||||
char *ldpreload_env = NULL;
|
const char *ldpreload_env = NULL;
|
||||||
|
|
||||||
/* Setup a temporary TLS area that is used to get a working
|
/* Setup a temporary TLS area that is used to get a working
|
||||||
* errno for system calls.
|
* errno for system calls.
|
||||||
@ -2135,20 +2139,32 @@ unsigned __linker_init(unsigned **elfdata)
|
|||||||
*/
|
*/
|
||||||
__tls_area[TLS_SLOT_BIONIC_PREINIT] = 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();
|
debugger_init();
|
||||||
|
|
||||||
/* skip past the environment */
|
/* Get a few environment variables */
|
||||||
while(vecs[0] != 0) {
|
{
|
||||||
if(!strncmp((char*) vecs[0], "DEBUG=", 6)) {
|
const char* env;
|
||||||
debug_verbosity = atoi(((char*) vecs[0]) + 6);
|
env = linker_env_get("DEBUG"); /* XXX: TODO: Change to LD_DEBUG */
|
||||||
} else if(!strncmp((char*) vecs[0], "LD_LIBRARY_PATH=", 16)) {
|
if (env)
|
||||||
ldpath_env = (char*) vecs[0] + 16;
|
debug_verbosity = atoi(env);
|
||||||
} else if(!strncmp((char*) vecs[0], "LD_PRELOAD=", 11)) {
|
|
||||||
ldpreload_env = (char*) vecs[0] + 11;
|
/* 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");
|
INFO("[ android linker & debugger ]\n");
|
||||||
DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata);
|
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
|
* is. Don't use alloc_info(), because the linker shouldn't
|
||||||
* be on the soinfo list.
|
* 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.flags = 0;
|
||||||
linker_soinfo.base = 0; // This is the important part; must be zero.
|
linker_soinfo.base = 0; // This is the important part; must be zero.
|
||||||
insert_soinfo_into_debug_map(&linker_soinfo);
|
insert_soinfo_into_debug_map(&linker_soinfo);
|
||||||
@ -2206,10 +2222,10 @@ unsigned __linker_init(unsigned **elfdata)
|
|||||||
si->refcount = 1;
|
si->refcount = 1;
|
||||||
|
|
||||||
/* Use LD_LIBRARY_PATH if we aren't setuid/setgid */
|
/* 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, ":");
|
parse_library_path(ldpath_env, ":");
|
||||||
|
|
||||||
if (ldpreload_env && getuid() == geteuid() && getgid() == getegid()) {
|
if (ldpreload_env) {
|
||||||
parse_preloads(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…
x
Reference in New Issue
Block a user