| 215 | } |
| 216 | |
| 217 | void UEventDeviceManager::ueventProcessRead() |
| 218 | { |
| 219 | std::string buffer(4096, 0); |
| 220 | struct iovec iov[1]; |
| 221 | iov[0].iov_base = (void*)&buffer[0]; |
| 222 | iov[0].iov_len = buffer.capacity(); |
| 223 | struct sockaddr_nl peer_sockaddr = { }; |
| 224 | union { |
| 225 | struct cmsghdr header; |
| 226 | uint8_t ucred[CMSG_SPACE(sizeof(struct ucred))]; |
| 227 | } cmsg_un; |
| 228 | cmsg_un.header.cmsg_len = CMSG_LEN(sizeof(struct ucred)); |
| 229 | cmsg_un.header.cmsg_level = SOL_SOCKET; |
| 230 | cmsg_un.header.cmsg_type = SCM_CREDENTIALS; |
| 231 | struct msghdr msg_header = { }; |
| 232 | msg_header.msg_control = cmsg_un.ucred; |
| 233 | msg_header.msg_controllen = sizeof cmsg_un.ucred; |
| 234 | msg_header.msg_iov = iov; |
| 235 | msg_header.msg_iovlen = 1; |
| 236 | msg_header.msg_name = &peer_sockaddr; |
| 237 | msg_header.msg_namelen = sizeof peer_sockaddr; |
| 238 | const int rc = recvmsg(_uevent_fd, &msg_header, MSG_DONTWAIT); |
| 239 | |
| 240 | if (rc <= 0) { |
| 241 | const int saved_errno = errno; |
| 242 | |
| 243 | if (saved_errno == EAGAIN || saved_errno == EWOULDBLOCK) { |
| 244 | USBGUARD_LOG(Warning) << "ueventProcessRead: " |
| 245 | << "reading from uevent source would block thread execution"; |
| 246 | return; |
| 247 | } |
| 248 | else if (saved_errno == ENOBUFS) { |
| 249 | USBGUARD_LOG(Error) << "ueventProcessRead: " |
| 250 | << "failed to read pending uevent (returning): " |
| 251 | << "rc=" << rc << " errno=" << saved_errno; |
| 252 | usleep(1000); |
| 253 | return; |
| 254 | } |
| 255 | else { |
| 256 | USBGUARD_LOG(Error) << "ueventProcessRead: " |
| 257 | << "failed to read pending uevent: " |
| 258 | << "rc=" << rc << " errno=" << saved_errno; |
| 259 | throw ErrnoException("UEvent device manager", "recvmsg", saved_errno); |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | buffer.resize((size_t)rc); |
| 264 | const struct cmsghdr* const cmsg_header = CMSG_FIRSTHDR(&msg_header); |
| 265 | |
| 266 | if (cmsg_header == nullptr) { |
| 267 | /* ignore */ |
| 268 | USBGUARD_LOG(Warning) << "ueventProcessRead: " |
| 269 | << "received uevent without required control message: ignoring."; |
| 270 | return; |
| 271 | } |
| 272 | |
| 273 | if (cmsg_header->cmsg_len != CMSG_LEN(sizeof(struct ucred)) |
| 274 | || cmsg_header->cmsg_level != SOL_SOCKET |
nothing calls this directly
no test coverage detected