1 /* Update data structures for changes and write them out. 2 Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006 Red Hat, Inc. 3 This file is part of elfutils. 4 Contributed by Ulrich Drepper <drepper (at) redhat.com>, 1999. 5 6 This file is free software; you can redistribute it and/or modify 7 it under the terms of either 8 9 * the GNU Lesser General Public License as published by the Free 10 Software Foundation; either version 3 of the License, or (at 11 your option) any later version 12 13 or 14 15 * the GNU General Public License as published by the Free 16 Software Foundation; either version 2 of the License, or (at 17 your option) any later version 18 19 or both in parallel, as here. 20 21 elfutils is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received copies of the GNU General Public License and 27 the GNU Lesser General Public License along with this program. If 28 not, see <http://www.gnu.org/licenses/>. */ 29 30 #ifdef HAVE_CONFIG_H 31 # include <config.h> 32 #endif 33 34 #include <libelf.h> 35 #include <unistd.h> 36 #include <sys/mman.h> 37 #include <sys/stat.h> 38 39 #include "libelfP.h" 40 41 42 static off_t 43 write_file (Elf *elf, off_t size, int change_bo, size_t shnum) 44 { 45 int class = elf->class; 46 47 /* Check the mode bits now, before modification might change them. */ 48 struct stat st; 49 if (unlikely (fstat (elf->fildes, &st) != 0)) 50 { 51 __libelf_seterrno (ELF_E_WRITE_ERROR); 52 return -1; 53 } 54 55 /* Adjust the size in any case. We do this even if we use `write'. 56 We cannot do this if this file is in an archive. We also don't 57 do it *now* if we are shortening the file since this would 58 prevent programs to use the data of the file in generating the 59 new file. We truncate the file later in this case. */ 60 if (elf->parent == NULL 61 && (elf->maximum_size == ~((size_t) 0) 62 || (size_t) size > elf->maximum_size) 63 && unlikely (ftruncate (elf->fildes, size) != 0)) 64 { 65 __libelf_seterrno (ELF_E_WRITE_ERROR); 66 return -1; 67 } 68 69 /* Try to map the file if this isn't done yet. */ 70 if (elf->map_address == NULL && elf->cmd == ELF_C_WRITE_MMAP) 71 { 72 elf->map_address = mmap (NULL, size, PROT_READ | PROT_WRITE, 73 MAP_SHARED, elf->fildes, 0); 74 if (unlikely (elf->map_address == MAP_FAILED)) 75 elf->map_address = NULL; 76 } 77 78 if (elf->map_address != NULL) 79 { 80 /* The file is mmaped. */ 81 if ((class == ELFCLASS32 82 ? __elf32_updatemmap (elf, change_bo, shnum) 83 : __elf64_updatemmap (elf, change_bo, shnum)) != 0) 84 /* Some problem while writing. */ 85 size = -1; 86 } 87 else 88 { 89 /* The file is not mmaped. */ 90 if ((class == ELFCLASS32 91 ? __elf32_updatefile (elf, change_bo, shnum) 92 : __elf64_updatefile (elf, change_bo, shnum)) != 0) 93 /* Some problem while writing. */ 94 size = -1; 95 } 96 97 if (size != -1 98 && elf->parent == NULL 99 && elf->maximum_size != ~((size_t) 0) 100 && (size_t) size < elf->maximum_size 101 && unlikely (ftruncate (elf->fildes, size) != 0)) 102 { 103 __libelf_seterrno (ELF_E_WRITE_ERROR); 104 size = -1; 105 } 106 107 /* POSIX says that ftruncate and write may clear the S_ISUID and S_ISGID 108 mode bits. So make sure we restore them afterwards if they were set. 109 This is not atomic if someone else chmod's the file while we operate. */ 110 if (size != -1 111 && unlikely (st.st_mode & (S_ISUID | S_ISGID)) 112 /* fchmod ignores the bits we cannot change. */ 113 && unlikely (fchmod (elf->fildes, st.st_mode) != 0)) 114 { 115 __libelf_seterrno (ELF_E_WRITE_ERROR); 116 size = -1; 117 } 118 119 if (size != -1 && elf->parent == NULL) 120 elf->maximum_size = size; 121 122 return size; 123 } 124 125 126 off_t 127 elf_update (elf, cmd) 128 Elf *elf; 129 Elf_Cmd cmd; 130 { 131 size_t shnum; 132 off_t size; 133 int change_bo = 0; 134 135 if (cmd != ELF_C_NULL 136 && cmd != ELF_C_WRITE 137 && unlikely (cmd != ELF_C_WRITE_MMAP)) 138 { 139 __libelf_seterrno (ELF_E_INVALID_CMD); 140 return -1; 141 } 142 143 if (elf == NULL) 144 return -1; 145 146 if (elf->kind != ELF_K_ELF) 147 { 148 __libelf_seterrno (ELF_E_INVALID_HANDLE); 149 return -1; 150 } 151 152 rwlock_wrlock (elf->lock); 153 154 /* Make sure we have an ELF header. */ 155 if (elf->state.elf.ehdr == NULL) 156 { 157 __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); 158 size = -1; 159 goto out; 160 } 161 162 /* Determine the number of sections. */ 163 shnum = (elf->state.elf.scns_last->cnt == 0 164 ? 0 165 : 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt - 1].index); 166 167 /* Update the ELF descriptor. First, place the program header. It 168 will come right after the ELF header. The count the size of all 169 sections and finally place the section table. */ 170 size = (elf->class == ELFCLASS32 171 ? __elf32_updatenull_wrlock (elf, &change_bo, shnum) 172 : __elf64_updatenull_wrlock (elf, &change_bo, shnum)); 173 if (likely (size != -1) 174 /* See whether we actually have to write out the data. */ 175 && (cmd == ELF_C_WRITE || cmd == ELF_C_WRITE_MMAP)) 176 { 177 if (elf->cmd != ELF_C_RDWR 178 && elf->cmd != ELF_C_RDWR_MMAP 179 && elf->cmd != ELF_C_WRITE 180 && unlikely (elf->cmd != ELF_C_WRITE_MMAP)) 181 { 182 __libelf_seterrno (ELF_E_UPDATE_RO); 183 size = -1; 184 } 185 else if (unlikely (elf->fildes == -1)) 186 { 187 /* We closed the file already. */ 188 __libelf_seterrno (ELF_E_FD_DISABLED); 189 size = -1; 190 } 191 else 192 size = write_file (elf, size, change_bo, shnum); 193 } 194 195 out: 196 rwlock_unlock (elf->lock); 197 198 return size; 199 } 200