summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp/library.h
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/linux/seccomp/library.h')
-rw-r--r--sandbox/linux/seccomp/library.h199
1 files changed, 199 insertions, 0 deletions
diff --git a/sandbox/linux/seccomp/library.h b/sandbox/linux/seccomp/library.h
new file mode 100644
index 0000000..e27bfde
--- /dev/null
+++ b/sandbox/linux/seccomp/library.h
@@ -0,0 +1,199 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef LIBRARY_H__
+#define LIBRARY_H__
+
+#include <elf.h>
+#include <functional>
+#include <map>
+#include <set>
+#include <string>
+#include <string.h>
+#include <sys/mman.h>
+
+#include "maps.h"
+
+#if defined(__x86_64__)
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Sym Elf_Sym;
+typedef Elf64_Addr Elf_Addr;
+#elif defined(__i386__)
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Addr Elf_Addr;
+#else
+#error Unsupported target platform
+#endif
+
+struct SyscallTable;
+namespace playground {
+
+class Library {
+ friend class Maps;
+ public:
+ typedef Maps::string string;
+
+ Library() :
+ valid_(false),
+ isVDSO_(false),
+ asr_offset_(0),
+ vsys_offset_(0),
+ maps_(0),
+ image_(0),
+ image_size_(0) {
+ }
+
+ ~Library();
+
+ void setLibraryInfo(Maps* maps) {
+ if (!maps_) {
+ maps_ = maps;
+ }
+ }
+
+ void addMemoryRange(void* start, void* stop, Elf_Addr offset,
+ int prot, int isVDSO) {
+ isVDSO_ = isVDSO;
+ RangeMap::const_iterator iter = memory_ranges_.find(offset);
+ if (iter != memory_ranges_.end()) {
+ // It is possible to have overlapping mappings. This is particularly
+ // likely to happen with very small programs or libraries. If it does
+ // happen, we really only care about the text segment. Look for a
+ // mapping that is mapped executable.
+ if ((prot & PROT_EXEC) == 0) {
+ return;
+ }
+ }
+ memory_ranges_.insert(std::make_pair(offset, Range(start, stop, prot)));
+ }
+
+ char *get(Elf_Addr offset, char *buf, size_t len);
+ string get(Elf_Addr offset);
+ char *getOriginal(Elf_Addr offset, char *buf, size_t len);
+ string getOriginal(Elf_Addr offset);
+
+ template<class T>T* get(Elf_Addr offset, T* t) {
+ if (!valid_) {
+ memset(t, 0, sizeof(T));
+ return NULL;
+ }
+ return reinterpret_cast<T *>(get(offset, reinterpret_cast<char *>(t),
+ sizeof(T)));
+ }
+
+ template<class T>T* getOriginal(Elf_Addr offset, T* t) {
+ if (!valid_) {
+ memset(t, 0, sizeof(T));
+ return NULL;
+ }
+ return reinterpret_cast<T *>(getOriginal(offset,
+ reinterpret_cast<char *>(t),
+ sizeof(T)));
+ }
+
+ template<class T>bool set(void *addr, T* value) {
+ if (!valid_) {
+ return false;
+ }
+ *reinterpret_cast<T *>(addr) = *value;
+ return true;
+ }
+
+ template<class T>bool set(Elf_Addr offset, T* value) {
+ if (!valid_) {
+ return false;
+ }
+ RangeMap::const_iterator iter = memory_ranges_.lower_bound(offset);
+ if (iter == memory_ranges_.end()) {
+ return false;
+ }
+ offset -= iter->first;
+ if (offset >
+ reinterpret_cast<char *>(iter->second.stop) -
+ reinterpret_cast<char *>(iter->second.start) -
+ sizeof(T)) {
+ return false;
+ }
+ *reinterpret_cast<T *>(
+ reinterpret_cast<char *>(iter->second.start) + offset) = *value;
+ return true;
+ }
+
+ bool parseElf();
+ const Elf_Ehdr* getEhdr();
+ const Elf_Shdr* getSection(const string& section);
+ int getSectionIndex(const string& section);
+ void makeWritable(bool state) const;
+ void patchSystemCalls();
+ bool isVDSO() const { return isVDSO_; }
+
+ protected:
+ bool parseSymbols();
+
+ private:
+ class GreaterThan : public std::binary_function<Elf_Addr, Elf_Addr, bool> {
+ // We create the RangeMap with a GreaterThan rather than the default
+ // comparator, as that allows us to use lower_bound() to find memory
+ // mappings.
+ public:
+ bool operator() (Elf_Addr s1, Elf_Addr s2) const {
+ return s1 > s2;
+ }
+ };
+
+ struct Range {
+ Range(void* start, void* stop, int prot) :
+ start(start), stop(stop), prot(prot) { }
+ void* start;
+ void* stop;
+ int prot;
+ };
+
+ typedef std::map<Elf_Addr, Range, GreaterThan,
+ SystemAllocator<std::pair<const Elf_Addr,
+ Range> > > RangeMap;
+ typedef std::map<string, std::pair<int, Elf_Shdr>, std::less<string>,
+ SystemAllocator<std::pair<const string,
+ std::pair<int, Elf_Shdr> > > >
+ SectionTable;
+ typedef std::map<string, Elf_Sym, std::less<string>,
+ SystemAllocator<std::pair<const string,
+ Elf_Sym> > > SymbolTable;
+ typedef std::map<string, Elf_Addr, std::less<string>,
+ SystemAllocator<std::pair<const string,
+ Elf_Addr> > > PltTable;
+
+ char* getBytes(char* dst, const char* src, ssize_t len);
+ static bool isSafeInsn(unsigned short insn);
+ static int isSimpleSystemCall(char *start, char *end);
+ static char* getScratchSpace(const Maps* maps, char* near, int needed,
+ char** extraSpace, int* extraLength);
+ void patchSystemCallsInFunction(const Maps* maps, char *start, char *end,
+ char** extraSpace, int* extraLength);
+ int patchVSystemCalls();
+ void patchVDSO(char** extraSpace, int* extraLength);
+
+ RangeMap memory_ranges_;
+ bool valid_;
+ bool isVDSO_;
+ char* asr_offset_;
+ int vsys_offset_;
+ Maps* maps_;
+ Elf_Ehdr ehdr_;
+ SectionTable section_table_;
+ SymbolTable symbols_;
+ PltTable plt_entries_;
+ char* image_;
+ size_t image_size_;
+ static char* __kernel_vsyscall;
+ static char* __kernel_sigreturn;
+ static char* __kernel_rt_sigreturn;
+};
+
+} // namespace
+
+#endif // LIBRARY_H__