Home | History | Annotate | Download | only in libelf
      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