1#!/usr/sbin/dtrace -q -s
2
3
4
5/*
6 * Tracking state
7 */
8typedef uint32_t DTPort;
9typedef uint64_t DTHandle;
10
11DTHandle portmap[DTPort];				/* map client reply ports to connections */
12
13struct connection {
14	DTPort replyport;		/* reply port for client thread */
15	uint32_t client;		/* client object for this connection */
16};
17struct connection connection[DTHandle];	/* indexed by connection handle */
18
19/* should be a single self struct, but that doesn't work right... */
20self string reqName;		/* request name */
21self DTHandle reqConnection; /* associated connection */
22self DTHandle reqClient;	/* associated client */
23
24struct client {
25	pid_t pid;				/* original client pid */
26	DTHandle session;		/* session handle */
27	string name;			/* abbreviated name */
28	string path;			/* path to client process (regardless of guests) */
29	DTPort  taskport;		/* process task port */
30};
31struct client client[DTHandle];			/* indexed by client handle */
32
33struct keychain {
34	string name;			/* keychain path */
35};
36struct keychain keychain[DTHandle];		/* indexed by DbCommon handle */
37
38
39/*
40 * Script management
41 */
42:::BEGIN
43{
44	/* fake data for unknown processes */
45	client[0].pid = 0;
46	client[0].session = 0;
47	client[0].name = "*UNKNOWN*";
48	client[0].path = "*UNKNOWN*";
49
50	printf("Ready...\n");
51}
52
53
54/*
55 * Translate thread id
56 */
57uint32_t threads[DTHandle];	/* map tids to simple thread numbers */
58uint32_t nextThread;		/* next unused thread number */
59self uint32_t mytid;		/* translated tid */
60
61securityd*::: /!threads[tid]/ { threads[tid] = ++nextThread; }
62security_debug*::: /!threads[tid]/ { threads[tid] = ++nextThread; }
63
64securityd*::: { self->mytid = threads[tid]; }
65security_debug*::: { self->mytid = threads[tid]; }
66
67
68/*
69 * Principal events
70 */
71securityd*:::installmode
72{
73	printf("%u SYSTEM INSTALLATION MODE SELECTED\n", timestamp);
74}
75
76securityd*:::initialized
77{
78	printf("%u COMMENCING SERVICE as %s\n", timestamp, copyinstr(arg0));
79}
80
81
82/*
83 * Client management
84 */
85securityd*:::client-connection-new
86{
87	replymap[arg1] = arg0;
88	self->reqClient = arg2;
89	connection[arg0].client = self->reqClient;
90	self->reqConnection = arg0;
91	@total["Connections"] = count();
92	printf("%u T%d:connection-new(<%x>,port=%d,client=<%x>/%s(%d))\n",
93		timestamp, self->mytid, arg0, arg1,
94		arg2, client[arg2].name, client[arg2].pid);
95}
96
97securityd*:::client-connection-release
98/connection[arg0].client/
99{
100	printf("%u T%d:connection-release(<%x>,client=<%x>/%s(%d))\n",
101		timestamp, self->mytid, arg0,
102		connection[arg0].client,
103		client[connection[arg0].client].name,
104		client[connection[arg0].client].pid);
105	replymap[connection[arg0].replyport] = 0;		/* clear from port map */
106	connection[arg0].replyport = 0;
107	connection[arg0].client = 0;
108}
109
110securityd*:::client-new
111{
112	client[arg0].pid = arg1;
113	client[arg0].session = arg2;
114    client[arg0].path = copyinstr(arg3);
115	client[arg0].name = basename(client[arg0].path);
116	client[arg0].taskport = arg4;
117	self->reqClient = arg0;
118	@total["Processes"] = count();
119    printf("%u T%d:client-new(<%x>,%s(%d),session=<%x>,task=%d)\n",
120        timestamp, self->mytid, arg0,
121		client[arg0].path, client[arg0].pid,
122		client[arg0].session, client[arg0].taskport);
123}
124
125securityd*:::client-release
126{
127    printf("%u T%d:client-release(<%x>,%s(%d))\n",
128		timestamp, self->mytid, arg0, client[arg0].path, arg1);
129	client[arg0].pid = 0;
130}
131
132securityd*:::client-change_session
133{
134    printf("%u T%d:client-change_session(<%x>,new session=<%x>)\n",
135		timestamp, self->mytid, arg0, arg1);
136	client[arg0].pid = 0;
137}
138
139
140/*
141 * Client requests
142 */
143uint32_t connections[DTHandle];
144uint32_t nextConnection;
145self uint32_t myConnection;
146
147securityd*:::request-entry
148/!connections[arg1]/
149{ connections[arg1] = ++nextConnection; }
150
151securityd*:::request-entry
152{
153	self->reqName = copyinstr(arg0);
154	self->reqConnection = arg1;
155	self->myConnection = connections[arg1];
156	self->reqClient = arg2;
157	this->client = client[self->reqClient];
158}
159
160securityd*:::request-entry
161/this->client.pid/
162{
163	printf("%u T%d:C%d:%s(%d)%s\n",
164		timestamp, self->mytid, self->myConnection, this->client.name, this->client.pid, self->reqName);
165	@request[client[self->reqClient].name, self->reqName] = count();
166}
167
168securityd*:::request-entry
169/!this->client.pid/
170{
171	printf("%u T%d:C%d:%s\n",
172		timestamp, self->mytid, self->myConnection, self->reqName);
173}
174
175securityd*:::request-entry
176{
177	@requests[self->reqName] = count();
178	@total["Requests"] = count();
179}
180
181securityd*:::request-return
182/self->reqConnection && arg0 == 0/
183{
184	printf("%u T%d:C%d:return\n",
185		timestamp, self->mytid, self->myConnection);
186}
187
188securityd*:::request-return
189/self->reqConnection && arg0 != 0/
190{
191	printf("%u T%d:C%d:FAIL(%d)\n",
192		timestamp, self->mytid, self->myConnection, arg0);
193}
194
195securityd*:::request-return
196{
197	self->reqConnection = 0;
198	self->reqClient = 0;
199}
200
201
202/*
203 * Sessions
204 */
205typedef uint32_t SessionId;
206
207struct Session {
208	DTHandle handle;
209	SessionId sessionid;
210};
211struct Session session[SessionId];
212
213struct xauditinfo {
214	uint32_t	ai_auid;		/* audit user id */
215	struct {
216		unsigned int low;
217		unsigned int high;
218	} ai_mask;
219	struct {
220		uint32_t dev;
221		uint32_t type;
222		uint32_t addr[4];
223	} ai_termid;
224	au_asid_t ai_asid;		/* audit session id */
225	au_asflgs_t ai_flags;	/* audit session flags */
226};
227self struct xauditinfo *ai;
228
229securityd*:::session-create
230{
231	session[arg1].handle = arg0;
232	session[arg1].sessionid = arg1;
233	self->ai = copyin(arg2, sizeof(struct xauditinfo));
234	printf("%u T%d:%s(<%x>,id=%d,uid=%d,flags=%#x)\n", timestamp, self->mytid, probename,
235		arg0, arg1, self->ai->ai_auid, self->ai->ai_flags);
236}
237
238securityd*:::session-kill
239{
240	printf("%u T%d:%s(<%x>,id=%d)\n", timestamp, self->mytid, probename, arg0, arg1);
241}
242
243securityd*:::session-destroy
244{
245	printf("%u T%d:%s(<%x>,id=%d)\n", timestamp, self->mytid, probename, arg0, arg1);
246}
247
248securityd*:::session-notify
249{
250	printf("%u T%d:%s(<%x>,id=%d,events=0x%x,uid=%d)\n", timestamp, self->mytid, probename,
251		session[arg0].handle, arg0, arg1, arg2);
252}
253
254
255/*
256 * Keychains
257 */
258securityd*:::keychain-*
259{
260	this->path = copyinstr(arg1);
261	printf("%u T%d:%s(<%x>,%s)\n", timestamp, self->mytid, probename, arg0, this->path);
262	@keychain[this->path, probename] = count();
263}
264
265
266/*
267 * Low-level port events
268 */
269securityd*:::ports-*
270{
271	printf("%u T%d:%s(%d)\n", timestamp, self->mytid, probename, arg0);
272}
273
274
275/*
276 * Code signing
277 */
278securityd*:::guest-create
279{
280	printf("%u T%d:guest-create(<%x>,host=<%x>,guest=<%x>,status=0x%x,flags=0x%x,path=%s)\n",
281		timestamp, self->mytid, arg0, arg1, arg2, arg3, arg4, copyinstr(arg5));
282	@total["Guests"] = count();
283}
284
285securityd*:::guest-change
286{
287	printf("%u T%d:guest-change(<%x>,<%x>,status=0x%x)\n", timestamp, self->mytid, arg0, arg1, arg2);
288}
289
290securityd*:::guest-destroy
291{
292	printf("%u T%d:guest-destroy(<%x>,<%x>)\n", timestamp, self->mytid, arg0, arg1);
293}
294
295securityd*:::host-register,
296securityd*:::host-proxy
297{
298	printf("%u T%d:%s(<%x>,port=%d)\n", timestamp, self->mytid, probename, arg0, arg1);
299	@total["Hosts"] = count();
300}
301
302securityd*:::host-unregister
303{
304	printf("%u T%d:host-unregister(<%x>)\n", timestamp, self->mytid, arg0);
305}
306
307
308/*
309 * Child management
310 */
311securityd*:::child-*
312{
313	printf("%u T%d:%s(%d,%d)\n", timestamp, self->mytid, probename, arg0, arg1);
314}
315
316
317/*
318 * Power events
319 */
320securityd*:::power-*
321{
322	printf("%u T%d:POWER(%s)\n", timestamp, self->mytid, probename);
323}
324
325
326/*
327 * Authorization
328 */
329securityd*:::auth-create
330{
331    printf("%u T%d:%s ref(%#x) session(%#x)\n", timestamp, self->mytid, probename, arg1, arg0);
332}
333
334securityd*:::auth-allow,
335securityd*:::auth-deny,
336securityd*:::auth-user,
337securityd*:::auth-rules,
338securityd*:::auth-kofn,
339securityd*:::auth-mechrule
340{
341    printf("%u T%d:%s ref(%#x) rule(%s)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1));
342}
343
344securityd*:::auth-mech
345{
346    printf("%u T%d:%s ref(%#x) (%s)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1));
347}
348
349securityd*:::auth-user-allowroot,
350securityd*:::auth-user-allowsessionowner
351{
352    printf("%u T%d:%s ref(%#x)\n", timestamp, self->mytid, probename, arg0);
353}
354
355securityd*:::auth-evalright
356{
357    printf("%u T%d:%s ref(%#x) %s (%d)\n", timestamp, self->mytid, probename, arg0, copyinstr(arg1), arg2);
358}
359
360
361/*
362 * Miscellanea
363 */
364securityd*:::entropy-collect
365{
366	printf("%u T%d:entropy-collect()\n", timestamp, tid);
367}
368
369securityd*:::entropy-seed
370{
371	printf("%u T%d:entropy-seed(%d)\n", timestamp, self->mytid, arg0);
372}
373
374securityd*:::entropy-save
375{
376	printf("%u T%d:entropy-save(%s)\n", timestamp, self->mytid, copyinstr(arg0));
377}
378
379securityd*:::signal-*
380{
381	printf("%u T%d:%s(%d)\n", timestamp, self->mytid, probename, arg0);
382}
383
384
385/*
386 * Integrate secdebug logs
387 */
388security_debug*:::log
389/execname == "securityd"/
390{
391	printf("%u T%d:[%s]%s\n", timestamp, threads[tid],
392		copyinstr(arg0), copyinstr(arg1));
393}
394
395security_exception*:::throw-*
396/execname == "securityd"/
397{
398	printf("%u T%d:EXCEPTION(%p) THROWN %s(%d)\n", timestamp, threads[tid],
399		arg0, probename, arg1);
400}
401
402
403/*
404 * Wrapup
405 */
406:::END
407{
408	printa("%@8u %s\n", @total);
409	printf("\n         Requests:\n");
410	printa("%@8u %s\n", @requests);
411	printf("\n         Requests by client:\n");
412	printa("%@8u %s:%s\n", @request);
413	printf("\n         Keychains by path and operation:\n");
414	printa("%@8u %s(%s)\n", @keychain);
415}
416