xref: /aosp_15_r20/bionic/linker/linker_note_gnu_property_test.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
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)*>(&section[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)*>(&section[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(&section[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(&section[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