~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/lib/buildid.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /lib/buildid.c (Architecture ppc) and /lib/buildid.c (Architecture i386)


  1 // SPDX-License-Identifier: GPL-2.0                 1 // SPDX-License-Identifier: GPL-2.0
  2                                                     2 
  3 #include <linux/buildid.h>                          3 #include <linux/buildid.h>
  4 #include <linux/cache.h>                            4 #include <linux/cache.h>
  5 #include <linux/elf.h>                              5 #include <linux/elf.h>
  6 #include <linux/kernel.h>                           6 #include <linux/kernel.h>
  7 #include <linux/pagemap.h>                          7 #include <linux/pagemap.h>
  8 #include <linux/secretmem.h>                        8 #include <linux/secretmem.h>
  9                                                     9 
 10 #define BUILD_ID 3                                 10 #define BUILD_ID 3
 11                                                    11 
 12 #define MAX_PHDR_CNT 256                           12 #define MAX_PHDR_CNT 256
 13                                                    13 
 14 struct freader {                                   14 struct freader {
 15         void *buf;                                 15         void *buf;
 16         u32 buf_sz;                                16         u32 buf_sz;
 17         int err;                                   17         int err;
 18         union {                                    18         union {
 19                 struct {                           19                 struct {
 20                         struct file *file;         20                         struct file *file;
 21                         struct folio *folio;       21                         struct folio *folio;
 22                         void *addr;                22                         void *addr;
 23                         loff_t folio_off;          23                         loff_t folio_off;
 24                         bool may_fault;            24                         bool may_fault;
 25                 };                                 25                 };
 26                 struct {                           26                 struct {
 27                         const char *data;          27                         const char *data;
 28                         u64 data_sz;               28                         u64 data_sz;
 29                 };                                 29                 };
 30         };                                         30         };
 31 };                                                 31 };
 32                                                    32 
 33 static void freader_init_from_file(struct frea     33 static void freader_init_from_file(struct freader *r, void *buf, u32 buf_sz,
 34                                    struct file     34                                    struct file *file, bool may_fault)
 35 {                                                  35 {
 36         memset(r, 0, sizeof(*r));                  36         memset(r, 0, sizeof(*r));
 37         r->buf = buf;                              37         r->buf = buf;
 38         r->buf_sz = buf_sz;                        38         r->buf_sz = buf_sz;
 39         r->file = file;                            39         r->file = file;
 40         r->may_fault = may_fault;                  40         r->may_fault = may_fault;
 41 }                                                  41 }
 42                                                    42 
 43 static void freader_init_from_mem(struct fread     43 static void freader_init_from_mem(struct freader *r, const char *data, u64 data_sz)
 44 {                                                  44 {
 45         memset(r, 0, sizeof(*r));                  45         memset(r, 0, sizeof(*r));
 46         r->data = data;                            46         r->data = data;
 47         r->data_sz = data_sz;                      47         r->data_sz = data_sz;
 48 }                                                  48 }
 49                                                    49 
 50 static void freader_put_folio(struct freader *     50 static void freader_put_folio(struct freader *r)
 51 {                                                  51 {
 52         if (!r->folio)                             52         if (!r->folio)
 53                 return;                            53                 return;
 54         kunmap_local(r->addr);                     54         kunmap_local(r->addr);
 55         folio_put(r->folio);                       55         folio_put(r->folio);
 56         r->folio = NULL;                           56         r->folio = NULL;
 57 }                                                  57 }
 58                                                    58 
 59 static int freader_get_folio(struct freader *r     59 static int freader_get_folio(struct freader *r, loff_t file_off)
 60 {                                                  60 {
 61         /* check if we can just reuse current      61         /* check if we can just reuse current folio */
 62         if (r->folio && file_off >= r->folio_o     62         if (r->folio && file_off >= r->folio_off &&
 63             file_off < r->folio_off + folio_si     63             file_off < r->folio_off + folio_size(r->folio))
 64                 return 0;                          64                 return 0;
 65                                                    65 
 66         freader_put_folio(r);                      66         freader_put_folio(r);
 67                                                    67 
 68         /* reject secretmem folios created wit     68         /* reject secretmem folios created with memfd_secret() */
 69         if (secretmem_mapping(r->file->f_mappi     69         if (secretmem_mapping(r->file->f_mapping))
 70                 return -EFAULT;                    70                 return -EFAULT;
 71                                                    71 
 72         r->folio = filemap_get_folio(r->file->     72         r->folio = filemap_get_folio(r->file->f_mapping, file_off >> PAGE_SHIFT);
 73                                                    73 
 74         /* if sleeping is allowed, wait for th     74         /* if sleeping is allowed, wait for the page, if necessary */
 75         if (r->may_fault && (IS_ERR(r->folio)      75         if (r->may_fault && (IS_ERR(r->folio) || !folio_test_uptodate(r->folio))) {
 76                 filemap_invalidate_lock_shared     76                 filemap_invalidate_lock_shared(r->file->f_mapping);
 77                 r->folio = read_cache_folio(r-     77                 r->folio = read_cache_folio(r->file->f_mapping, file_off >> PAGE_SHIFT,
 78                                             NU     78                                             NULL, r->file);
 79                 filemap_invalidate_unlock_shar     79                 filemap_invalidate_unlock_shared(r->file->f_mapping);
 80         }                                          80         }
 81                                                    81 
 82         if (IS_ERR(r->folio) || !folio_test_up     82         if (IS_ERR(r->folio) || !folio_test_uptodate(r->folio)) {
 83                 if (!IS_ERR(r->folio))             83                 if (!IS_ERR(r->folio))
 84                         folio_put(r->folio);       84                         folio_put(r->folio);
 85                 r->folio = NULL;                   85                 r->folio = NULL;
 86                 return -EFAULT;                    86                 return -EFAULT;
 87         }                                          87         }
 88                                                    88 
 89         r->folio_off = folio_pos(r->folio);        89         r->folio_off = folio_pos(r->folio);
 90         r->addr = kmap_local_folio(r->folio, 0     90         r->addr = kmap_local_folio(r->folio, 0);
 91                                                    91 
 92         return 0;                                  92         return 0;
 93 }                                                  93 }
 94                                                    94 
 95 static const void *freader_fetch(struct freade     95 static const void *freader_fetch(struct freader *r, loff_t file_off, size_t sz)
 96 {                                                  96 {
 97         size_t folio_sz;                           97         size_t folio_sz;
 98                                                    98 
 99         /* provided internal temporary buffer      99         /* provided internal temporary buffer should be sized correctly */
100         if (WARN_ON(r->buf && sz > r->buf_sz))    100         if (WARN_ON(r->buf && sz > r->buf_sz)) {
101                 r->err = -E2BIG;                  101                 r->err = -E2BIG;
102                 return NULL;                      102                 return NULL;
103         }                                         103         }
104                                                   104 
105         if (unlikely(file_off + sz < file_off)    105         if (unlikely(file_off + sz < file_off)) {
106                 r->err = -EOVERFLOW;              106                 r->err = -EOVERFLOW;
107                 return NULL;                      107                 return NULL;
108         }                                         108         }
109                                                   109 
110         /* working with memory buffer is much     110         /* working with memory buffer is much more straightforward */
111         if (!r->buf) {                            111         if (!r->buf) {
112                 if (file_off + sz > r->data_sz    112                 if (file_off + sz > r->data_sz) {
113                         r->err = -ERANGE;         113                         r->err = -ERANGE;
114                         return NULL;              114                         return NULL;
115                 }                                 115                 }
116                 return r->data + file_off;        116                 return r->data + file_off;
117         }                                         117         }
118                                                   118 
119         /* fetch or reuse folio for given file    119         /* fetch or reuse folio for given file offset */
120         r->err = freader_get_folio(r, file_off    120         r->err = freader_get_folio(r, file_off);
121         if (r->err)                               121         if (r->err)
122                 return NULL;                      122                 return NULL;
123                                                   123 
124         /* if requested data is crossing folio    124         /* if requested data is crossing folio boundaries, we have to copy
125          * everything into our local buffer to    125          * everything into our local buffer to keep a simple linear memory
126          * access interface                       126          * access interface
127          */                                       127          */
128         folio_sz = folio_size(r->folio);          128         folio_sz = folio_size(r->folio);
129         if (file_off + sz > r->folio_off + fol    129         if (file_off + sz > r->folio_off + folio_sz) {
130                 int part_sz = r->folio_off + f    130                 int part_sz = r->folio_off + folio_sz - file_off;
131                                                   131 
132                 /* copy the part that resides     132                 /* copy the part that resides in the current folio */
133                 memcpy(r->buf, r->addr + (file    133                 memcpy(r->buf, r->addr + (file_off - r->folio_off), part_sz);
134                                                   134 
135                 /* fetch next folio */            135                 /* fetch next folio */
136                 r->err = freader_get_folio(r,     136                 r->err = freader_get_folio(r, r->folio_off + folio_sz);
137                 if (r->err)                       137                 if (r->err)
138                         return NULL;              138                         return NULL;
139                                                   139 
140                 /* copy the rest of requested     140                 /* copy the rest of requested data */
141                 memcpy(r->buf + part_sz, r->ad    141                 memcpy(r->buf + part_sz, r->addr, sz - part_sz);
142                                                   142 
143                 return r->buf;                    143                 return r->buf;
144         }                                         144         }
145                                                   145 
146         /* if data fits in a single folio, jus    146         /* if data fits in a single folio, just return direct pointer */
147         return r->addr + (file_off - r->folio_    147         return r->addr + (file_off - r->folio_off);
148 }                                                 148 }
149                                                   149 
150 static void freader_cleanup(struct freader *r)    150 static void freader_cleanup(struct freader *r)
151 {                                                 151 {
152         if (!r->buf)                              152         if (!r->buf)
153                 return; /* non-file-backed mod    153                 return; /* non-file-backed mode */
154                                                   154 
155         freader_put_folio(r);                     155         freader_put_folio(r);
156 }                                                 156 }
157                                                   157 
158 /*                                                158 /*
159  * Parse build id from the note segment. This     159  * Parse build id from the note segment. This logic can be shared between
160  * 32-bit and 64-bit system, because Elf32_Nhd    160  * 32-bit and 64-bit system, because Elf32_Nhdr and Elf64_Nhdr are
161  * identical.                                     161  * identical.
162  */                                               162  */
163 static int parse_build_id(struct freader *r, u    163 static int parse_build_id(struct freader *r, unsigned char *build_id, __u32 *size,
164                           loff_t note_off, Elf    164                           loff_t note_off, Elf32_Word note_size)
165 {                                                 165 {
166         const char note_name[] = "GNU";           166         const char note_name[] = "GNU";
167         const size_t note_name_sz = sizeof(not    167         const size_t note_name_sz = sizeof(note_name);
168         u32 build_id_off, new_off, note_end, n    168         u32 build_id_off, new_off, note_end, name_sz, desc_sz;
169         const Elf32_Nhdr *nhdr;                   169         const Elf32_Nhdr *nhdr;
170         const char *data;                         170         const char *data;
171                                                   171 
172         if (check_add_overflow(note_off, note_    172         if (check_add_overflow(note_off, note_size, &note_end))
173                 return -EINVAL;                   173                 return -EINVAL;
174                                                   174 
175         while (note_end - note_off > sizeof(El    175         while (note_end - note_off > sizeof(Elf32_Nhdr) + note_name_sz) {
176                 nhdr = freader_fetch(r, note_o    176                 nhdr = freader_fetch(r, note_off, sizeof(Elf32_Nhdr) + note_name_sz);
177                 if (!nhdr)                        177                 if (!nhdr)
178                         return r->err;            178                         return r->err;
179                                                   179 
180                 name_sz = READ_ONCE(nhdr->n_na    180                 name_sz = READ_ONCE(nhdr->n_namesz);
181                 desc_sz = READ_ONCE(nhdr->n_de    181                 desc_sz = READ_ONCE(nhdr->n_descsz);
182                                                   182 
183                 new_off = note_off + sizeof(El    183                 new_off = note_off + sizeof(Elf32_Nhdr);
184                 if (check_add_overflow(new_off    184                 if (check_add_overflow(new_off, ALIGN(name_sz, 4), &new_off) ||
185                     check_add_overflow(new_off    185                     check_add_overflow(new_off, ALIGN(desc_sz, 4), &new_off) ||
186                     new_off > note_end)           186                     new_off > note_end)
187                         break;                    187                         break;
188                                                   188 
189                 if (nhdr->n_type == BUILD_ID &    189                 if (nhdr->n_type == BUILD_ID &&
190                     name_sz == note_name_sz &&    190                     name_sz == note_name_sz &&
191                     memcmp(nhdr + 1, note_name    191                     memcmp(nhdr + 1, note_name, note_name_sz) == 0 &&
192                     desc_sz > 0 && desc_sz <=     192                     desc_sz > 0 && desc_sz <= BUILD_ID_SIZE_MAX) {
193                         build_id_off = note_of    193                         build_id_off = note_off + sizeof(Elf32_Nhdr) + ALIGN(note_name_sz, 4);
194                                                   194 
195                         /* freader_fetch() wil    195                         /* freader_fetch() will invalidate nhdr pointer */
196                         data = freader_fetch(r    196                         data = freader_fetch(r, build_id_off, desc_sz);
197                         if (!data)                197                         if (!data)
198                                 return r->err;    198                                 return r->err;
199                                                   199 
200                         memcpy(build_id, data,    200                         memcpy(build_id, data, desc_sz);
201                         memset(build_id + desc    201                         memset(build_id + desc_sz, 0, BUILD_ID_SIZE_MAX - desc_sz);
202                         if (size)                 202                         if (size)
203                                 *size = desc_s    203                                 *size = desc_sz;
204                         return 0;                 204                         return 0;
205                 }                                 205                 }
206                                                   206 
207                 note_off = new_off;               207                 note_off = new_off;
208         }                                         208         }
209                                                   209 
210         return -EINVAL;                           210         return -EINVAL;
211 }                                                 211 }
212                                                   212 
213 /* Parse build ID from 32-bit ELF */              213 /* Parse build ID from 32-bit ELF */
214 static int get_build_id_32(struct freader *r,     214 static int get_build_id_32(struct freader *r, unsigned char *build_id, __u32 *size)
215 {                                                 215 {
216         const Elf32_Ehdr *ehdr;                   216         const Elf32_Ehdr *ehdr;
217         const Elf32_Phdr *phdr;                   217         const Elf32_Phdr *phdr;
218         __u32 phnum, phoff, i;                    218         __u32 phnum, phoff, i;
219                                                   219 
220         ehdr = freader_fetch(r, 0, sizeof(Elf3    220         ehdr = freader_fetch(r, 0, sizeof(Elf32_Ehdr));
221         if (!ehdr)                                221         if (!ehdr)
222                 return r->err;                    222                 return r->err;
223                                                   223 
224         /* subsequent freader_fetch() calls in    224         /* subsequent freader_fetch() calls invalidate pointers, so remember locally */
225         phnum = READ_ONCE(ehdr->e_phnum);         225         phnum = READ_ONCE(ehdr->e_phnum);
226         phoff = READ_ONCE(ehdr->e_phoff);         226         phoff = READ_ONCE(ehdr->e_phoff);
227                                                   227 
228         /* set upper bound on amount of segmen    228         /* set upper bound on amount of segments (phdrs) we iterate */
229         if (phnum > MAX_PHDR_CNT)                 229         if (phnum > MAX_PHDR_CNT)
230                 phnum = MAX_PHDR_CNT;             230                 phnum = MAX_PHDR_CNT;
231                                                   231 
232         /* check that phoff is not large enoug    232         /* check that phoff is not large enough to cause an overflow */
233         if (phoff + phnum * sizeof(Elf32_Phdr)    233         if (phoff + phnum * sizeof(Elf32_Phdr) < phoff)
234                 return -EINVAL;                   234                 return -EINVAL;
235                                                   235 
236         for (i = 0; i < phnum; ++i) {             236         for (i = 0; i < phnum; ++i) {
237                 phdr = freader_fetch(r, phoff     237                 phdr = freader_fetch(r, phoff + i * sizeof(Elf32_Phdr), sizeof(Elf32_Phdr));
238                 if (!phdr)                        238                 if (!phdr)
239                         return r->err;            239                         return r->err;
240                                                   240 
241                 if (phdr->p_type == PT_NOTE &&    241                 if (phdr->p_type == PT_NOTE &&
242                     !parse_build_id(r, build_i    242                     !parse_build_id(r, build_id, size, READ_ONCE(phdr->p_offset),
243                                     READ_ONCE(    243                                     READ_ONCE(phdr->p_filesz)))
244                         return 0;                 244                         return 0;
245         }                                         245         }
246         return -EINVAL;                           246         return -EINVAL;
247 }                                                 247 }
248                                                   248 
249 /* Parse build ID from 64-bit ELF */              249 /* Parse build ID from 64-bit ELF */
250 static int get_build_id_64(struct freader *r,     250 static int get_build_id_64(struct freader *r, unsigned char *build_id, __u32 *size)
251 {                                                 251 {
252         const Elf64_Ehdr *ehdr;                   252         const Elf64_Ehdr *ehdr;
253         const Elf64_Phdr *phdr;                   253         const Elf64_Phdr *phdr;
254         __u32 phnum, i;                           254         __u32 phnum, i;
255         __u64 phoff;                              255         __u64 phoff;
256                                                   256 
257         ehdr = freader_fetch(r, 0, sizeof(Elf6    257         ehdr = freader_fetch(r, 0, sizeof(Elf64_Ehdr));
258         if (!ehdr)                                258         if (!ehdr)
259                 return r->err;                    259                 return r->err;
260                                                   260 
261         /* subsequent freader_fetch() calls in    261         /* subsequent freader_fetch() calls invalidate pointers, so remember locally */
262         phnum = READ_ONCE(ehdr->e_phnum);         262         phnum = READ_ONCE(ehdr->e_phnum);
263         phoff = READ_ONCE(ehdr->e_phoff);         263         phoff = READ_ONCE(ehdr->e_phoff);
264                                                   264 
265         /* set upper bound on amount of segmen    265         /* set upper bound on amount of segments (phdrs) we iterate */
266         if (phnum > MAX_PHDR_CNT)                 266         if (phnum > MAX_PHDR_CNT)
267                 phnum = MAX_PHDR_CNT;             267                 phnum = MAX_PHDR_CNT;
268                                                   268 
269         /* check that phoff is not large enoug    269         /* check that phoff is not large enough to cause an overflow */
270         if (phoff + phnum * sizeof(Elf64_Phdr)    270         if (phoff + phnum * sizeof(Elf64_Phdr) < phoff)
271                 return -EINVAL;                   271                 return -EINVAL;
272                                                   272 
273         for (i = 0; i < phnum; ++i) {             273         for (i = 0; i < phnum; ++i) {
274                 phdr = freader_fetch(r, phoff     274                 phdr = freader_fetch(r, phoff + i * sizeof(Elf64_Phdr), sizeof(Elf64_Phdr));
275                 if (!phdr)                        275                 if (!phdr)
276                         return r->err;            276                         return r->err;
277                                                   277 
278                 if (phdr->p_type == PT_NOTE &&    278                 if (phdr->p_type == PT_NOTE &&
279                     !parse_build_id(r, build_i    279                     !parse_build_id(r, build_id, size, READ_ONCE(phdr->p_offset),
280                                     READ_ONCE(    280                                     READ_ONCE(phdr->p_filesz)))
281                         return 0;                 281                         return 0;
282         }                                         282         }
283                                                   283 
284         return -EINVAL;                           284         return -EINVAL;
285 }                                                 285 }
286                                                   286 
287 /* enough for Elf64_Ehdr, Elf64_Phdr, and all     287 /* enough for Elf64_Ehdr, Elf64_Phdr, and all the smaller requests */
288 #define MAX_FREADER_BUF_SZ 64                     288 #define MAX_FREADER_BUF_SZ 64
289                                                   289 
290 static int __build_id_parse(struct vm_area_str    290 static int __build_id_parse(struct vm_area_struct *vma, unsigned char *build_id,
291                             __u32 *size, bool     291                             __u32 *size, bool may_fault)
292 {                                                 292 {
293         const Elf32_Ehdr *ehdr;                   293         const Elf32_Ehdr *ehdr;
294         struct freader r;                         294         struct freader r;
295         char buf[MAX_FREADER_BUF_SZ];             295         char buf[MAX_FREADER_BUF_SZ];
296         int ret;                                  296         int ret;
297                                                   297 
298         /* only works for page backed storage     298         /* only works for page backed storage  */
299         if (!vma->vm_file)                        299         if (!vma->vm_file)
300                 return -EINVAL;                   300                 return -EINVAL;
301                                                   301 
302         freader_init_from_file(&r, buf, sizeof    302         freader_init_from_file(&r, buf, sizeof(buf), vma->vm_file, may_fault);
303                                                   303 
304         /* fetch first 18 bytes of ELF header     304         /* fetch first 18 bytes of ELF header for checks */
305         ehdr = freader_fetch(&r, 0, offsetofen    305         ehdr = freader_fetch(&r, 0, offsetofend(Elf32_Ehdr, e_type));
306         if (!ehdr) {                              306         if (!ehdr) {
307                 ret = r.err;                      307                 ret = r.err;
308                 goto out;                         308                 goto out;
309         }                                         309         }
310                                                   310 
311         ret = -EINVAL;                            311         ret = -EINVAL;
312                                                   312 
313         /* compare magic x7f "ELF" */             313         /* compare magic x7f "ELF" */
314         if (memcmp(ehdr->e_ident, ELFMAG, SELF    314         if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0)
315                 goto out;                         315                 goto out;
316                                                   316 
317         /* only support executable file and sh    317         /* only support executable file and shared object file */
318         if (ehdr->e_type != ET_EXEC && ehdr->e    318         if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
319                 goto out;                         319                 goto out;
320                                                   320 
321         if (ehdr->e_ident[EI_CLASS] == ELFCLAS    321         if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
322                 ret = get_build_id_32(&r, buil    322                 ret = get_build_id_32(&r, build_id, size);
323         else if (ehdr->e_ident[EI_CLASS] == EL    323         else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
324                 ret = get_build_id_64(&r, buil    324                 ret = get_build_id_64(&r, build_id, size);
325 out:                                              325 out:
326         freader_cleanup(&r);                      326         freader_cleanup(&r);
327         return ret;                               327         return ret;
328 }                                                 328 }
329                                                   329 
330 /*                                                330 /*
331  * Parse build ID of ELF file mapped to vma       331  * Parse build ID of ELF file mapped to vma
332  * @vma:      vma object                          332  * @vma:      vma object
333  * @build_id: buffer to store build id, at lea    333  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
334  * @size:     returns actual build id size in     334  * @size:     returns actual build id size in case of success
335  *                                                335  *
336  * Assumes no page fault can be taken, so if r    336  * Assumes no page fault can be taken, so if relevant portions of ELF file are
337  * not already paged in, fetching of build ID     337  * not already paged in, fetching of build ID fails.
338  *                                                338  *
339  * Return: 0 on success; negative error, other    339  * Return: 0 on success; negative error, otherwise
340  */                                               340  */
341 int build_id_parse_nofault(struct vm_area_stru    341 int build_id_parse_nofault(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
342 {                                                 342 {
343         return __build_id_parse(vma, build_id,    343         return __build_id_parse(vma, build_id, size, false /* !may_fault */);
344 }                                                 344 }
345                                                   345 
346 /*                                                346 /*
347  * Parse build ID of ELF file mapped to VMA       347  * Parse build ID of ELF file mapped to VMA
348  * @vma:      vma object                          348  * @vma:      vma object
349  * @build_id: buffer to store build id, at lea    349  * @build_id: buffer to store build id, at least BUILD_ID_SIZE long
350  * @size:     returns actual build id size in     350  * @size:     returns actual build id size in case of success
351  *                                                351  *
352  * Assumes faultable context and can cause pag    352  * Assumes faultable context and can cause page faults to bring in file data
353  * into page cache.                               353  * into page cache.
354  *                                                354  *
355  * Return: 0 on success; negative error, other    355  * Return: 0 on success; negative error, otherwise
356  */                                               356  */
357 int build_id_parse(struct vm_area_struct *vma,    357 int build_id_parse(struct vm_area_struct *vma, unsigned char *build_id, __u32 *size)
358 {                                                 358 {
359         return __build_id_parse(vma, build_id,    359         return __build_id_parse(vma, build_id, size, true /* may_fault */);
360 }                                                 360 }
361                                                   361 
362 /**                                               362 /**
363  * build_id_parse_buf - Get build ID from a bu    363  * build_id_parse_buf - Get build ID from a buffer
364  * @buf:      ELF note section(s) to parse        364  * @buf:      ELF note section(s) to parse
365  * @buf_size: Size of @buf in bytes               365  * @buf_size: Size of @buf in bytes
366  * @build_id: Build ID parsed from @buf, at le    366  * @build_id: Build ID parsed from @buf, at least BUILD_ID_SIZE_MAX long
367  *                                                367  *
368  * Return: 0 on success, -EINVAL otherwise        368  * Return: 0 on success, -EINVAL otherwise
369  */                                               369  */
370 int build_id_parse_buf(const void *buf, unsign    370 int build_id_parse_buf(const void *buf, unsigned char *build_id, u32 buf_size)
371 {                                                 371 {
372         struct freader r;                         372         struct freader r;
373         int err;                                  373         int err;
374                                                   374 
375         freader_init_from_mem(&r, buf, buf_siz    375         freader_init_from_mem(&r, buf, buf_size);
376                                                   376 
377         err = parse_build_id(&r, build_id, NUL    377         err = parse_build_id(&r, build_id, NULL, 0, buf_size);
378                                                   378 
379         freader_cleanup(&r);                      379         freader_cleanup(&r);
380         return err;                               380         return err;
381 }                                                 381 }
382                                                   382 
383 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) ||     383 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID) || IS_ENABLED(CONFIG_VMCORE_INFO)
384 unsigned char vmlinux_build_id[BUILD_ID_SIZE_M    384 unsigned char vmlinux_build_id[BUILD_ID_SIZE_MAX] __ro_after_init;
385                                                   385 
386 /**                                               386 /**
387  * init_vmlinux_build_id - Compute and stash t    387  * init_vmlinux_build_id - Compute and stash the running kernel's build ID
388  */                                               388  */
389 void __init init_vmlinux_build_id(void)           389 void __init init_vmlinux_build_id(void)
390 {                                                 390 {
391         extern const void __start_notes;          391         extern const void __start_notes;
392         extern const void __stop_notes;           392         extern const void __stop_notes;
393         unsigned int size = &__stop_notes - &_    393         unsigned int size = &__stop_notes - &__start_notes;
394                                                   394 
395         build_id_parse_buf(&__start_notes, vml    395         build_id_parse_buf(&__start_notes, vmlinux_build_id, size);
396 }                                                 396 }
397 #endif                                            397 #endif
398                                                   398 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php