]> git.saurik.com Git - apple/securityd.git/blob - src/structure.h
securityd-40120.tar.gz
[apple/securityd.git] / src / structure.h
1 /*
2 * Copyright (c) 2000-2001,2008 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 //
26 // structure - structural framework for securityd objects
27 //
28 #ifndef _H_STRUCTURE
29 #define _H_STRUCTURE
30
31 #include <security_utilities/refcount.h>
32 #include <security_utilities/mach++.h>
33 #include <security_cdsa_utilities/u32handleobject.h>
34 #include <map>
35 #include "dtrace.h"
36
37 using MachPlusPlus::Port;
38
39
40 //
41 // Track a per-process real world object
42 //
43 template <class Base, class Glob> class Node;
44 class PerConnection;
45 class PerProcess;
46 class PerSession;
47 class PerGlobal;
48
49
50 //
51 // A generic core node of the object mesh.
52 // Repeat after me: "Everything that matters is a Node."
53 //
54 // This contains the mesh links (as smart pointers to NodeCores).
55 // The 'parent' is the next-more-global related object in the mesh, if any;
56 // nodes with the same parent "belong together" at the more global layer.
57 // For example, processes have their sessions as parents.
58 // The 'referent' is an object at the *same* globality layer that controls
59 // the lifetime of this node. For example, a Database has its Process as
60 // its referent.
61 // Both parent and referent are optional (can be NULL).
62 // The references set is a partial referent back-link. All NodeCores listed
63 // in a node's References have this node as a referent, but the set is
64 // selective (not necessarily complete). The References set propagates the
65 // 'kill' operation up the referents chain; thus being included in a node's
66 // References means that a kill() on the referent will (recursively) kill
67 // all references, too.
68 //
69 // Do not inherit directly from NodeCore; use Node<> (below).
70 //
71 class NodeCore : public RefCount, public Mutex {
72 template <class Base, class Glob> friend class Node;
73 public:
74 #if !defined(DEBUGDUMP) // (see below if DEBUGDUMP)
75 NodeCore() : Mutex(Mutex::recursive) { }
76 #endif
77 virtual ~NodeCore();
78
79 void addReference(NodeCore &p);
80 void removeReference(NodeCore &p);
81
82 // reference set operations
83 template <class Sub>
84 void allReferences(void (Sub::*func)());
85 template <class Sub, class Value>
86 RefPointer<Sub> findFirst(Value (Sub::*func)() const, Value compare);
87 void clearReferences();
88
89 virtual void kill(); // kill all references and self
90 virtual void kill(NodeCore &ref); // kill ref from my references()
91
92 // for STL ordering (so we can have sets of RefPointers of NodeCores)
93 bool operator < (const NodeCore &other) const
94 { return this < &other; }
95
96 protected:
97 void parent(NodeCore &p); // set parent
98 void referent(NodeCore &r); // set referent
99 void clearReferent(); // clear referent
100
101 bool hasParent() const { return mParent; }
102 bool hasReferent() const { return mReferent; }
103
104 private:
105 RefPointer<NodeCore> mParent;
106 RefPointer<NodeCore> mReferent;
107 typedef set<RefPointer<NodeCore> > ReferenceSet;
108 ReferenceSet mReferences;
109
110 IFDEBUG(bool hasReference(NodeCore &p));
111
112 #if defined(DEBUGDUMP)
113 public: // dump support
114 NodeCore(); // dump-only constructor (registers node)
115
116 virtual void dumpNode(); // node description (partial line)
117 virtual void dump(); // dumpNode() + references + NL
118 static void dumpAll(); // dump all nodes
119
120 static Mutex mCoreLock; // lock for mCoreNodes
121 static set<NodeCore *> mCoreNodes; // (debug) set of all known nodes
122 #endif //DEBUGDUMP
123 };
124
125
126 //
127 // Call a member on each reference of a Node<> object.
128 // The object lock is held throughout, and we keep a RefPointer to each object
129 // as it's being processed. Thus it's safe for a reference to self-unlink in
130 // the object mesh; it'll get destroyed after its method returns.
131 //
132 template <class Sub>
133 void NodeCore::allReferences(void (Sub::*func)())
134 {
135 StLock<Mutex> _(*this);
136 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end();)
137 if (RefPointer<Sub> sub = dynamic_cast<Sub *>((it++)->get()))
138 (sub->*func)();
139 }
140
141
142 //
143 // Find a reference of a Node<> object that satisfies a simple "method returns value"
144 // condition. There is no defined order of the scan, so if the condition is not unique,
145 // any one reference may be returned. If none are found, we return NULL.
146 // This returns a RefPointer: lifetime of the returned instance (if any) is ensured even
147 // if it is asynchronously removed from the references set.
148 //
149 template <class Sub, class Value>
150 RefPointer<Sub> NodeCore::findFirst(Value (Sub::*func)() const, Value compare)
151 {
152 StLock<Mutex> _(*this);
153 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++)
154 if (Sub *sub = dynamic_cast<Sub *>(it->get()))
155 if ((sub->*func)() == compare)
156 return sub;
157 return NULL;
158 }
159
160
161 //
162 // A typed node of the object mesh.
163 // This adds type-safe accessors and modifiers to NodeCore.
164 //
165 template <class Base, class Glob>
166 class Node : public NodeCore {
167 protected:
168 // type-safer versions of node mesh setters
169 void parent(Glob &p) { NodeCore::parent(p); }
170 void referent(Base &r) { NodeCore::referent(r); }
171
172 public:
173 template <class T>
174 T& parent() const
175 { assert(mParent); return safer_cast<T &>(*mParent); }
176
177 template <class T>
178 T& referent() const
179 { assert(mReferent); return safer_cast<T &>(*mReferent); }
180
181 public:
182 void addReference(Base &p) { NodeCore::addReference(p); }
183 void removeReference(Base &p) { NodeCore::removeReference(p); }
184 };
185
186
187 //
188 // Connection (client thread) layer nodes
189 //
190 class PerConnection : public Node<PerConnection, PerProcess> {
191 public:
192 };
193
194
195 //
196 // Process (client process) layer nodes
197 //
198 class PerProcess : public U32HandleObject, public Node<PerProcess, PerSession> {
199 public:
200 };
201
202
203 //
204 // Session (client-side session) layer nodes
205 //
206 class PerSession : public Node<PerSession, PerGlobal> {
207 public:
208 };
209
210
211 //
212 // Global (per-system) layer nodes
213 //
214 class PerGlobal : public Node<PerGlobal, PerGlobal> {
215 public:
216 };
217
218
219 //
220 // A map from mach port names to (refcounted) pointers-to-somethings
221 //
222 template <class Node>
223 class PortMap : public Mutex, public std::map<Port, RefPointer<Node> > {
224 typedef std::map<Port, RefPointer<Node> > _Map;
225 public:
226 bool contains(mach_port_t port) const { return this->find(port) != this->end(); }
227 Node *getOpt(mach_port_t port) const
228 {
229 typename _Map::const_iterator it = this->find(port);
230 return (it == this->end()) ? NULL : it->second;
231 }
232
233 Node *get(mach_port_t port) const
234 {
235 typename _Map::const_iterator it = this->find(port);
236 assert(it != this->end());
237 return it->second;
238 }
239
240 Node *get(mach_port_t port, OSStatus error) const
241 {
242 typename _Map::const_iterator it = this->find(port);
243 if (it == this->end())
244 MacOSError::throwMe(error);
245 return it->second;
246 }
247
248 void dump();
249 };
250
251 template <class Node>
252 void PortMap<Node>::dump()
253 {
254 for (typename _Map::const_iterator it = this->begin(); it != this->end(); it++)
255 it->second->dump();
256 }
257
258
259 #endif //_H_STRUCTURE