It is my understanding that this patch enhances OSv only as far as 
supporting programs using non-fPIC shared libraries. It in no way affects 
or changes how OSv handles loading and execution of executables themselves 
(ELF with symbol main). 

I guess you are referring to so called non-pie executables that OSv does 
not support. I believe there are at least 2 open issues related to this:

   - https://github.com/cloudius-systems/osv/issues/190
   - https://github.com/cloudius-systems/osv/issues/212
   
I am not sure how relevant they are because the main driving force behind 
them was Golang support. Given that modern Golang supports generation of 
shared libraries and OSv supports running Golang as of release 0.51.0, the 
need to execute non-pies is also less and less important.

BTW I have noticed that on my latest Ubuntu 18.10 distribution programs 
like 'ls' and 'grep' seems to be pies as well.

file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically 
linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, 
BuildID[sha1]=e9c4234db3592c18920f9e0eb2d49eecf0fa5e4c, not stripped

file /bin/ls
/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), 
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 
3.2.0, BuildID[sha1]=bf40cb84e7815de09fa792a097061886933e56fa, stripped

When I tried to run unmodified '/bin/ls' on OSv I got this error:

/ls: failed looking up symbol __progname in other objects

[backtrace]
0x000000000034c26b <elf::object::symbol_other(unsigned int)+315>
0x000000000039f3e0 <elf::object::arch_relocate_rela(unsigned int, unsigned 
int, void*, long)+224>
0x000000000034a5e4 <elf::object::relocate_rela()+148>
0x000000000034d1d7 <elf::object::relocate()+199>
0x0000000000350adc 
<elf::program::load_object(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > >, 
std::vector<std::shared_ptr<elf::object>, 
std::allocator<std::shared_ptr<elf::object> > >&)+1452>
0x0000000000351330 
<elf::program::get_library(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > >, bool)+336>
0x000000000042b73b 
<osv::application::application(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > > const&, bool, 
std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > >, 
std::allocator<std::pair<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const, 
std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > > > > const*, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::function<0x000000000042bfbc 
<osv::application::run(std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, 
std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > > const&, bool, 
std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > >, 
std::allocator<std::pair<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const, 
std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > > > > const*, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&, std::function<void 
()>0x000000000042c22b 
<osv::application::run(std::vector<std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, 
std::allocator<char> > > > const&)+91>
0x0000000000219e06 <do_main_thread(void*)+1942>
0x0000000000459fb5 <???+4562869>
0x00000000003f9186 <thread_main_c+38>
0x000000000039b172 <???+3780978>

So I wonder how close OSv is to be able to run unmodified Linux executables 
like ls and grep as long as they are PIEs. 

Waldek

On Thursday, October 25, 2018 at 8:22:11 PM UTC-4, Qixuan Wu wrote:
>
> Good news, can we support NON-fPIC elf executable binary ? 
>
> 在 2018年10月25日星期四 UTC+8上午6:10:09,Waldek Kozaczuk写道:
>>
>> This patch enhances ELF dynamic loader to support position 
>> dependent shared libraries. It does it by detecting presence 
>> of DT_TEXTREL marker and temporarilily making PT_LOAD sections 
>> writable so that corresponding references in code get updated 
>> to point to correct addresses in memory. Eventually it fixes 
>> permissions of PT_LOAD sections to make it non-writable. 
>>
>> This patch most notably allows to run GraalVM generated 
>> Java apps. 
>>
>> Fixes #1004 
>>
>> Signed-off-by: Waldemar Kozaczuk <[email protected]> 
>> --- 
>>  core/elf.cc            | 47 +++++++++++++++++++++++++++++++++++------- 
>>  include/osv/elf.hh     |  5 ++++- 
>>  modules/tests/Makefile |  9 +++++++- 
>>  tests/misc-non-fpic.cc | 13 ++++++++++++ 
>>  tests/tst-run.cc       |  3 +++ 
>>  5 files changed, 68 insertions(+), 9 deletions(-) 
>>  create mode 100644 tests/misc-non-fpic.cc 
>>
>> diff --git a/core/elf.cc b/core/elf.cc 
>> index b0e3c1aa..c0dfbbb9 100644 
>> --- a/core/elf.cc 
>> +++ b/core/elf.cc 
>> @@ -325,13 +325,7 @@ void file::load_segment(const Elf64_Phdr& phdr) 
>>      ulong filesz = align_up(filesz_unaligned, mmu::page_size); 
>>      ulong memsz = align_up(phdr.p_vaddr + phdr.p_memsz, mmu::page_size) 
>> - vstart; 
>>   
>> -    unsigned perm = 0; 
>> -    if (phdr.p_flags & PF_X) 
>> -        perm |= mmu::perm_exec; 
>> -    if (phdr.p_flags & PF_W) 
>> -        perm |= mmu::perm_write; 
>> -    if (phdr.p_flags & PF_R) 
>> -        perm |= mmu::perm_read; 
>> +    unsigned perm = get_segment_mmap_permissions(phdr); 
>>   
>>      auto flag = mmu::mmap_fixed | (mlocked() ? mmu::mmap_populate : 0); 
>>      mmu::map_file(_base + vstart, filesz, flag, perm, _f, 
>> align_down(phdr.p_offset, mmu::page_size)); 
>> @@ -354,6 +348,11 @@ bool object::mlocked() 
>>      return false; 
>>  } 
>>   
>> +bool object::has_non_writable_text_relocations() 
>> +{ 
>> +    return dynamic_exists(DT_TEXTREL); 
>> +} 
>> + 
>>  Elf64_Note::Elf64_Note(void *_base, char *str) 
>>  { 
>>      Elf64_Word *base = reinterpret_cast<Elf64_Word *>(_base); 
>> @@ -468,8 +467,24 @@ void object::unload_segments() 
>>       } 
>>  } 
>>   
>> +unsigned object::get_segment_mmap_permissions(const Elf64_Phdr& phdr) 
>> +{ 
>> +    unsigned perm = 0; 
>> +    if (phdr.p_flags & PF_X) 
>> +        perm |= mmu::perm_exec; 
>> +    if (phdr.p_flags & PF_W) 
>> +        perm |= mmu::perm_write; 
>> +    if (phdr.p_flags & PF_R) 
>> +        perm |= mmu::perm_read; 
>> +    return perm; 
>> +} 
>> + 
>>  void object::fix_permissions() 
>>  { 
>> +    if(has_non_writable_text_relocations()) { 
>> +        make_text_writable(false); 
>> +    } 
>> + 
>>      for (auto&& phdr : _phdrs) { 
>>          if (phdr.p_type != PT_GNU_RELRO) 
>>              continue; 
>> @@ -482,6 +497,20 @@ void object::fix_permissions() 
>>      } 
>>  } 
>>   
>> +void object::make_text_writable(bool flag) 
>> +{ 
>> +    for (auto&& phdr : _phdrs) { 
>> +        if (phdr.p_type != PT_LOAD) 
>> +            continue; 
>> + 
>> +        ulong vstart = align_down(phdr.p_vaddr, mmu::page_size); 
>> +        ulong memsz = align_up(phdr.p_vaddr + phdr.p_memsz, 
>> mmu::page_size) - vstart; 
>> + 
>> +        unsigned perm = get_segment_mmap_permissions(phdr); 
>> +        mmu::mprotect(_base + vstart, memsz, flag ? perm | 
>> mmu::perm_write : perm); 
>> +    } 
>> +} 
>> + 
>>  template <typename T> 
>>  T* object::dynamic_ptr(unsigned tag) 
>>  { 
>> @@ -600,6 +629,10 @@ symbol_module object::symbol_other(unsigned idx) 
>>   
>>  void object::relocate_rela() 
>>  { 
>> +    if(has_non_writable_text_relocations()) { 
>> +        make_text_writable(true); 
>> +    } 
>> + 
>>      auto rela = dynamic_ptr<Elf64_Rela>(DT_RELA); 
>>      assert(dynamic_val(DT_RELAENT) == sizeof(Elf64_Rela)); 
>>      unsigned nb = dynamic_val(DT_RELASZ) / sizeof(Elf64_Rela); 
>> diff --git a/include/osv/elf.hh b/include/osv/elf.hh 
>> index 5449f98f..19b24eec 100644 
>> --- a/include/osv/elf.hh 
>> +++ b/include/osv/elf.hh 
>> @@ -177,7 +177,7 @@ enum { 
>>      DT_PLTREL = 20, // d_val Type of relocation entry used for the 
>> procedure linkage 
>>        // table. The d_val member contains either DT_REL or DT_RELA. 
>>      DT_DEBUG = 21, // d_ptr Reserved for debugger use. 
>> -    DT_TEXTREL = 22, // ignored The presence of this dynamic table entry 
>> signals that the 
>> +    DT_TEXTREL = 22, // The presence of this dynamic table entry signals 
>> that the 
>>        // relocation table contains relocations for a non-writable 
>>        // segment. 
>>      DT_JMPREL = 23, // d_ptr Address of the relocations associated with 
>> the procedure 
>> @@ -367,6 +367,8 @@ protected: 
>>      virtual void unload_segment(const Elf64_Phdr& segment) = 0; 
>>      virtual void read(Elf64_Off offset, void* data, size_t len) = 0; 
>>      bool mlocked(); 
>> +    bool has_non_writable_text_relocations(); 
>> +    unsigned get_segment_mmap_permissions(const Elf64_Phdr& phdr); 
>>  private: 
>>      Elf64_Sym* lookup_symbol_old(const char* name); 
>>      Elf64_Sym* lookup_symbol_gnu(const char* name); 
>> @@ -388,6 +390,7 @@ private: 
>>      void collect_dependencies(std::unordered_set<elf::object*>& ds); 
>>      void prepare_initial_tls(void* buffer, size_t size, 
>> std::vector<ptrdiff_t>& offsets); 
>>      void alloc_static_tls(); 
>> +    void make_text_writable(bool flag); 
>>  protected: 
>>      program& _prog; 
>>      std::string _pathname; 
>> diff --git a/modules/tests/Makefile b/modules/tests/Makefile 
>> index cec4febe..0fed7a3b 100644 
>> --- a/modules/tests/Makefile 
>> +++ b/modules/tests/Makefile 
>> @@ -60,6 +60,13 @@ $(out)/tests/rofs/%.o: $(src)/tests/%.c 
>>  $(out)/%.so: $(out)/%.o 
>>          $(call quiet, $(CXX) $(CXXFLAGS) -shared -o $@ $< $(LIBS), LD 
>> $*.so) 
>>   
>> +NON_FPIC_CXXFLAGS = $(autodepend) $(INCLUDES) -g -O2 -mcmodel=large 
>> -fno-pie -DBOOST_TEST_DYN_LINK \ 
>> +        -U _FORTIFY_SOURCE -D_KERNEL -D__OSV__ -DCONF_debug_memory=0 \ 
>> +        -Wall -Wno-pointer-arith -Wformat=0 -Wno-format-security 
>> +$(out)/tests/misc-non-fpic.so: $(src)/tests/misc-non-fpic.cc 
>> +        $(makedir) 
>> +        $(call quiet, $(CXX) -shared $(NON_FPIC_CXXFLAGS) -o $@ $<, LD 
>> $*.so) 
>> + 
>>  # The rofs test image mounts /tmp as ramfs and 4 tests that exercise 
>> file system 
>>  # fail due to some unresolved bugs or other shortcomings of the ramfs 
>> implementation 
>>  # and are temporarily removed from the rofs-only-tests list. The tests 
>> tst-readdir.so 
>> @@ -93,7 +100,7 @@ tests := tst-pthread.so misc-ramdisk.so tst-vblk.so 
>> tst-bsd-evh.so \ 
>>          misc-tcp-sendonly.so tst-tcp-nbwrite.so misc-tcp-hash-srv.so \ 
>>          misc-loadbalance.so misc-scheduler.so tst-console.so tst-app.so 
>> \ 
>>          misc-setpriority.so misc-timeslice.so misc-tls.so misc-gtod.so \ 
>> -        tst-dns-resolver.so tst-kill.so tst-truncate.so \ 
>> +        tst-dns-resolver.so tst-kill.so tst-truncate.so misc-non-fpic.so 
>> \ 
>>          misc-panic.so tst-utimes.so tst-utimensat.so tst-futimesat.so \ 
>>          misc-tcp.so tst-strerror_r.so misc-random.so misc-urandom.so \ 
>>          tst-commands.so tst-threadcomplete.so tst-timerfd.so \ 
>> diff --git a/tests/misc-non-fpic.cc b/tests/misc-non-fpic.cc 
>> new file mode 100644 
>> index 00000000..77cf17a5 
>> --- /dev/null 
>> +++ b/tests/misc-non-fpic.cc 
>> @@ -0,0 +1,13 @@ 
>> +/* 
>> + * Copyright (C) 2018 Waldemar Kozaczuk 
>> + * 
>> + * This work is open source software, licensed under the terms of the 
>> + * BSD license as described in the LICENSE file in the top-level 
>> directory. 
>> + */ 
>> +#include <stdio.h> 
>> +#include <assert.h> 
>> + 
>> +int main() { 
>> +    printf("Hello\n"); 
>> +    assert(1); 
>> +} 
>> diff --git a/tests/tst-run.cc b/tests/tst-run.cc 
>> index 3f1139c3..2d3d6317 100644 
>> --- a/tests/tst-run.cc 
>> +++ b/tests/tst-run.cc 
>> @@ -48,6 +48,9 @@ int main(int ac, char** av) 
>>          report(true, "Run nonexistant"); 
>>      } 
>>   
>> +    b = (bool)osv::run("/tests/misc-non-fpic.so", 0, nullptr, nullptr); 
>> +    report(b == true, "Run non-PIC with non-writable relocations"); 
>> + 
>>      return 0; 
>>  } 
>>   
>> -- 
>> 2.17.1 
>>
>>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to