1*0f4c859eSApple OSS Distributions /* 2*0f4c859eSApple OSS Distributions * Test that sending a message to a voucher with the same voucher as the voucher port 3*0f4c859eSApple OSS Distributions * with only one send right count with move send before the copy send doesn't panic. 4*0f4c859eSApple OSS Distributions * 5*0f4c859eSApple OSS Distributions * clang -o voucherentry voucherentry.c -ldarwintest -Weverything -Wno-gnu-flexible-array-initializer 6*0f4c859eSApple OSS Distributions * 7*0f4c859eSApple OSS Distributions * <rdar://problem/18826844> 8*0f4c859eSApple OSS Distributions */ 9*0f4c859eSApple OSS Distributions 10*0f4c859eSApple OSS Distributions #include <mach/mach.h> 11*0f4c859eSApple OSS Distributions #include <darwintest.h> 12*0f4c859eSApple OSS Distributions 13*0f4c859eSApple OSS Distributions T_GLOBAL_META( 14*0f4c859eSApple OSS Distributions T_META_NAMESPACE("xnu.ipc"), 15*0f4c859eSApple OSS Distributions T_META_RUN_CONCURRENTLY(TRUE), 16*0f4c859eSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"), 17*0f4c859eSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("IPC")); 18*0f4c859eSApple OSS Distributions 19*0f4c859eSApple OSS Distributions T_DECL(voucher_entry, "voucher_entry", T_META_CHECK_LEAKS(false), T_META_ALL_VALID_ARCHS(true)) 20*0f4c859eSApple OSS Distributions { 21*0f4c859eSApple OSS Distributions kern_return_t kr = KERN_SUCCESS; 22*0f4c859eSApple OSS Distributions mach_voucher_t voucher = MACH_VOUCHER_NULL; 23*0f4c859eSApple OSS Distributions 24*0f4c859eSApple OSS Distributions /* 25*0f4c859eSApple OSS Distributions * The bank voucher already exists in this process, so using it doesn't 26*0f4c859eSApple OSS Distributions * actually test the problem. Use an importance voucher instead. 27*0f4c859eSApple OSS Distributions */ 28*0f4c859eSApple OSS Distributions mach_voucher_attr_recipe_data_t recipe = { 29*0f4c859eSApple OSS Distributions .key = MACH_VOUCHER_ATTR_KEY_IMPORTANCE, 30*0f4c859eSApple OSS Distributions .command = MACH_VOUCHER_ATTR_IMPORTANCE_SELF, 31*0f4c859eSApple OSS Distributions .previous_voucher = MACH_VOUCHER_NULL, 32*0f4c859eSApple OSS Distributions .content_size = 0, 33*0f4c859eSApple OSS Distributions }; 34*0f4c859eSApple OSS Distributions 35*0f4c859eSApple OSS Distributions kr = host_create_mach_voucher(mach_host_self(), 36*0f4c859eSApple OSS Distributions (mach_voucher_attr_raw_recipe_array_t)&recipe, 37*0f4c859eSApple OSS Distributions sizeof(recipe), &voucher); 38*0f4c859eSApple OSS Distributions 39*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "host_create_mach_voucher"); 40*0f4c859eSApple OSS Distributions 41*0f4c859eSApple OSS Distributions T_ASSERT_NOTNULL(voucher, "voucher must not be null"); 42*0f4c859eSApple OSS Distributions 43*0f4c859eSApple OSS Distributions mach_port_urefs_t refs = 0; 44*0f4c859eSApple OSS Distributions 45*0f4c859eSApple OSS Distributions kr = mach_port_get_refs(mach_task_self(), voucher, MACH_PORT_RIGHT_SEND, &refs); 46*0f4c859eSApple OSS Distributions 47*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "mach_port_get_refs"); 48*0f4c859eSApple OSS Distributions 49*0f4c859eSApple OSS Distributions T_ASSERT_EQ(refs, (mach_port_urefs_t)1, "voucher must have only one ref"); 50*0f4c859eSApple OSS Distributions 51*0f4c859eSApple OSS Distributions /* First, try with two moves (must fail because there's only one ref) */ 52*0f4c859eSApple OSS Distributions mach_msg_header_t request_msg_1 = { 53*0f4c859eSApple OSS Distributions .msgh_remote_port = voucher, 54*0f4c859eSApple OSS Distributions .msgh_local_port = MACH_PORT_NULL, 55*0f4c859eSApple OSS Distributions .msgh_voucher_port = voucher, 56*0f4c859eSApple OSS Distributions .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND, 0, MACH_MSG_TYPE_MOVE_SEND, 0), 57*0f4c859eSApple OSS Distributions .msgh_id = 0xDEAD, 58*0f4c859eSApple OSS Distributions .msgh_size = sizeof(request_msg_1), 59*0f4c859eSApple OSS Distributions }; 60*0f4c859eSApple OSS Distributions 61*0f4c859eSApple OSS Distributions kr = mach_msg2(&request_msg_1, MACH64_SEND_MSG | MACH64_SEND_KOBJECT_CALL, 62*0f4c859eSApple OSS Distributions request_msg_1, request_msg_1.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, 0); 63*0f4c859eSApple OSS Distributions 64*0f4c859eSApple OSS Distributions T_ASSERT_MACH_ERROR(MACH_SEND_INVALID_DEST, kr, "send with two moves should fail with invalid dest"); 65*0f4c859eSApple OSS Distributions 66*0f4c859eSApple OSS Distributions /* Next, try with a move and a copy (will succeed and destroy the last ref) */ 67*0f4c859eSApple OSS Distributions mach_msg_header_t request_msg_2 = { 68*0f4c859eSApple OSS Distributions .msgh_remote_port = voucher, 69*0f4c859eSApple OSS Distributions .msgh_local_port = MACH_PORT_NULL, 70*0f4c859eSApple OSS Distributions .msgh_voucher_port = voucher, 71*0f4c859eSApple OSS Distributions .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MOVE_SEND, 0, MACH_MSG_TYPE_COPY_SEND, 0), 72*0f4c859eSApple OSS Distributions .msgh_id = 0xDEAD, 73*0f4c859eSApple OSS Distributions .msgh_size = sizeof(request_msg_2), 74*0f4c859eSApple OSS Distributions }; 75*0f4c859eSApple OSS Distributions 76*0f4c859eSApple OSS Distributions /* panic happens here */ 77*0f4c859eSApple OSS Distributions kr = mach_msg2(&request_msg_2, MACH64_SEND_MSG | MACH64_SEND_KOBJECT_CALL, 78*0f4c859eSApple OSS Distributions request_msg_2, request_msg_2.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, 0); 79*0f4c859eSApple OSS Distributions 80*0f4c859eSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "send with move and copy succeeds"); 81*0f4c859eSApple OSS Distributions 82*0f4c859eSApple OSS Distributions kr = mach_port_get_refs(mach_task_self(), voucher, MACH_PORT_RIGHT_SEND, &refs); 83*0f4c859eSApple OSS Distributions 84*0f4c859eSApple OSS Distributions T_ASSERT_MACH_ERROR(KERN_INVALID_NAME, kr, "voucher should now be invalid name"); 85*0f4c859eSApple OSS Distributions } 86