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 
19 namespace 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
42 class 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