Skip to content

Commit

Permalink
Enable fortify by default.
Browse files Browse the repository at this point in the history
Test: ./checkbuild.py && ./run_tests.py
Bug: android/ndk#976
Change-Id: Ic14955978abb0045a6bdac3e8a91ed5d12693057
  • Loading branch information
DanAlbert committed Sep 19, 2019
1 parent 78e0da6 commit 9c6bc63
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 0 deletions.
2 changes: 2 additions & 0 deletions build/cmake/android.toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@ endif()
# TODO: Remove when https://github.com/android-ndk/ndk/issues/884 is fixed.
list(APPEND ANDROID_COMPILER_FLAGS -fno-addrsig)

list(APPEND ANDROID_COMPILER_FLAGS -D_FORTIFY_SOURCE=2)

# STL specific flags.
if(ANDROID_STL MATCHES "^c\\+\\+_")
if(ANDROID_ABI MATCHES "^armeabi")
Expand Down
2 changes: 2 additions & 0 deletions build/core/default-build-commands.mk
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ GLOBAL_CFLAGS += \
# TODO: Remove when https://github.com/android-ndk/ndk/issues/884 is fixed.
GLOBAL_CFLAGS += -fno-addrsig

GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=2

GLOBAL_LDFLAGS = \
-target $(LLVM_TRIPLE)$(TARGET_PLATFORM_LEVEL) \
-no-canonical-prefixes \
Expand Down
18 changes: 18 additions & 0 deletions docs/BuildSystemMaintainers.md
Original file line number Diff line number Diff line change
Expand Up @@ -465,13 +465,31 @@ Manual].

### Hardening

#### Stack protectors

It is recommented to build all code with `-fstack-protector-strong`. This causes
the compiler to emit stack guards to protect against security vulnerabilities
caused by buffer overruns.

Note: ndk-build and the NDK's CMake toolchain file enable this option by
default.

#### Fortify

FORTIFY is a set of extensions to the C standard library that tries to catch the
incorrect use of standard functions, such as `memset`, `sprintf`, and `open`.
Where possible, runtime bugs will be diagnosed as errors at compile-time. If not
provable at compile-time, a run-time check is used. Note that the specific set
of APIs checked depends on the `minSdkVersion` used, since run-time support is
required. See [FORTIFY in Android] for more details.

To enable this feature in your build define `_FORTIFY_SOURCE=2` when compiling.

Note: ndk-build and the NDK's CMake toolchain file enable this option by
default.

[FORTIFY in Android]: https://android-developers.googleblog.com/2017/04/fortify-in-android.html

## Common Issues

### Unwinding
Expand Down
4 changes: 4 additions & 0 deletions docs/changelogs/Changelog-r21.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,18 @@ For Android Studio issues, follow the docs on the [Android Studio site].
`cxx-stl/system`, remove that and ensure that `APP_STL` is set to `system`
instead.
* `llvm-ar` is now used instead of `ar`.
* [Issue 976]: ndk-build and the CMake toolchain file now enable
`_FORTIFY_SOURCE` by default. See [FORTIFY in Android] for more details.

[FORTIFY in Android]: https://android-developers.googleblog.com/2017/04/fortify-in-android.html
[Issue 1004]: https://github.com/android-ndk/ndk/issues/1004
[Issue 1028]: https://github.com/android/ndk/issues/1028
[Issue 744]: https://github.com/android/ndk/issues/744
[Issue 855]: https://github.com/android-ndk/ndk/issues/855
[Issue 859]: https://github.com/android-ndk/ndk/issues/859
[Issue 884]: https://github.com/android-ndk/ndk/issues/884
[Issue 885]: https://github.com/android-ndk/ndk/issues/885
[Issue 976]: https://github.com/android/ndk/issues/976
[blacklist CPUs]: https://support.google.com/googleplay/android-developer/answer/7353455?hl=en
[maintainer_linkers]: https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Linkers

Expand Down
3 changes: 3 additions & 0 deletions tests/build/fortify_strcpy_available/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.6.0)

add_executable(foo jni/foo.cpp)
6 changes: 6 additions & 0 deletions tests/build/fortify_strcpy_available/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_EXECUTABLE)
12 changes: 12 additions & 0 deletions tests/build/fortify_strcpy_available/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <string.h>

#if _FORTIFY_SOURCE != 2
#error Expected _FORTIFY_SOURCE=2
#endif

int main(int argc, char** argv) {
const char src[] = "foo bar baz";
char dst[10];
strcpy(dst, src);
return 0;
}
13 changes: 13 additions & 0 deletions tests/build/fortify_strcpy_available/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from typing import Optional

from ndk.test.types import Test


def build_unsupported(test: Test) -> Optional[str]:
if test.config.api is not None and test.config.api < 17:
return f'__strcpy_chk not available in android-{test.config.api}'
return None


def is_negative_test() -> bool:
return True
9 changes: 9 additions & 0 deletions tests/device/fortify_runtime/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := fortify_test
LOCAL_SRC_FILES := fortify_test.cpp
LOCAL_STATIC_LIBRARIES := googletest_main
include $(BUILD_EXECUTABLE)

$(call import-module,third_party/googletest)
1 change: 1 addition & 0 deletions tests/device/fortify_runtime/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
APP_STL := c++_static
11 changes: 11 additions & 0 deletions tests/device/fortify_runtime/jni/fortify_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <memory.h>

#include "gtest/gtest.h"
#include "gtest/gtest-death-test.h"

TEST(fortify, smoke) {
char cs[4];
char* p = cs;
ASSERT_DEATH(memset(p, 0, 5),
"memset: prevented 5-byte write into 4-byte buffer");
}
10 changes: 10 additions & 0 deletions tests/device/fortify_runtime/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from typing import Optional

from ndk.test.devices import Device
from ndk.test.types import Test


def run_unsupported(test: Test, device: Device) -> Optional[str]:
if test.config.api is not None and test.config.api < 17:
return f'__memset_chk not available in android-{test.config.api}'
return None
3 changes: 3 additions & 0 deletions tests/device/fortify_strcpy_unavailable/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.6.0)

add_executable(foo jni/foo.cpp)
6 changes: 6 additions & 0 deletions tests/device/fortify_strcpy_unavailable/jni/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.cpp
include $(BUILD_EXECUTABLE)
12 changes: 12 additions & 0 deletions tests/device/fortify_strcpy_unavailable/jni/foo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <string.h>

#if _FORTIFY_SOURCE != 2
#error Expected _FORTIFY_SOURCE=2
#endif

int main(int argc, char** argv) {
const char src[] = "foo bar baz";
char dst[10];
strcpy(dst, src);
return 0;
}
9 changes: 9 additions & 0 deletions tests/device/fortify_strcpy_unavailable/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from typing import Optional

from ndk.test.types import Test


def build_unsupported(test: Test) -> Optional[str]:
if test.config.api is not None and test.config.api >= 21:
return f'strcpy is caught at build time for android-{test.config.api}'
return None

0 comments on commit 9c6bc63

Please sign in to comment.