1 #include <darwintest.h>
2 #include <darwintest_multiprocess.h>
4 #include <servers/bootstrap.h>
5 #include <sys/sysctl.h>
6 #include "exc_helpers.h"
9 T_META_NAMESPACE("xnu.ipc"),
10 T_META_RUN_CONCURRENTLY(true));
12 #pragma mark - helpers
14 #define SERVICE_NAME "com.apple.xnu.test.mach_port"
17 mach_msg_header_t header
;
19 mach_msg_port_descriptor_t port_descriptor
;
20 mach_msg_trailer_t trailer
; // subtract this when sending
29 kr
= bootstrap_check_in(bootstrap_port
, SERVICE_NAME
, &mp
);
30 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "bootstrap_check_in");
40 kr
= bootstrap_look_up(bootstrap_port
, SERVICE_NAME
, &mp
);
41 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "bootstrap_look_up");
48 mach_port_options_t opts
= {
49 .flags
= MPO_INSERT_SEND_RIGHT
,
54 kr
= mach_port_construct(mach_task_self(), &opts
, 0ull, &port
);
55 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "mach_port_construct");
60 destroy_port(mach_port_t port
, bool receive
, int srights
)
65 kr
= mach_port_mod_refs(mach_task_self(), port
,
66 MACH_PORT_RIGHT_SEND
, -srights
);
67 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "srights -= %d", srights
);
70 kr
= mach_port_mod_refs(mach_task_self(), port
,
71 MACH_PORT_RIGHT_RECEIVE
, -1);
72 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "receive -= 1");
81 mach_msg_type_name_t disp
)
83 struct one_port_msg msg
= {
85 .msgh_remote_port
= dest
,
86 .msgh_bits
= MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND
,
87 0, MACH_MSG_TYPE_MOVE_SEND
, MACH_MSGH_BITS_COMPLEX
),
89 .msgh_size
= offsetof(struct one_port_msg
, trailer
),
92 .msgh_descriptor_count
= 1,
97 .type
= MACH_MSG_PORT_DESCRIPTOR
,
102 kr
= mach_msg(&msg
.header
, MACH_SEND_MSG
| MACH_SEND_TIMEOUT
,
103 msg
.header
.msgh_size
, 0, MACH_PORT_NULL
, 10000, 0);
105 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "send(%d)", id
);
108 #pragma mark - basic test about right deduplication
112 mach_msg_id_t expected_id
,
113 mach_port_t rcv_port
,
114 mach_msg_type_name_t expected_disp
)
116 struct one_port_msg msg
= { };
119 T_LOG("waiting for message %d", expected_id
);
120 kr
= mach_msg(&msg
.header
, MACH_RCV_MSG
, 0,
121 sizeof(msg
), rcv_port
, 0, 0);
122 T_QUIET
; T_ASSERT_MACH_SUCCESS(kr
, "receive(%d)", expected_id
);
123 T_QUIET
; T_ASSERT_EQ(msg
.header
.msgh_id
, expected_id
, "message id matches");
124 T_QUIET
; T_ASSERT_NE(msg
.header
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
, 0,
125 "message is complex");
126 T_QUIET
; T_ASSERT_EQ(msg
.body
.msgh_descriptor_count
, 1, "message has one right");
127 T_QUIET
; T_ASSERT_EQ(msg
.port_descriptor
.disposition
, expected_disp
,
128 "port has right disposition");
129 return msg
.port_descriptor
.name
;
132 T_HELPER_DECL(right_dedup_server
, "right_dedup_server")
134 mach_port_t svc_port
= server_checkin();
135 mach_port_t ports
[3];
137 ports
[0] = receive_port(1, svc_port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
138 ports
[1] = receive_port(2, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
139 ports
[2] = receive_port(3, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
140 T_ASSERT_EQ(ports
[0], ports
[1], "receive, send, send");
141 T_ASSERT_EQ(ports
[0], ports
[2], "receive, send, send");
142 destroy_port(ports
[0], true, 2);
144 ports
[0] = receive_port(4, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
145 ports
[1] = receive_port(5, svc_port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
146 ports
[2] = receive_port(6, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
147 T_ASSERT_EQ(ports
[0], ports
[1], "send, receive, send");
148 T_ASSERT_EQ(ports
[0], ports
[2], "send, receive, send");
149 destroy_port(ports
[0], true, 2);
151 ports
[0] = receive_port(7, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
152 ports
[1] = receive_port(8, svc_port
, MACH_MSG_TYPE_MOVE_SEND
);
153 ports
[2] = receive_port(9, svc_port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
154 T_ASSERT_EQ(ports
[0], ports
[1], "send, send, receive");
155 T_ASSERT_EQ(ports
[0], ports
[2], "send, send, receive");
156 destroy_port(ports
[0], true, 2);
161 T_HELPER_DECL(right_dedup_client
, "right_dedup_client")
163 mach_port_t svc_port
= server_lookup();
166 port
= make_sr_port();
167 send_port(1, svc_port
, port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
168 send_port(2, svc_port
, port
, MACH_MSG_TYPE_COPY_SEND
);
169 send_port(3, svc_port
, port
, MACH_MSG_TYPE_MOVE_SEND
);
171 port
= make_sr_port();
172 send_port(4, svc_port
, port
, MACH_MSG_TYPE_COPY_SEND
);
173 send_port(5, svc_port
, port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
174 send_port(6, svc_port
, port
, MACH_MSG_TYPE_MOVE_SEND
);
176 port
= make_sr_port();
177 send_port(7, svc_port
, port
, MACH_MSG_TYPE_COPY_SEND
);
178 send_port(8, svc_port
, port
, MACH_MSG_TYPE_MOVE_SEND
);
179 send_port(9, svc_port
, port
, MACH_MSG_TYPE_MOVE_RECEIVE
);
182 T_DECL(right_dedup
, "make sure right deduplication works")
184 dt_helper_t helpers
[] = {
185 dt_launchd_helper_domain("com.apple.xnu.test.mach_port.plist",
186 "right_dedup_server", NULL
, LAUNCH_SYSTEM_DOMAIN
),
187 dt_fork_helper("right_dedup_client"),
189 dt_run_helpers(helpers
, 2, 600);