xref: /xnu-11215.1.10/tests/kevent_info.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1*8d741a5dSApple OSS Distributions #include <stdio.h>
2*8d741a5dSApple OSS Distributions #include <assert.h>
3*8d741a5dSApple OSS Distributions #include <stdlib.h>
4*8d741a5dSApple OSS Distributions #include <unistd.h>
5*8d741a5dSApple OSS Distributions #include <mach/mach.h>
6*8d741a5dSApple OSS Distributions #include <pthread.h>
7*8d741a5dSApple OSS Distributions #include <sys/event.h>
8*8d741a5dSApple OSS Distributions #include <errno.h>
9*8d741a5dSApple OSS Distributions #include <string.h>
10*8d741a5dSApple OSS Distributions #include <libproc.h>
11*8d741a5dSApple OSS Distributions 
12*8d741a5dSApple OSS Distributions #include <darwintest.h>
13*8d741a5dSApple OSS Distributions 
14*8d741a5dSApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.kevent"),
15*8d741a5dSApple OSS Distributions     T_META_RADAR_COMPONENT_NAME("xnu"),
16*8d741a5dSApple OSS Distributions     T_META_RADAR_COMPONENT_VERSION("kevent"));
17*8d741a5dSApple OSS Distributions 
18*8d741a5dSApple OSS Distributions extern int __proc_info(int32_t callnum, int32_t pid, uint32_t flavor, uint64_t arg, user_addr_t buffer, int32_t buffersize);
19*8d741a5dSApple OSS Distributions 
20*8d741a5dSApple OSS Distributions T_DECL(avoid_leaking_KASLR, "rdar://101248992", T_META_TAG_VM_PREFERRED) {
21*8d741a5dSApple OSS Distributions 	int kq = kqueue();
22*8d741a5dSApple OSS Distributions 	T_ASSERT_GE(kq, 0, "Valid kqueue");
23*8d741a5dSApple OSS Distributions 
24*8d741a5dSApple OSS Distributions 	mach_port_t sync_port = MACH_PORT_NULL, mq_port = MACH_PORT_NULL;
25*8d741a5dSApple OSS Distributions 	kern_return_t kr = KERN_SUCCESS;
26*8d741a5dSApple OSS Distributions 
27*8d741a5dSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &sync_port);
28*8d741a5dSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "allocated sync port");
29*8d741a5dSApple OSS Distributions 	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &mq_port);
30*8d741a5dSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "allocated mq port");
31*8d741a5dSApple OSS Distributions 
32*8d741a5dSApple OSS Distributions 
33*8d741a5dSApple OSS Distributions 	/* Create a kmsg which has the receive right of mq port in it for later copy
34*8d741a5dSApple OSS Distributions 	 * out */
35*8d741a5dSApple OSS Distributions 	typedef struct msg_request_s {
36*8d741a5dSApple OSS Distributions 		mach_msg_header_t header;
37*8d741a5dSApple OSS Distributions 		mach_msg_body_t body;
38*8d741a5dSApple OSS Distributions 		mach_msg_port_descriptor_t port;
39*8d741a5dSApple OSS Distributions 	}* msg_request_t;
40*8d741a5dSApple OSS Distributions 
41*8d741a5dSApple OSS Distributions 	typedef struct msg_reply_s {
42*8d741a5dSApple OSS Distributions 		mach_msg_header_t header;
43*8d741a5dSApple OSS Distributions 		mach_msg_body_t body;
44*8d741a5dSApple OSS Distributions 		mach_msg_port_descriptor_t port;
45*8d741a5dSApple OSS Distributions 		mach_msg_trailer_t trailer;
46*8d741a5dSApple OSS Distributions 	}* msg_reply_t;
47*8d741a5dSApple OSS Distributions 
48*8d741a5dSApple OSS Distributions 	union {
49*8d741a5dSApple OSS Distributions 		struct msg_request_s request;
50*8d741a5dSApple OSS Distributions 		struct msg_reply_s reply;
51*8d741a5dSApple OSS Distributions 	} message;
52*8d741a5dSApple OSS Distributions 	memset(&message, 0, sizeof(message));
53*8d741a5dSApple OSS Distributions 
54*8d741a5dSApple OSS Distributions 	msg_request_t requestp = &message.request;
55*8d741a5dSApple OSS Distributions 	msg_reply_t replyp = &message.reply;
56*8d741a5dSApple OSS Distributions 
57*8d741a5dSApple OSS Distributions 	*requestp = (struct msg_request_s) {
58*8d741a5dSApple OSS Distributions 		.header = {
59*8d741a5dSApple OSS Distributions 			.msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0, 0, MACH_MSGH_BITS_COMPLEX),
60*8d741a5dSApple OSS Distributions 			.msgh_remote_port = sync_port,
61*8d741a5dSApple OSS Distributions 			.msgh_local_port = MACH_PORT_NULL,
62*8d741a5dSApple OSS Distributions 			.msgh_voucher_port = MACH_PORT_NULL,
63*8d741a5dSApple OSS Distributions 			.msgh_size = sizeof(*requestp),
64*8d741a5dSApple OSS Distributions 			.msgh_id = 0x88888888,
65*8d741a5dSApple OSS Distributions 		},
66*8d741a5dSApple OSS Distributions 		.body = {
67*8d741a5dSApple OSS Distributions 			.msgh_descriptor_count = 1,
68*8d741a5dSApple OSS Distributions 		},
69*8d741a5dSApple OSS Distributions 		.port = {
70*8d741a5dSApple OSS Distributions 			.name = mq_port,
71*8d741a5dSApple OSS Distributions 			.type = MACH_MSG_PORT_DESCRIPTOR,
72*8d741a5dSApple OSS Distributions 			.disposition = MACH_MSG_TYPE_MOVE_RECEIVE,
73*8d741a5dSApple OSS Distributions 		},
74*8d741a5dSApple OSS Distributions 	};
75*8d741a5dSApple OSS Distributions 
76*8d741a5dSApple OSS Distributions 	/*
77*8d741a5dSApple OSS Distributions 	 *	Send the receive right of mq_port to sync_port for later copyout.
78*8d741a5dSApple OSS Distributions 	 */
79*8d741a5dSApple OSS Distributions 	kr = mach_msg(&requestp->header, MACH_SEND_MSG, sizeof(*requestp), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
80*8d741a5dSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "sending message to sync port");
81*8d741a5dSApple OSS Distributions 
82*8d741a5dSApple OSS Distributions 	/*
83*8d741a5dSApple OSS Distributions 	 * The EV_DISPATCH is required that can pass filt_machport_kqueue_has_turnstile().
84*8d741a5dSApple OSS Distributions 	 * The received message will be copied out to replyp.
85*8d741a5dSApple OSS Distributions 	 * In filt_machport_stash_port(), the value in ext[3] will be set to the mq_port object.
86*8d741a5dSApple OSS Distributions 	 */
87*8d741a5dSApple OSS Distributions 	struct kevent_qos_s req_event = {
88*8d741a5dSApple OSS Distributions 		.ident = sync_port,
89*8d741a5dSApple OSS Distributions 		.filter = EVFILT_MACHPORT,
90*8d741a5dSApple OSS Distributions 		.flags = EV_ADD | EV_DISPATCH,
91*8d741a5dSApple OSS Distributions 		.fflags = MACH_RCV_MSG,
92*8d741a5dSApple OSS Distributions 		.ext = {
93*8d741a5dSApple OSS Distributions 			[0] = (uint64_t)replyp,
94*8d741a5dSApple OSS Distributions 			[1] = sizeof(*replyp),
95*8d741a5dSApple OSS Distributions 		},
96*8d741a5dSApple OSS Distributions 	};
97*8d741a5dSApple OSS Distributions 	struct kevent_qos_s reply_event = {};
98*8d741a5dSApple OSS Distributions 
99*8d741a5dSApple OSS Distributions 	int nevents = kevent_qos(kq, &req_event, 1, &reply_event, 1, NULL, NULL, 0);
100*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(nevents, 1, NULL);
101*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(replyp->body.msgh_descriptor_count, 1, NULL);
102*8d741a5dSApple OSS Distributions 	assert(MACH_PORT_VALID(replyp->port.name) && replyp->port.disposition == MACH_MSG_TYPE_MOVE_RECEIVE);
103*8d741a5dSApple OSS Distributions 
104*8d741a5dSApple OSS Distributions 	struct kevent_extinfo extinfo;
105*8d741a5dSApple OSS Distributions 	int knotes = __proc_info(PROC_INFO_CALL_PIDFDINFO, getpid(), PROC_PIDFDKQUEUE_EXTINFO, kq, (user_addr_t)&extinfo, sizeof(extinfo));
106*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(knotes, 1, NULL);
107*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(extinfo.kqext_kev.ident, sync_port, NULL);
108*8d741a5dSApple OSS Distributions 
109*8d741a5dSApple OSS Distributions 	uint64_t leaked_addr = extinfo.kqext_kev.ext[3];
110*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ(leaked_addr, NULL, "Leaked kernel address");
111*8d741a5dSApple OSS Distributions }
112