From 89757447dbcd0ac946db345fa6aa1edc76a37a11 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Sun, 11 Sep 2005 09:05:20 +0000 Subject: [PATCH] 2005-09-09 Roland McGrath * elf_update.c (write_file): Stat the file and fchmod it after update if its mode had S_ISUID or S_ISGID bits set. --- libelf/ChangeLog | 5 +++++ libelf/elf_update.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index bd710aeec..35667cee3 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,8 @@ +2005-09-09 Roland McGrath + + * elf_update.c (write_file): Stat the file and fchmod it after update + if its mode had S_ISUID or S_ISGID bits set. + 2005-08-28 Ulrich Drepper * elf32_getphdr.c: Include . Use pread_retry instead of diff --git a/libelf/elf_update.c b/libelf/elf_update.c index 5d6c6b7a1..f380e2b9d 100644 --- a/libelf/elf_update.c +++ b/libelf/elf_update.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "libelfP.h" @@ -31,6 +32,14 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum) { int class = elf->class; + /* Check the mode bits now, before modification might change them. */ + struct stat st; + if (unlikely (fstat (elf->fildes, &st) != 0)) + { + __libelf_seterrno (ELF_E_WRITE_ERROR); + return -1; + } + /* Adjust the size in any case. We do this even if we use `write'. We cannot do this if this file is in an archive. We also don't do it *now* if we are shortening the file since this would @@ -87,6 +96,18 @@ write_file (Elf *elf, off_t size, int change_bo, size_t shnum) size = -1; } + /* POSIX says that ftruncate and write may clear the S_ISUID and S_ISGID + mode bits. So make sure we restore them afterwards if they were set. + This is not atomic if someone else chmod's the file while we operate. */ + if (size != -1 + && unlikely (st.st_mode & (S_ISUID | S_ISGID)) + /* fchmod ignores the bits we cannot change. */ + && unlikely (fchmod (elf->fildes, st.st_mode) != 0)) + { + __libelf_seterrno (ELF_E_WRITE_ERROR); + size = -1; + } + if (size != -1 && elf->parent == NULL) elf->maximum_size = size; -- 2.47.2