OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "util/mach/notify_server.h" |
| 16 |
| 17 #include "base/logging.h" |
| 18 #include "util/mach/notifyServer.h" |
| 19 #include "util/mach/mach_message.h" |
| 20 |
| 21 extern "C" { |
| 22 |
| 23 // These five functions are not used, and are in fact obsoleted by the other |
| 24 // functionality implemented in this file. The standard MIG-generated |
| 25 // notify_server() (in notifyServer.c) server dispatch routine usable with the |
| 26 // standard mach_msg_server() function calls out to this function. |
| 27 // notify_server() is unused and is replaced by the more flexible NotifyServer, |
| 28 // but the linker still needs to see these five function definitions. |
| 29 |
| 30 kern_return_t do_mach_notify_port_deleted(notify_port_t notify, |
| 31 mach_port_name_t name) { |
| 32 NOTREACHED(); |
| 33 return KERN_FAILURE; |
| 34 } |
| 35 |
| 36 kern_return_t do_mach_notify_port_destroyed(notify_port_t notify, |
| 37 mach_port_t rights) { |
| 38 NOTREACHED(); |
| 39 return KERN_FAILURE; |
| 40 } |
| 41 |
| 42 kern_return_t do_mach_notify_no_senders(notify_port_t notify, |
| 43 mach_port_mscount_t mscount) { |
| 44 NOTREACHED(); |
| 45 return KERN_FAILURE; |
| 46 } |
| 47 |
| 48 kern_return_t do_mach_notify_send_once(notify_port_t notify) { |
| 49 NOTREACHED(); |
| 50 return KERN_FAILURE; |
| 51 } |
| 52 |
| 53 kern_return_t do_mach_notify_dead_name(notify_port_t notify, |
| 54 mach_port_name_t name) { |
| 55 NOTREACHED(); |
| 56 return KERN_FAILURE; |
| 57 } |
| 58 |
| 59 } // extern "C" |
| 60 |
| 61 namespace { |
| 62 |
| 63 // The MIG-generated __MIG_check__Request__*() functions are not declared as |
| 64 // accepting const data, but they could have been because they in fact do not |
| 65 // modify the data. These wrapper functions are provided to bridge the const gap |
| 66 // between the code in this file, which is const-correct and treats request |
| 67 // message data as const, and the generated functions. |
| 68 |
| 69 kern_return_t MIGCheckRequestMachNotifyPortDeleted( |
| 70 const __Request__mach_notify_port_deleted_t* in_request) { |
| 71 using Request = __Request__mach_notify_port_deleted_t; |
| 72 return __MIG_check__Request__mach_notify_port_deleted_t( |
| 73 const_cast<Request*>(in_request)); |
| 74 } |
| 75 |
| 76 kern_return_t MIGCheckRequestMachNotifyPortDestroyed( |
| 77 const __Request__mach_notify_port_destroyed_t* in_request) { |
| 78 using Request = __Request__mach_notify_port_destroyed_t; |
| 79 return __MIG_check__Request__mach_notify_port_destroyed_t( |
| 80 const_cast<Request*>(in_request)); |
| 81 } |
| 82 |
| 83 kern_return_t MIGCheckRequestMachNotifyNoSenders( |
| 84 const __Request__mach_notify_no_senders_t* in_request) { |
| 85 using Request = __Request__mach_notify_no_senders_t; |
| 86 return __MIG_check__Request__mach_notify_no_senders_t( |
| 87 const_cast<Request*>(in_request)); |
| 88 } |
| 89 |
| 90 kern_return_t MIGCheckRequestMachNotifySendOnce( |
| 91 const __Request__mach_notify_send_once_t* in_request) { |
| 92 using Request = __Request__mach_notify_send_once_t; |
| 93 return __MIG_check__Request__mach_notify_send_once_t( |
| 94 const_cast<Request*>(in_request)); |
| 95 } |
| 96 |
| 97 kern_return_t MIGCheckRequestMachNotifyDeadName( |
| 98 const __Request__mach_notify_dead_name_t* in_request) { |
| 99 using Request = __Request__mach_notify_dead_name_t; |
| 100 return __MIG_check__Request__mach_notify_dead_name_t( |
| 101 const_cast<Request*>(in_request)); |
| 102 } |
| 103 |
| 104 } // namespace |
| 105 |
| 106 namespace crashpad { |
| 107 |
| 108 NotifyServer::NotifyServer(NotifyServer::Interface* interface) |
| 109 : MachMessageServer::Interface(), |
| 110 interface_(interface) { |
| 111 } |
| 112 |
| 113 bool NotifyServer::MachMessageServerFunction( |
| 114 const mach_msg_header_t* in_header, |
| 115 mach_msg_header_t* out_header, |
| 116 bool* destroy_complex_request) { |
| 117 PrepareMIGReplyFromRequest(in_header, out_header); |
| 118 |
| 119 const mach_msg_trailer_t* in_trailer = |
| 120 MachMessageTrailerFromHeader(in_header); |
| 121 |
| 122 switch (in_header->msgh_id) { |
| 123 case MACH_NOTIFY_PORT_DELETED: { |
| 124 // mach_notify_port_deleted(), do_mach_notify_port_deleted(). |
| 125 using Request = __Request__mach_notify_port_deleted_t; |
| 126 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 127 kern_return_t kr = MIGCheckRequestMachNotifyPortDeleted(in_request); |
| 128 if (kr != MACH_MSG_SUCCESS) { |
| 129 SetMIGReplyError(out_header, kr); |
| 130 return true; |
| 131 } |
| 132 |
| 133 using Reply = __Reply__mach_notify_port_deleted_t; |
| 134 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 135 out_reply->RetCode = |
| 136 interface_->DoMachNotifyPortDeleted(in_header->msgh_local_port, |
| 137 in_request->name, |
| 138 in_trailer); |
| 139 return true; |
| 140 } |
| 141 |
| 142 case MACH_NOTIFY_PORT_DESTROYED: { |
| 143 // mach_notify_port_destroyed(), do_mach_notify_port_destroyed(). |
| 144 using Request = __Request__mach_notify_port_destroyed_t; |
| 145 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 146 kern_return_t kr = MIGCheckRequestMachNotifyPortDestroyed(in_request); |
| 147 if (kr != MACH_MSG_SUCCESS) { |
| 148 SetMIGReplyError(out_header, kr); |
| 149 return true; |
| 150 } |
| 151 |
| 152 using Reply = __Reply__mach_notify_port_destroyed_t; |
| 153 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 154 out_reply->RetCode = |
| 155 interface_->DoMachNotifyPortDestroyed(in_header->msgh_local_port, |
| 156 in_request->rights.name, |
| 157 in_trailer, |
| 158 destroy_complex_request); |
| 159 return true; |
| 160 } |
| 161 |
| 162 case MACH_NOTIFY_NO_SENDERS: { |
| 163 // mach_notify_no_senders(), do_mach_notify_no_senders(). |
| 164 using Request = __Request__mach_notify_no_senders_t; |
| 165 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 166 kern_return_t kr = MIGCheckRequestMachNotifyNoSenders(in_request); |
| 167 if (kr != MACH_MSG_SUCCESS) { |
| 168 SetMIGReplyError(out_header, kr); |
| 169 return true; |
| 170 } |
| 171 |
| 172 using Reply = __Reply__mach_notify_no_senders_t; |
| 173 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 174 out_reply->RetCode = |
| 175 interface_->DoMachNotifyNoSenders(in_header->msgh_local_port, |
| 176 in_request->mscount, |
| 177 in_trailer); |
| 178 return true; |
| 179 } |
| 180 |
| 181 case MACH_NOTIFY_SEND_ONCE: { |
| 182 // mach_notify_send_once(), do_mach_notify_send_once(). |
| 183 using Request = __Request__mach_notify_send_once_t; |
| 184 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 185 kern_return_t kr = MIGCheckRequestMachNotifySendOnce(in_request); |
| 186 if (kr != MACH_MSG_SUCCESS) { |
| 187 SetMIGReplyError(out_header, kr); |
| 188 return true; |
| 189 } |
| 190 |
| 191 using Reply = __Reply__mach_notify_send_once_t; |
| 192 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 193 out_reply->RetCode = |
| 194 interface_->DoMachNotifySendOnce(in_header->msgh_local_port, |
| 195 in_trailer); |
| 196 return true; |
| 197 } |
| 198 |
| 199 case MACH_NOTIFY_DEAD_NAME: { |
| 200 // mach_notify_dead_name(), do_mach_notify_dead_name(). |
| 201 using Request = __Request__mach_notify_dead_name_t; |
| 202 const Request* in_request = reinterpret_cast<const Request*>(in_header); |
| 203 kern_return_t kr = MIGCheckRequestMachNotifyDeadName(in_request); |
| 204 if (kr != MACH_MSG_SUCCESS) { |
| 205 SetMIGReplyError(out_header, kr); |
| 206 return true; |
| 207 } |
| 208 |
| 209 using Reply = __Reply__mach_notify_dead_name_t; |
| 210 Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
| 211 out_reply->RetCode = |
| 212 interface_->DoMachNotifyDeadName(in_header->msgh_local_port, |
| 213 in_request->name, |
| 214 in_trailer); |
| 215 return true; |
| 216 } |
| 217 |
| 218 default: { |
| 219 SetMIGReplyError(out_header, MIG_BAD_ID); |
| 220 return false; |
| 221 } |
| 222 } |
| 223 } |
| 224 |
| 225 std::set<mach_msg_id_t> NotifyServer::MachMessageServerRequestIDs() { |
| 226 const mach_msg_id_t request_ids[] = { |
| 227 MACH_NOTIFY_PORT_DELETED, |
| 228 MACH_NOTIFY_PORT_DESTROYED, |
| 229 MACH_NOTIFY_NO_SENDERS, |
| 230 MACH_NOTIFY_SEND_ONCE, |
| 231 MACH_NOTIFY_DEAD_NAME, |
| 232 }; |
| 233 return std::set<mach_msg_id_t>(&request_ids[0], |
| 234 &request_ids[arraysize(request_ids)]); |
| 235 } |
| 236 |
| 237 mach_msg_size_t NotifyServer::MachMessageServerRequestSize() { |
| 238 return sizeof(__RequestUnion__do_notify_subsystem); |
| 239 } |
| 240 |
| 241 mach_msg_size_t NotifyServer::MachMessageServerReplySize() { |
| 242 return sizeof(__ReplyUnion__do_notify_subsystem); |
| 243 } |
| 244 |
| 245 } // namespace crashpad |
OLD | NEW |