1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef BASE_POSIX_GLOBAL_DESCRIPTORS_H_
6#define BASE_POSIX_GLOBAL_DESCRIPTORS_H_
7
8#include "build/build_config.h"
9
10#include <vector>
11#include <utility>
12
13#include <stdint.h>
14
15#include "base/files/memory_mapped_file.h"
16#include "base/files/scoped_file.h"
17#include "base/memory/singleton.h"
18
19namespace base {
20
21// It's common practice to install file descriptors into well known slot
22// numbers before execing a child; stdin, stdout and stderr are ubiqutous
23// examples.
24//
25// However, when using a zygote model, this becomes troublesome. Since the
26// descriptors which need to be in these slots generally aren't known, any code
27// could open a resource and take one of the reserved descriptors. Simply
28// overwriting the slot isn't a viable solution.
29//
30// We could try to fill the reserved slots as soon as possible, but this is a
31// fragile solution since global constructors etc are able to open files.
32//
33// Instead, we retreat from the idea of installing descriptors in specific
34// slots and add a layer of indirection in the form of this singleton object.
35// It maps from an abstract key to a descriptor. If independent modules each
36// need to define keys, then values should be chosen randomly so as not to
37// collide.
38//
39// Note that this class is deprecated and passing file descriptor should ideally
40// be done through the command line and using FileDescriptorStore.
41// See https://crbugs.com/detail?id=692619
42class BASE_EXPORT GlobalDescriptors {
43 public:
44  typedef uint32_t Key;
45  struct Descriptor {
46    Descriptor(Key key, int fd);
47    Descriptor(Key key, int fd, base::MemoryMappedFile::Region region);
48
49    // Globally unique key.
50    Key key;
51    // Actual FD.
52    int fd;
53    // Optional region, defaults to kWholeFile.
54    base::MemoryMappedFile::Region region;
55  };
56  typedef std::vector<Descriptor> Mapping;
57
58  // Often we want a canonical descriptor for a given Key. In this case, we add
59  // the following constant to the key value:
60  static const int kBaseDescriptor = 3;  // 0, 1, 2 are already taken.
61
62  // Return the singleton instance of GlobalDescriptors.
63  static GlobalDescriptors* GetInstance();
64
65  // Get a descriptor given a key. It is a fatal error if the key is not known.
66  int Get(Key key) const;
67
68  // Get a descriptor given a key. Returns -1 on error.
69  int MaybeGet(Key key) const;
70
71  // Returns a descriptor given a key and removes it from this class mappings.
72  // Also populates |region|.
73  // It is a fatal error if the key is not known.
74  base::ScopedFD TakeFD(Key key, base::MemoryMappedFile::Region* region);
75
76  // Get a region given a key. It is a fatal error if the key is not known.
77  base::MemoryMappedFile::Region GetRegion(Key key) const;
78
79  // Set the descriptor for the given |key|. This sets the region associated
80  // with |key| to kWholeFile.
81  void Set(Key key, int fd);
82
83  // Set the descriptor and |region| for the given |key|.
84  void Set(Key key, int fd, base::MemoryMappedFile::Region region);
85
86  void Reset(const Mapping& mapping);
87
88 private:
89  friend struct DefaultSingletonTraits<GlobalDescriptors>;
90  GlobalDescriptors();
91  ~GlobalDescriptors();
92
93  Mapping descriptors_;
94};
95
96}  // namespace base
97
98#endif  // BASE_POSIX_GLOBAL_DESCRIPTORS_H_
99