elf: Ignore LD_BIND_NOW and LD_BIND_NOT for setuid binaries
[platform/upstream/glibc.git] / elf / tst-_dl_addr_inside_object.c
1 /* Unit test for _dl_addr_inside_object.
2    Copyright (C) 2016-2023 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <link.h>
22 #include <elf.h>
23 #include <libc-symbols.h>
24
25 extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr);
26
27 static int
28 do_test (void)
29 {
30   int ret, err = 0;
31   ElfW(Addr) addr;
32   struct link_map map;
33   ElfW(Phdr) header;
34   map.l_phdr = &header;
35   map.l_phnum = 1;
36   map.l_addr = 0x0;
37   /* Segment spans 0x2000 -> 0x4000.  */
38   header.p_vaddr = 0x2000;
39   header.p_memsz = 0x2000;
40   header.p_type = PT_LOAD;
41   /* Address is above the segment e.g. > 0x4000.  */
42   addr = 0x5000;
43   ret = _dl_addr_inside_object (&map, addr);
44   switch (ret)
45     {
46       case 0:
47         printf ("PASS: Above: Address is detected as outside the segment.\n");
48         break;
49       case 1:
50         printf ("FAIL: Above: Address is detected as inside the segment.\n");
51         err++;
52         break;
53       default:
54         printf ("FAIL: Above: Invalid return value.\n");
55         exit (1);
56     }
57   /* Address is inside the segment e.g. 0x2000 < addr < 0x4000.  */
58   addr = 0x3000;
59   ret = _dl_addr_inside_object (&map, addr);
60   switch (ret)
61     {
62       case 0:
63         printf ("FAIL: Inside: Address is detected as outside the segment.\n");
64         err++;
65         break;
66       case 1:
67         printf ("PASS: Inside: Address is detected as inside the segment.\n");
68         break;
69       default:
70         printf ("FAIL: Inside: Invalid return value.\n");
71         exit (1);
72     }
73   /* Address is below the segment e.g. < 0x2000.  */
74   addr = 0x1000;
75   ret = _dl_addr_inside_object (&map, addr);
76   switch (ret)
77     {
78       case 0:
79         printf ("PASS: Below: Address is detected as outside the segment.\n");
80         break;
81       case 1:
82         printf ("FAIL: Below: Address is detected as inside the segment.\n");
83         err++;
84         break;
85       default:
86         printf ("FAIL: Below: Invalid return value.\n");
87         exit (1);
88     }
89   /* Address is in the segment and addr == p_vaddr.  */
90   addr = 0x2000;
91   ret = _dl_addr_inside_object (&map, addr);
92   switch (ret)
93     {
94       case 0:
95         printf ("FAIL: At p_vaddr: Address is detected as outside the segment.\n");
96         err++;
97         break;
98       case 1:
99         printf ("PASS: At p_vaddr: Address is detected as inside the segment.\n");
100         break;
101       default:
102         printf ("FAIL: At p_vaddr: Invalid return value.\n");
103         exit (1);
104     }
105   /* Address is in the segment and addr == p_vaddr + p_memsz - 1.  */
106   addr = 0x2000 + 0x2000 - 0x1;
107   ret = _dl_addr_inside_object (&map, addr);
108   switch (ret)
109     {
110       case 0:
111         printf ("FAIL: At p_memsz-1: Address is detected as outside the segment.\n");
112         err++;
113         break;
114       case 1:
115         printf ("PASS: At p_memsz-1: Address is detected as inside the segment.\n");
116         break;
117       default:
118         printf ("FAIL: At p_memsz-1: Invalid return value.\n");
119         exit (1);
120     }
121   /* Address is outside the segment and addr == p_vaddr + p_memsz.  */
122   addr = 0x2000 + 0x2000;
123   ret = _dl_addr_inside_object (&map, addr);
124   switch (ret)
125     {
126       case 0:
127         printf ("PASS: At p_memsz: Address is detected as outside the segment.\n");
128         break;
129       case 1:
130         printf ("FAIL: At p_memsz: Address is detected as inside the segment.\n");
131         err++;
132         break;
133       default:
134         printf ("FAIL: At p_memsz: Invalid return value.\n");
135         exit (1);
136     }
137   /* Address is outside the segment and p_vaddr at maximum address.  */
138   addr = 0x0 - 0x2;
139   header.p_vaddr = 0x0 - 0x1;
140   header.p_memsz = 0x1;
141   ret = _dl_addr_inside_object (&map, addr);
142   switch (ret)
143     {
144       case 0:
145         printf ("PASS: At max: Address is detected as outside the segment.\n");
146         break;
147       case 1:
148         printf ("FAIL: At max: Address is detected as inside the segment.\n");
149         err++;
150         break;
151       default:
152         printf ("FAIL: At max: Invalid return value.\n");
153         exit (1);
154     }
155   /* Address is outside the segment and p_vaddr at minimum address.  */
156   addr = 0x1;
157   header.p_vaddr = 0x0;
158   header.p_memsz = 0x1;
159   ret = _dl_addr_inside_object (&map, addr);
160   switch (ret)
161     {
162       case 0:
163         printf ("PASS: At min: Address is detected as outside the segment.\n");
164         break;
165       case 1:
166         printf ("FAIL: At min: Address is detected as inside the segment.\n");
167         err++;
168         break;
169       default:
170         printf ("FAIL: At min: Invalid return value.\n");
171         exit (1);
172     }
173   /* Address is always inside the segment with p_memsz at max.  */
174   addr = 0x0;
175   header.p_vaddr = 0x0;
176   header.p_memsz = 0x0 - 0x1;
177   ret = _dl_addr_inside_object (&map, addr);
178   switch (ret)
179     {
180       case 0:
181         printf ("FAIL: At maxmem: Address is detected as outside the segment.\n");
182         err++;
183         break;
184       case 1:
185         printf ("PASS: At maxmem: Address is detected as inside the segment.\n");
186         break;
187       default:
188         printf ("FAIL: At maxmem: Invalid return value.\n");
189         exit (1);
190     }
191   /* Attempt to wrap addr into the segment.
192      Pick a load address in the middle of the address space.
193      Place the test address at 0x0 so it wraps to the middle again.  */
194   map.l_addr = 0x0 - 0x1;
195   map.l_addr = map.l_addr / 2;
196   addr = 0;
197   /* Setup a segment covering 1/2 the address space.  */
198   header.p_vaddr = 0x0;
199   header.p_memsz = 0x0 - 0x1 - map.l_addr;
200   /* No matter where you place addr everything is shifted modulo l_addr
201      and even with this underflow you're always 1 byte away from being
202      in the range.  */
203   ret = _dl_addr_inside_object (&map, addr);
204   switch (ret)
205     {
206       case 0:
207         printf ("PASS: Underflow: Address is detected as outside the segment.\n");
208         break;
209       case 1:
210         printf ("FAIL: Underflow: Address is detected as inside the segment.\n");
211         err++;
212         break;
213       default:
214         printf ("FAIL: Underflow: Invalid return value.\n");
215         exit (1);
216     }
217
218   return err;
219 }
220
221 #include <support/test-driver.c>