14e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Copyright (c) 2012 The Chromium Authors. All rights reserved.
24e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Use of this source code is governed by a BSD-style license that can be
34e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// found in the LICENSE file.
44e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
54e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#ifndef BASE_POSIX_GLOBAL_DESCRIPTORS_H_
64e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#define BASE_POSIX_GLOBAL_DESCRIPTORS_H_
74e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
84e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "build/build_config.h"
94e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
104e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include <vector>
114e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include <utility>
124e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
134e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include <stdint.h>
144e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
154e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "base/files/memory_mapped_file.h"
164e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#include "base/memory/singleton.h"
174e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
184e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusnamespace base {
194e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
204e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// It's common practice to install file descriptors into well known slot
214e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// numbers before execing a child; stdin, stdout and stderr are ubiqutous
224e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// examples.
234e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius//
244e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// However, when using a zygote model, this becomes troublesome. Since the
254e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// descriptors which need to be in these slots generally aren't known, any code
264e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// could open a resource and take one of the reserved descriptors. Simply
274e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// overwriting the slot isn't a viable solution.
284e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius//
294e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// We could try to fill the reserved slots as soon as possible, but this is a
304e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// fragile solution since global constructors etc are able to open files.
314e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius//
324e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// Instead, we retreat from the idea of installing descriptors in specific
334e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// slots and add a layer of indirection in the form of this singleton object.
344e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// It maps from an abstract key to a descriptor. If independent modules each
354e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// need to define keys, then values should be chosen randomly so as not to
364e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius// collide.
374e2ea8184cc1f9609f1f1251394316629a108a78Roshan Piusclass BASE_EXPORT GlobalDescriptors {
384e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius public:
394e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  typedef uint32_t Key;
404e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  struct Descriptor {
414e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    Descriptor(Key key, int fd);
424e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    Descriptor(Key key, int fd, base::MemoryMappedFile::Region region);
434e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
444e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    // Globally unique key.
454e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    Key key;
464e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    // Actual FD.
474e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    int fd;
484e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    // Optional region, defaults to kWholeFile.
494e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius    base::MemoryMappedFile::Region region;
504e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  };
514e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  typedef std::vector<Descriptor> Mapping;
524e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
534e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Often we want a canonical descriptor for a given Key. In this case, we add
544e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // the following constant to the key value:
554e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#if !defined(OS_ANDROID)
564e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  static const int kBaseDescriptor = 3;  // 0, 1, 2 are already taken.
574e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#else
584e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  static const int kBaseDescriptor = 4;  // 3 used by __android_log_write().
594e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius#endif
604e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
614e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Return the singleton instance of GlobalDescriptors.
624e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  static GlobalDescriptors* GetInstance();
634e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
644e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Get a descriptor given a key. It is a fatal error if the key is not known.
654e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int Get(Key key) const;
664e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
674e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Get a descriptor given a key. Returns -1 on error.
684e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  int MaybeGet(Key key) const;
694e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
704e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Get a region given a key. It is a fatal error if the key is not known.
714e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  base::MemoryMappedFile::Region GetRegion(Key key) const;
724e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
734e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Set the descriptor for the given |key|. This sets the region associated
744e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // with |key| to kWholeFile.
754e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  void Set(Key key, int fd);
764e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
774e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  // Set the descriptor and |region| for the given |key|.
784e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  void Set(Key key, int fd, base::MemoryMappedFile::Region region);
794e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
804e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  void Reset(const Mapping& mapping);
814e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius
824e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius private:
834e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  friend struct DefaultSingletonTraits<GlobalDescriptors>;
844e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  GlobalDescriptors();
854e2ea8184cc1f9609f1f1251394316629a108a78Roshan Pius  ~GlobalDescriptors();
86
87  Mapping descriptors_;
88};
89
90}  // namespace base
91
92#endif  // BASE_POSIX_GLOBAL_DESCRIPTORS_H_
93