1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker *
5*8d67ca89SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker * are met:
8*8d67ca89SAndroid Build Coastguard Worker * * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker * * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker * the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker * distribution.
14*8d67ca89SAndroid Build Coastguard Worker *
15*8d67ca89SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker */
28*8d67ca89SAndroid Build Coastguard Worker
29*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
30*8d67ca89SAndroid Build Coastguard Worker #include <iostream>
31*8d67ca89SAndroid Build Coastguard Worker #include <sstream>
32*8d67ca89SAndroid Build Coastguard Worker #include <string>
33*8d67ca89SAndroid Build Coastguard Worker
34*8d67ca89SAndroid Build Coastguard Worker #include <gtest/gtest.h>
35*8d67ca89SAndroid Build Coastguard Worker
36*8d67ca89SAndroid Build Coastguard Worker #include "linker.h"
37*8d67ca89SAndroid Build Coastguard Worker #include "linker_globals.h"
38*8d67ca89SAndroid Build Coastguard Worker #include "linker_note_gnu_property.h"
39*8d67ca89SAndroid Build Coastguard Worker #include "platform/bionic/macros.h"
40*8d67ca89SAndroid Build Coastguard Worker
41*8d67ca89SAndroid Build Coastguard Worker #define SONAME "test_so"
42*8d67ca89SAndroid Build Coastguard Worker
43*8d67ca89SAndroid Build Coastguard Worker static char error_buffer[1024];
44*8d67ca89SAndroid Build Coastguard Worker
linker_get_error_buffer()45*8d67ca89SAndroid Build Coastguard Worker char* linker_get_error_buffer() {
46*8d67ca89SAndroid Build Coastguard Worker return error_buffer;
47*8d67ca89SAndroid Build Coastguard Worker }
48*8d67ca89SAndroid Build Coastguard Worker
linker_get_error_buffer_size()49*8d67ca89SAndroid Build Coastguard Worker size_t linker_get_error_buffer_size() {
50*8d67ca89SAndroid Build Coastguard Worker return std::size(error_buffer);
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker
reset_error_buffer()53*8d67ca89SAndroid Build Coastguard Worker static void reset_error_buffer() {
54*8d67ca89SAndroid Build Coastguard Worker error_buffer[0] = '\0';
55*8d67ca89SAndroid Build Coastguard Worker }
56*8d67ca89SAndroid Build Coastguard Worker
57*8d67ca89SAndroid Build Coastguard Worker platform_properties g_platform_properties {
58*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
59*8d67ca89SAndroid Build Coastguard Worker // Assume "hardware" supports Armv8.5-A BTI.
60*8d67ca89SAndroid Build Coastguard Worker .bti_supported = true
61*8d67ca89SAndroid Build Coastguard Worker #endif
62*8d67ca89SAndroid Build Coastguard Worker };
63*8d67ca89SAndroid Build Coastguard Worker
64*8d67ca89SAndroid Build Coastguard Worker // Helper macro to make the test cleaner.
65*8d67ca89SAndroid Build Coastguard Worker #define PHDR_WITH_NOTE_GNU_PROPERTY(__prop) \
66*8d67ca89SAndroid Build Coastguard Worker reset_error_buffer(); \
67*8d67ca89SAndroid Build Coastguard Worker ElfW(Phdr) phdrs[] = { \
68*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_LOAD}, \
69*8d67ca89SAndroid Build Coastguard Worker { \
70*8d67ca89SAndroid Build Coastguard Worker .p_type = PT_GNU_PROPERTY, \
71*8d67ca89SAndroid Build Coastguard Worker .p_vaddr = reinterpret_cast<ElfW(Addr)>(__prop), \
72*8d67ca89SAndroid Build Coastguard Worker .p_memsz = sizeof(ElfW(NhdrGNUProperty)) + (__prop)->nhdr.n_descsz, \
73*8d67ca89SAndroid Build Coastguard Worker }, \
74*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_NULL}, \
75*8d67ca89SAndroid Build Coastguard Worker }; \
76*8d67ca89SAndroid Build Coastguard Worker auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME)
77*8d67ca89SAndroid Build Coastguard Worker
78*8d67ca89SAndroid Build Coastguard Worker // Helper to check for no error message.
79*8d67ca89SAndroid Build Coastguard Worker #define ASSERT_NO_ERROR_MSG() ASSERT_STREQ(error_buffer, "")
80*8d67ca89SAndroid Build Coastguard Worker
81*8d67ca89SAndroid Build Coastguard Worker // Helper to check expected error message.
82*8d67ca89SAndroid Build Coastguard Worker #define ASSERT_ERROR_MSG_EQ(__expected) ASSERT_STREQ(error_buffer, "\"" SONAME "\" " __expected)
83*8d67ca89SAndroid Build Coastguard Worker
test_bti_not_supported(GnuPropertySection & note __unused)84*8d67ca89SAndroid Build Coastguard Worker static void test_bti_not_supported(GnuPropertySection& note __unused) {
85*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
86*8d67ca89SAndroid Build Coastguard Worker ASSERT_FALSE(note.IsBTICompatible());
87*8d67ca89SAndroid Build Coastguard Worker #endif
88*8d67ca89SAndroid Build Coastguard Worker }
89*8d67ca89SAndroid Build Coastguard Worker
90*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
test_bti_supported(GnuPropertySection & note __unused)91*8d67ca89SAndroid Build Coastguard Worker static void test_bti_supported(GnuPropertySection& note __unused) {
92*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(note.IsBTICompatible());
93*8d67ca89SAndroid Build Coastguard Worker }
94*8d67ca89SAndroid Build Coastguard Worker #endif
95*8d67ca89SAndroid Build Coastguard Worker
96*8d67ca89SAndroid Build Coastguard Worker // Helper class to build a well-formed .note.gnu.property section.
97*8d67ca89SAndroid Build Coastguard Worker class GnuPropertySectionBuilder {
98*8d67ca89SAndroid Build Coastguard Worker public:
GnuPropertySectionBuilder()99*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder() {
100*8d67ca89SAndroid Build Coastguard Worker note = reinterpret_cast<ElfW(NhdrGNUProperty)*>(§ion[0]);
101*8d67ca89SAndroid Build Coastguard Worker note->nhdr.n_namesz = 4;
102*8d67ca89SAndroid Build Coastguard Worker note->nhdr.n_descsz = 0;
103*8d67ca89SAndroid Build Coastguard Worker note->nhdr.n_type = NT_GNU_PROPERTY_TYPE_0;
104*8d67ca89SAndroid Build Coastguard Worker memcpy(note->n_name, "GNU", 4);
105*8d67ca89SAndroid Build Coastguard Worker }
106*8d67ca89SAndroid Build Coastguard Worker
107*8d67ca89SAndroid Build Coastguard Worker template <typename T>
push(ElfW (Word)pr_type,ElfW (Word)pr_datasz,const T * pr_data)108*8d67ca89SAndroid Build Coastguard Worker bool push(ElfW(Word) pr_type, ElfW(Word) pr_datasz, const T* pr_data) {
109*8d67ca89SAndroid Build Coastguard Worker // Must be aligned.
110*8d67ca89SAndroid Build Coastguard Worker const uintptr_t addition = align_up(pr_datasz, sizeof(ElfW(Addr)));
111*8d67ca89SAndroid Build Coastguard Worker if ((offset() + addition) > kMaxSectionSize) {
112*8d67ca89SAndroid Build Coastguard Worker return false;
113*8d67ca89SAndroid Build Coastguard Worker }
114*8d67ca89SAndroid Build Coastguard Worker ++entries;
115*8d67ca89SAndroid Build Coastguard Worker ElfW(Prop)* prop = reinterpret_cast<ElfW(Prop)*>(§ion[offset()]);
116*8d67ca89SAndroid Build Coastguard Worker // Header
117*8d67ca89SAndroid Build Coastguard Worker prop->pr_type = pr_type;
118*8d67ca89SAndroid Build Coastguard Worker prop->pr_datasz = pr_datasz;
119*8d67ca89SAndroid Build Coastguard Worker step(2 * sizeof(ElfW(Word)));
120*8d67ca89SAndroid Build Coastguard Worker // Data
121*8d67ca89SAndroid Build Coastguard Worker memcpy(§ion[offset()], reinterpret_cast<const void*>(pr_data), pr_datasz);
122*8d67ca89SAndroid Build Coastguard Worker step(pr_datasz);
123*8d67ca89SAndroid Build Coastguard Worker // Padding
124*8d67ca89SAndroid Build Coastguard Worker memset(§ion[offset()], 0xAA, addition - pr_datasz);
125*8d67ca89SAndroid Build Coastguard Worker step(addition - pr_datasz);
126*8d67ca89SAndroid Build Coastguard Worker return true;
127*8d67ca89SAndroid Build Coastguard Worker }
128*8d67ca89SAndroid Build Coastguard Worker
ElfW(NhdrGNUProperty)129*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty)* data() const { return note; }
130*8d67ca89SAndroid Build Coastguard Worker
dump() const131*8d67ca89SAndroid Build Coastguard Worker void dump() const {
132*8d67ca89SAndroid Build Coastguard Worker std::cout << ".note.gnu.property\n";
133*8d67ca89SAndroid Build Coastguard Worker dump_member("n_namesz", note->nhdr.n_namesz);
134*8d67ca89SAndroid Build Coastguard Worker dump_member("n_descsz", note->nhdr.n_descsz);
135*8d67ca89SAndroid Build Coastguard Worker dump_member("n_type ", note->nhdr.n_type);
136*8d67ca89SAndroid Build Coastguard Worker dump_member("n_name ", note->n_name);
137*8d67ca89SAndroid Build Coastguard Worker dump_member("entries ", entries);
138*8d67ca89SAndroid Build Coastguard Worker if (entries > 0) {
139*8d67ca89SAndroid Build Coastguard Worker std::cout << " raw data:";
140*8d67ca89SAndroid Build Coastguard Worker const uintptr_t end = note->nhdr.n_descsz + 16;
141*8d67ca89SAndroid Build Coastguard Worker for (uintptr_t offset = 16; offset < end; ++offset) {
142*8d67ca89SAndroid Build Coastguard Worker std::cout << std::hex;
143*8d67ca89SAndroid Build Coastguard Worker if ((offset % 8) == 0) {
144*8d67ca89SAndroid Build Coastguard Worker std::cout << "\n ";
145*8d67ca89SAndroid Build Coastguard Worker }
146*8d67ca89SAndroid Build Coastguard Worker auto value = static_cast<unsigned>(section[offset]);
147*8d67ca89SAndroid Build Coastguard Worker std::cout << " ";
148*8d67ca89SAndroid Build Coastguard Worker if (value < 0x10) {
149*8d67ca89SAndroid Build Coastguard Worker std::cout << "0";
150*8d67ca89SAndroid Build Coastguard Worker }
151*8d67ca89SAndroid Build Coastguard Worker std::cout << static_cast<unsigned>(section[offset]);
152*8d67ca89SAndroid Build Coastguard Worker }
153*8d67ca89SAndroid Build Coastguard Worker std::cout << std::dec << "\n";
154*8d67ca89SAndroid Build Coastguard Worker }
155*8d67ca89SAndroid Build Coastguard Worker }
156*8d67ca89SAndroid Build Coastguard Worker
corrupt_n_descsz(ElfW (Word)n_descsz)157*8d67ca89SAndroid Build Coastguard Worker void corrupt_n_descsz(ElfW(Word) n_descsz) { note->nhdr.n_descsz = n_descsz; }
158*8d67ca89SAndroid Build Coastguard Worker
159*8d67ca89SAndroid Build Coastguard Worker private:
160*8d67ca89SAndroid Build Coastguard Worker template <typename T>
dump_member(const char * name,T value) const161*8d67ca89SAndroid Build Coastguard Worker void dump_member(const char* name, T value) const {
162*8d67ca89SAndroid Build Coastguard Worker std::cout << " " << name << " " << value << "\n";
163*8d67ca89SAndroid Build Coastguard Worker }
164*8d67ca89SAndroid Build Coastguard Worker
offset() const165*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) offset() const { return note->nhdr.n_descsz + 16; }
166*8d67ca89SAndroid Build Coastguard Worker
167*8d67ca89SAndroid Build Coastguard Worker template <typename T>
step(T value)168*8d67ca89SAndroid Build Coastguard Worker void step(T value) {
169*8d67ca89SAndroid Build Coastguard Worker note->nhdr.n_descsz += static_cast<ElfW(Word)>(value);
170*8d67ca89SAndroid Build Coastguard Worker }
171*8d67ca89SAndroid Build Coastguard Worker
172*8d67ca89SAndroid Build Coastguard Worker static const size_t kMaxSectionSize = 1024;
173*8d67ca89SAndroid Build Coastguard Worker
174*8d67ca89SAndroid Build Coastguard Worker alignas(8) uint8_t section[kMaxSectionSize];
175*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty)* note;
176*8d67ca89SAndroid Build Coastguard Worker size_t entries = 0;
177*8d67ca89SAndroid Build Coastguard Worker };
178*8d67ca89SAndroid Build Coastguard Worker
179*8d67ca89SAndroid Build Coastguard Worker // Tests that the default constructed instance does not report support
180*8d67ca89SAndroid Build Coastguard Worker // for Armv8.5-A BTI.
TEST(note_gnu_property,default)181*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, default) {
182*8d67ca89SAndroid Build Coastguard Worker GnuPropertySection note;
183*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
184*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
185*8d67ca89SAndroid Build Coastguard Worker }
186*8d67ca89SAndroid Build Coastguard Worker
187*8d67ca89SAndroid Build Coastguard Worker // Tests that an instance without valid phdr pointer does not report
188*8d67ca89SAndroid Build Coastguard Worker // support for Armv8.5-A BTI.
TEST(note_gnu_property,phdr_null)189*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, phdr_null) {
190*8d67ca89SAndroid Build Coastguard Worker auto note = GnuPropertySection(nullptr, 0, 0, SONAME);
191*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
192*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
193*8d67ca89SAndroid Build Coastguard Worker }
194*8d67ca89SAndroid Build Coastguard Worker
195*8d67ca89SAndroid Build Coastguard Worker // Tests that an instance without finding PT_GNU_PROPERTY does not
196*8d67ca89SAndroid Build Coastguard Worker // report support for Armv8.5-A BTI.
TEST(note_gnu_property,no_pt_gnu_property)197*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, no_pt_gnu_property) {
198*8d67ca89SAndroid Build Coastguard Worker ElfW(Phdr) phdrs[] = {
199*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_LOAD},
200*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_NULL},
201*8d67ca89SAndroid Build Coastguard Worker };
202*8d67ca89SAndroid Build Coastguard Worker
203*8d67ca89SAndroid Build Coastguard Worker reset_error_buffer();
204*8d67ca89SAndroid Build Coastguard Worker auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
205*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
206*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
207*8d67ca89SAndroid Build Coastguard Worker }
208*8d67ca89SAndroid Build Coastguard Worker
209*8d67ca89SAndroid Build Coastguard Worker // Tests the validity check for invalid PT_GNU_PROPERTY size.
TEST(note_gnu_property,pt_gnu_property_bad_size)210*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_size) {
211*8d67ca89SAndroid Build Coastguard Worker ElfW(Phdr) phdrs[] = {
212*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_LOAD},
213*8d67ca89SAndroid Build Coastguard Worker {
214*8d67ca89SAndroid Build Coastguard Worker .p_type = PT_GNU_PROPERTY,
215*8d67ca89SAndroid Build Coastguard Worker .p_vaddr = 0,
216*8d67ca89SAndroid Build Coastguard Worker .p_memsz = sizeof(ElfW(NhdrGNUProperty)) - 1, // Invalid
217*8d67ca89SAndroid Build Coastguard Worker },
218*8d67ca89SAndroid Build Coastguard Worker {.p_type = PT_NULL},
219*8d67ca89SAndroid Build Coastguard Worker };
220*8d67ca89SAndroid Build Coastguard Worker
221*8d67ca89SAndroid Build Coastguard Worker reset_error_buffer();
222*8d67ca89SAndroid Build Coastguard Worker auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
223*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
224*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ("PT_GNU_PROPERTY segment is too small. Segment size is 15, minimum is 16.");
225*8d67ca89SAndroid Build Coastguard Worker }
226*8d67ca89SAndroid Build Coastguard Worker
227*8d67ca89SAndroid Build Coastguard Worker // Tests that advertised n_descsz should still fit into p_memsz.
TEST(note_gnu_property,pt_gnu_property_too_small)228*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_too_small) {
229*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty) prop = {
230*8d67ca89SAndroid Build Coastguard Worker .nhdr = {.n_namesz = PT_GNU_PROPERTY, .n_descsz = 1, .n_type = NT_GNU_PROPERTY_TYPE_0},
231*8d67ca89SAndroid Build Coastguard Worker .n_name = "GNU",
232*8d67ca89SAndroid Build Coastguard Worker };
233*8d67ca89SAndroid Build Coastguard Worker ElfW(Phdr) phdrs[] = {
234*8d67ca89SAndroid Build Coastguard Worker {
235*8d67ca89SAndroid Build Coastguard Worker .p_type = PT_GNU_PROPERTY,
236*8d67ca89SAndroid Build Coastguard Worker .p_vaddr = reinterpret_cast<ElfW(Addr)>(&prop),
237*8d67ca89SAndroid Build Coastguard Worker .p_memsz = sizeof(ElfW(NhdrGNUProperty)), // Off by one
238*8d67ca89SAndroid Build Coastguard Worker },
239*8d67ca89SAndroid Build Coastguard Worker };
240*8d67ca89SAndroid Build Coastguard Worker
241*8d67ca89SAndroid Build Coastguard Worker reset_error_buffer();
242*8d67ca89SAndroid Build Coastguard Worker auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
243*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
244*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ("PT_GNU_PROPERTY segment p_memsz (16) is too small for note n_descsz (1).");
245*8d67ca89SAndroid Build Coastguard Worker }
246*8d67ca89SAndroid Build Coastguard Worker
247*8d67ca89SAndroid Build Coastguard Worker // Tests the validity check for invalid .note.gnu.property type.
TEST(note_gnu_property,pt_gnu_property_bad_type)248*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_type) {
249*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty) prop = {
250*8d67ca89SAndroid Build Coastguard Worker .nhdr =
251*8d67ca89SAndroid Build Coastguard Worker {
252*8d67ca89SAndroid Build Coastguard Worker .n_namesz = 4,
253*8d67ca89SAndroid Build Coastguard Worker .n_descsz = 0,
254*8d67ca89SAndroid Build Coastguard Worker .n_type = NT_GNU_PROPERTY_TYPE_0 - 1 // Invalid
255*8d67ca89SAndroid Build Coastguard Worker },
256*8d67ca89SAndroid Build Coastguard Worker .n_name = "GNU",
257*8d67ca89SAndroid Build Coastguard Worker };
258*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
259*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
260*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected note type. Expected 5, got 4.");
261*8d67ca89SAndroid Build Coastguard Worker }
262*8d67ca89SAndroid Build Coastguard Worker
263*8d67ca89SAndroid Build Coastguard Worker // Tests the validity check for invalid .note.gnu.property name size.
TEST(note_gnu_property,pt_gnu_property_bad_namesz)264*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_namesz) {
265*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty) prop = {
266*8d67ca89SAndroid Build Coastguard Worker .nhdr = {.n_namesz = 3, // Invalid
267*8d67ca89SAndroid Build Coastguard Worker .n_descsz = 0,
268*8d67ca89SAndroid Build Coastguard Worker .n_type = NT_GNU_PROPERTY_TYPE_0},
269*8d67ca89SAndroid Build Coastguard Worker .n_name = "GNU",
270*8d67ca89SAndroid Build Coastguard Worker };
271*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
272*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
273*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected name size. Expected 4, got 3.");
274*8d67ca89SAndroid Build Coastguard Worker }
275*8d67ca89SAndroid Build Coastguard Worker
276*8d67ca89SAndroid Build Coastguard Worker // Tests the validity check for invalid .note.gnu.property name.
TEST(note_gnu_property,pt_gnu_property_bad_name)277*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_name) {
278*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty) prop = {
279*8d67ca89SAndroid Build Coastguard Worker .nhdr = {.n_namesz = 4, .n_descsz = 0, .n_type = NT_GNU_PROPERTY_TYPE_0},
280*8d67ca89SAndroid Build Coastguard Worker .n_name = "ABC", // Invalid
281*8d67ca89SAndroid Build Coastguard Worker };
282*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
283*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
284*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected name. Expected 'GNU', got 'ABC'.");
285*8d67ca89SAndroid Build Coastguard Worker }
286*8d67ca89SAndroid Build Coastguard Worker
287*8d67ca89SAndroid Build Coastguard Worker // Tests the validity check for not enough space for a Program Property header.
TEST(note_gnu_property,pt_gnu_property_pphdr_no_space)288*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_pphdr_no_space) {
289*8d67ca89SAndroid Build Coastguard Worker ElfW(NhdrGNUProperty) prop = {
290*8d67ca89SAndroid Build Coastguard Worker .nhdr = {.n_namesz = 4,
291*8d67ca89SAndroid Build Coastguard Worker .n_descsz = 7, // Invalid
292*8d67ca89SAndroid Build Coastguard Worker .n_type = NT_GNU_PROPERTY_TYPE_0},
293*8d67ca89SAndroid Build Coastguard Worker .n_name = "GNU",
294*8d67ca89SAndroid Build Coastguard Worker };
295*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
296*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
297*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(".note.gnu.property: no more space left for a Program Property Note header.");
298*8d67ca89SAndroid Build Coastguard Worker }
299*8d67ca89SAndroid Build Coastguard Worker
300*8d67ca89SAndroid Build Coastguard Worker // Tests an empty .note.gnu.property.
TEST(note_gnu_property,pt_gnu_property_no_data)301*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_no_data) {
302*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
303*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
304*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
305*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
306*8d67ca89SAndroid Build Coastguard Worker }
307*8d67ca89SAndroid Build Coastguard Worker
308*8d67ca89SAndroid Build Coastguard Worker // Tests a .note.gnu.property section with elements with pr_datasz = 0.
TEST(note_gnu_property,pt_gnu_property_no_prop)309*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_no_prop) {
310*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
311*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(1, 0, (void*)nullptr));
312*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(2, 0, (void*)nullptr));
313*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(3, 0, (void*)nullptr));
314*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
315*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
316*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
317*8d67ca89SAndroid Build Coastguard Worker }
318*8d67ca89SAndroid Build Coastguard Worker
319*8d67ca89SAndroid Build Coastguard Worker // Tests that GNU_PROPERTY_AARCH64_FEATURE_1_AND must have pr_datasz = 4.
TEST(note_gnu_property,pt_gnu_property_bad_pr_datasz)320*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_pr_datasz) {
321*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
322*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
323*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI, 0, 0};
324*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, 12, &pr_data));
325*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
326*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
327*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(
328*8d67ca89SAndroid Build Coastguard Worker ".note.gnu.property: property descriptor size is invalid. Expected 4 bytes for "
329*8d67ca89SAndroid Build Coastguard Worker "GNU_PROPERTY_AARCH64_FEATURE_1_AND, got 12.");
330*8d67ca89SAndroid Build Coastguard Worker #else
331*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
332*8d67ca89SAndroid Build Coastguard Worker #endif
333*8d67ca89SAndroid Build Coastguard Worker }
334*8d67ca89SAndroid Build Coastguard Worker
335*8d67ca89SAndroid Build Coastguard Worker // Tests a .note.gnu.property section with only GNU_PROPERTY_AARCH64_FEATURE_1_BTI property array.
TEST(note_gnu_property,pt_gnu_property_ok_1)336*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_ok_1) {
337*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
338*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
339*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
340*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
341*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
342*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
343*8d67ca89SAndroid Build Coastguard Worker test_bti_supported(note);
344*8d67ca89SAndroid Build Coastguard Worker #else
345*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
346*8d67ca89SAndroid Build Coastguard Worker #endif
347*8d67ca89SAndroid Build Coastguard Worker }
348*8d67ca89SAndroid Build Coastguard Worker
349*8d67ca89SAndroid Build Coastguard Worker // Tests a .note.gnu.property section with only GNU_PROPERTY_AARCH64_FEATURE_1_BTI property array.
TEST(note_gnu_property,pt_gnu_property_ok_2)350*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_ok_2) {
351*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
352*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
353*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {static_cast<ElfW(Word)>(~GNU_PROPERTY_AARCH64_FEATURE_1_BTI)};
354*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
355*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
356*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
357*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
358*8d67ca89SAndroid Build Coastguard Worker #else
359*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
360*8d67ca89SAndroid Build Coastguard Worker #endif
361*8d67ca89SAndroid Build Coastguard Worker }
362*8d67ca89SAndroid Build Coastguard Worker
363*8d67ca89SAndroid Build Coastguard Worker // Tests a .note.gnu.property section with more property arrays.
TEST(note_gnu_property,pt_gnu_property_ok_3)364*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_ok_3) {
365*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
366*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
367*8d67ca89SAndroid Build Coastguard Worker
368*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data_0[8] = {0xCD};
369*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(1, 4, &pr_data_0));
370*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(2, 3, &pr_data_0));
371*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(3, 8, &pr_data_0));
372*8d67ca89SAndroid Build Coastguard Worker
373*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
374*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
375*8d67ca89SAndroid Build Coastguard Worker
376*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(4, 1, &pr_data_0));
377*8d67ca89SAndroid Build Coastguard Worker
378*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
379*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
380*8d67ca89SAndroid Build Coastguard Worker test_bti_supported(note);
381*8d67ca89SAndroid Build Coastguard Worker #else
382*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
383*8d67ca89SAndroid Build Coastguard Worker #endif
384*8d67ca89SAndroid Build Coastguard Worker }
385*8d67ca89SAndroid Build Coastguard Worker
386*8d67ca89SAndroid Build Coastguard Worker // Tests a .note.gnu.property but with bad property descriptor size.
TEST(note_gnu_property,pt_gnu_property_bad_n_descsz)387*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, pt_gnu_property_bad_n_descsz) {
388*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
389*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
390*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
391*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
392*8d67ca89SAndroid Build Coastguard Worker
393*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) n_descsz;
394*8d67ca89SAndroid Build Coastguard Worker if (sizeof(ElfW(Addr)) == 4) {
395*8d67ca89SAndroid Build Coastguard Worker n_descsz = 11;
396*8d67ca89SAndroid Build Coastguard Worker } else {
397*8d67ca89SAndroid Build Coastguard Worker n_descsz = 15;
398*8d67ca89SAndroid Build Coastguard Worker }
399*8d67ca89SAndroid Build Coastguard Worker
400*8d67ca89SAndroid Build Coastguard Worker prop.corrupt_n_descsz(n_descsz);
401*8d67ca89SAndroid Build Coastguard Worker
402*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
403*8d67ca89SAndroid Build Coastguard Worker if (sizeof(ElfW(Addr)) == 4) {
404*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(
405*8d67ca89SAndroid Build Coastguard Worker ".note.gnu.property: property descriptor size is invalid. Expected at least 12 bytes, got "
406*8d67ca89SAndroid Build Coastguard Worker "11.");
407*8d67ca89SAndroid Build Coastguard Worker } else {
408*8d67ca89SAndroid Build Coastguard Worker ASSERT_ERROR_MSG_EQ(
409*8d67ca89SAndroid Build Coastguard Worker ".note.gnu.property: property descriptor size is invalid. Expected at least 16 bytes, got "
410*8d67ca89SAndroid Build Coastguard Worker "15.");
411*8d67ca89SAndroid Build Coastguard Worker }
412*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
413*8d67ca89SAndroid Build Coastguard Worker #else
414*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
415*8d67ca89SAndroid Build Coastguard Worker #endif
416*8d67ca89SAndroid Build Coastguard Worker }
417*8d67ca89SAndroid Build Coastguard Worker
418*8d67ca89SAndroid Build Coastguard Worker // Tests if platform support is missing.
TEST(note_gnu_property,no_platform_support)419*8d67ca89SAndroid Build Coastguard Worker TEST(note_gnu_property, no_platform_support) {
420*8d67ca89SAndroid Build Coastguard Worker #if defined(__aarch64__)
421*8d67ca89SAndroid Build Coastguard Worker auto bti_supported_orig = g_platform_properties.bti_supported;
422*8d67ca89SAndroid Build Coastguard Worker g_platform_properties.bti_supported = false;
423*8d67ca89SAndroid Build Coastguard Worker
424*8d67ca89SAndroid Build Coastguard Worker GnuPropertySectionBuilder prop;
425*8d67ca89SAndroid Build Coastguard Worker ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
426*8d67ca89SAndroid Build Coastguard Worker ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
427*8d67ca89SAndroid Build Coastguard Worker PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
428*8d67ca89SAndroid Build Coastguard Worker ASSERT_NO_ERROR_MSG();
429*8d67ca89SAndroid Build Coastguard Worker test_bti_not_supported(note);
430*8d67ca89SAndroid Build Coastguard Worker
431*8d67ca89SAndroid Build Coastguard Worker g_platform_properties.bti_supported = bti_supported_orig;
432*8d67ca89SAndroid Build Coastguard Worker #else
433*8d67ca89SAndroid Build Coastguard Worker GTEST_SKIP() << "BTI is not supported on this architecture.";
434*8d67ca89SAndroid Build Coastguard Worker #endif
435*8d67ca89SAndroid Build Coastguard Worker }
436