Merge "add fortified readlink/readlinkat implementations"
This commit is contained in:
		@@ -74,6 +74,8 @@ libc_common_src_files += \
 | 
				
			|||||||
    bionic/__pread64_chk.cpp \
 | 
					    bionic/__pread64_chk.cpp \
 | 
				
			||||||
    bionic/__pread_chk.cpp \
 | 
					    bionic/__pread_chk.cpp \
 | 
				
			||||||
    bionic/__read_chk.cpp \
 | 
					    bionic/__read_chk.cpp \
 | 
				
			||||||
 | 
					    bionic/__readlink_chk.cpp \
 | 
				
			||||||
 | 
					    bionic/__readlinkat_chk.cpp \
 | 
				
			||||||
    bionic/__recvfrom_chk.cpp \
 | 
					    bionic/__recvfrom_chk.cpp \
 | 
				
			||||||
    bionic/__stpcpy_chk.cpp \
 | 
					    bionic/__stpcpy_chk.cpp \
 | 
				
			||||||
    bionic/__stpncpy_chk.cpp \
 | 
					    bionic/__stpncpy_chk.cpp \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										43
									
								
								libc/bionic/__readlink_chk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libc/bionic/__readlink_chk.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" ssize_t __readlink_chk(const char* path, char* buf, size_t size, size_t buf_size) {
 | 
				
			||||||
 | 
					  if (__predict_false(size > buf_size)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("readlink: prevented write past end of buffer", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (__predict_false(size > SSIZE_MAX)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("readlink: size > SSIZE_MAX", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return readlink(path, buf, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								libc/bionic/__readlinkat_chk.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								libc/bionic/__readlinkat_chk.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2015 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.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include "private/libc_logging.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern "C" ssize_t __readlinkat_chk(int dirfd, const char* path, char* buf, size_t size, size_t buf_size) {
 | 
				
			||||||
 | 
					  if (__predict_false(size > buf_size)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("readlinkat: prevented write past end of buffer", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (__predict_false(size > SSIZE_MAX)) {
 | 
				
			||||||
 | 
					    __fortify_chk_fail("readlinkat: size > SSIZE_MAX", 0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return readlinkat(dirfd, path, buf, size);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -26,6 +26,8 @@
 | 
				
			|||||||
 * SUCH DAMAGE.
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#undef _FORTIFY_SOURCE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -239,6 +239,16 @@ __errordecl(__read_dest_size_error, "read called with size bigger than destinati
 | 
				
			|||||||
__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
 | 
					__errordecl(__read_count_toobig_error, "read called with count > SSIZE_MAX");
 | 
				
			||||||
extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
 | 
					extern ssize_t __read_real(int, void*, size_t) __RENAME(read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern ssize_t __readlink_chk(const char*, char*, size_t, size_t);
 | 
				
			||||||
 | 
					__errordecl(__readlink_dest_size_error, "readlink called with size bigger than destination");
 | 
				
			||||||
 | 
					__errordecl(__readlink_size_toobig_error, "readlink called with size > SSIZE_MAX");
 | 
				
			||||||
 | 
					extern ssize_t __readlink_real(const char*, char*, size_t) __RENAME(readlink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t);
 | 
				
			||||||
 | 
					__errordecl(__readlinkat_dest_size_error, "readlinkat called with size bigger than destination");
 | 
				
			||||||
 | 
					__errordecl(__readlinkat_size_toobig_error, "readlinkat called with size > SSIZE_MAX");
 | 
				
			||||||
 | 
					extern ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME(readlinkat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__BIONIC_FORTIFY)
 | 
					#if defined(__BIONIC_FORTIFY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(__USE_FILE_OFFSET64)
 | 
					#if defined(__USE_FILE_OFFSET64)
 | 
				
			||||||
@@ -322,6 +332,56 @@ ssize_t read(int fd, void* buf, size_t count) {
 | 
				
			|||||||
    return __read_chk(fd, buf, count, bos);
 | 
					    return __read_chk(fd, buf, count, bos);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 | 
					ssize_t readlink(const char* path, char* buf, size_t size) {
 | 
				
			||||||
 | 
					    size_t bos = __bos(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__clang__)
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
 | 
				
			||||||
 | 
					        __readlink_size_toobig_error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
 | 
				
			||||||
 | 
					        return __readlink_real(path, buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size > bos)) {
 | 
				
			||||||
 | 
					        __readlink_dest_size_error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size <= bos)) {
 | 
				
			||||||
 | 
					        return __readlink_real(path, buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return __readlink_chk(path, buf, size, bos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__BIONIC_FORTIFY_INLINE
 | 
				
			||||||
 | 
					ssize_t readlinkat(int dirfd, const char* path, char* buf, size_t size) {
 | 
				
			||||||
 | 
					    size_t bos = __bos(buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if !defined(__clang__)
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size > SSIZE_MAX)) {
 | 
				
			||||||
 | 
					        __readlinkat_size_toobig_error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
 | 
				
			||||||
 | 
					        return __readlinkat_real(dirfd, path, buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size > bos)) {
 | 
				
			||||||
 | 
					        __readlinkat_dest_size_error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (__builtin_constant_p(size) && (size <= bos)) {
 | 
				
			||||||
 | 
					        return __readlinkat_real(dirfd, path, buf, size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return __readlinkat_chk(dirfd, path, buf, size, bos);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* defined(__BIONIC_FORTIFY) */
 | 
					#endif /* defined(__BIONIC_FORTIFY) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__END_DECLS
 | 
					__END_DECLS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -647,6 +647,18 @@ TEST_F(DEATHTEST, read_fortified) {
 | 
				
			|||||||
  close(fd);
 | 
					  close(fd);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DEATHTEST, readlink_fortified) {
 | 
				
			||||||
 | 
					  char buf[1];
 | 
				
			||||||
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 | 
					  ASSERT_FORTIFY(readlink("/dev/null", buf, ct));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST_F(DEATHTEST, readlinkat_fortified) {
 | 
				
			||||||
 | 
					  char buf[1];
 | 
				
			||||||
 | 
					  size_t ct = atoi("2"); // prevent optimizations
 | 
				
			||||||
 | 
					  ASSERT_FORTIFY(readlinkat(AT_FDCWD, "/dev/null", buf, ct));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
 | 
					extern "C" char* __strncat_chk(char*, const char*, size_t, size_t);
 | 
				
			||||||
extern "C" char* __strcat_chk(char*, const char*, size_t);
 | 
					extern "C" char* __strcat_chk(char*, const char*, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user