1/* quick and dirty hack to grab credential backtrace info from kernel via sysctl.
2 * sysctl is only defined if xnu is built with DEBUG_CRED defined.
3 * The current version of this is used to target a specific credential and gather
4 * backtrace info on all references and unreferences.
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <fcntl.h>
10#include <limits.h>
11#include <string.h>
12#include <errno.h>
13#include <unistd.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <sys/sysctl.h>
17#include <bsm/audit.h>
18
19/* bad!  this is replicated in kern_credential.c.  make sure they stay in sync!
20 * Or better yet have commone header file?
21 */
22#define MAX_STACK_DEPTH 8
23struct cred_backtrace {
24	int				depth;
25	uint32_t		stack[ MAX_STACK_DEPTH ];
26};
27typedef struct cred_backtrace cred_backtrace;
28
29struct cred_debug_buffer {
30	int				next_slot;
31	cred_backtrace	stack_buffer[ 1 ];
32};
33typedef struct cred_debug_buffer cred_debug_buffer;
34
35
36main( int argc, char *argv[] )
37{
38	int				err, i, j;
39	size_t			len;
40    char 			*my_bufferp = NULL;
41	cred_debug_buffer	*bt_buffp;
42	cred_backtrace		*btp;
43
44	/* get size of buffer we will need */
45	len = 0;
46    err = sysctlbyname( "kern.cred_bt", NULL, &len, NULL, 0 );
47	if ( err != 0 ) {
48		printf( "sysctl failed  \n" );
49		printf( "\terrno %d - \"%s\" \n", errno, strerror( errno ) );
50		return;
51	}
52
53	/* get a buffer for our back traces */
54	my_bufferp = malloc( len );
55	if ( my_bufferp == NULL ) {
56		printf( "malloc error %d - \"%s\" \n", errno, strerror( errno ) );
57		return;
58	}
59    err = sysctlbyname( "kern.cred_bt", my_bufferp, &len, NULL, 0 );
60	if ( err != 0 ) {
61		printf( "sysctl 2 failed  \n" );
62		printf( "\terrno %d - \"%s\" \n", errno, strerror( errno ) );
63		return;
64	}
65
66	bt_buffp = (cred_debug_buffer *) my_bufferp;
67	btp = &bt_buffp->stack_buffer[ 0 ];
68
69	printf("number of traces %d \n", bt_buffp->next_slot);
70	for ( i = 0; i < bt_buffp->next_slot; i++, btp++ ) {
71		printf("[%d] ", i);
72		for ( j = 0; j < btp->depth; j++ ) {
73			printf("%p ", btp->stack[ j ]);
74		}
75		printf("\n");
76	}
77
78	return;
79}
80
81