Branch data Line data Source code
1 : : /* Get note information at the supplied offset. 2 : : Copyright (C) 2007, 2014, 2015, 2018 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <assert.h> 34 : : #include <gelf.h> 35 : : #include <string.h> 36 : : 37 : : #include "libelfP.h" 38 : : 39 : : size_t 40 : 12118 : gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result, 41 : : size_t *name_offset, size_t *desc_offset) 42 : : { 43 [ - + ]: 12118 : if (data == NULL) 44 : : return 0; 45 : : 46 [ - + ]: 12118 : if (unlikely (data->d_type != ELF_T_NHDR && data->d_type != ELF_T_NHDR8)) 47 : : { 48 : 0 : __libelf_seterrno (ELF_E_INVALID_HANDLE); 49 : 0 : return 0; 50 : : } 51 : : 52 : : /* It's easy to handle this type. It has the same size for 32 and 53 : : 64 bit objects. */ 54 : 12118 : assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr)); 55 : 12118 : assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr)); 56 : : 57 : 12118 : rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock); 58 : : 59 : : /* The data is already in the correct form. Just make sure the 60 : : offset is OK. */ 61 [ + - + + ]: 12118 : if (unlikely (offset > data->d_size 62 : : || data->d_size - offset < sizeof (GElf_Nhdr))) 63 : : { 64 : 1108 : __libelf_seterrno (ELF_E_OFFSET_RANGE); 65 : 1108 : offset = 0; 66 : : } 67 : : else 68 : : { 69 : 11010 : const GElf_Nhdr *n = data->d_buf + offset; 70 : 11010 : offset += sizeof *n; 71 : : 72 [ + + ]: 11010 : if (offset > data->d_size) 73 : : offset = 0; 74 : : else 75 : : { 76 : : /* This is slightly tricky, offset is guaranteed to be 4 77 : : byte aligned, which is what we need for the name_offset. 78 : : And normally desc_offset is also 4 byte aligned, but not 79 : : for GNU Property notes, then it should be 8. So align 80 : : the offset, after adding the namesz, and include padding 81 : : in descsz to get to the end. */ 82 : 11009 : *name_offset = offset; 83 [ - + ]: 11009 : if (n->n_namesz > data->d_size 84 [ # + ]: 11009 : || offset > data->d_size - n->n_namesz) 85 : : offset = 0; 86 : : else 87 : : { 88 : 11010 : offset += n->n_namesz; 89 : : /* Include padding. Check below for overflow. */ 90 [ + + ]: 11010 : GElf_Word descsz = (data->d_type == ELF_T_NHDR8 91 : 782 : ? NOTE_ALIGN8 (n->n_descsz) 92 : 10228 : : NOTE_ALIGN4 (n->n_descsz)); 93 : : 94 [ + + ]: 11010 : if (data->d_type == ELF_T_NHDR8) 95 : 782 : offset = NOTE_ALIGN8 (offset); 96 : : else 97 : 10228 : offset = NOTE_ALIGN4 (offset); 98 : : 99 [ - + - + : 11010 : if (unlikely (offset > data->d_size + + - + ] 100 : : || data->d_size - offset < descsz 101 : : || (descsz == 0 && n->n_descsz != 0))) 102 : : offset = 0; 103 : : else 104 : : { 105 : 11010 : *desc_offset = offset; 106 : 11010 : offset += descsz; 107 : 11010 : *result = *n; 108 : : } 109 : : } 110 : : } 111 : : } 112 : : 113 : 12117 : rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock); 114 : : 115 : 12117 : return offset; 116 : : }