1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 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 16#include <poll.h> 17#include <stdlib.h> 18#include <errno.h> 19#include <unistd.h> 20#include <sys/socket.h> 21#include <linux/netlink.h> 22#include "securec.h" 23#define INIT_LOG_TAG "ueventd" 24#include "init_log.h" 25 26#define UEVENT_SOCKET_BUFF_SIZE (256 * 1024) 27 28int UeventdSocketInit(void) 29{ 30 struct sockaddr_nl addr; 31 int buffSize = UEVENT_SOCKET_BUFF_SIZE; 32 int on = 1; 33 34 if (memset_s(&addr, sizeof(addr), 0, sizeof(addr)) != EOK) { 35 INIT_LOGE("Failed to clear socket address"); 36 return -1; 37 } 38 addr.nl_family = AF_NETLINK; 39 addr.nl_pid = getpid(); 40 addr.nl_groups = 0xffffffff; 41 42 int sockfd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT); 43 if (sockfd < 0) { 44 INIT_LOGE("Create socket failed, err = %d", errno); 45 return -1; 46 } 47 48 setsockopt(sockfd, SOL_SOCKET, SO_RCVBUFFORCE, &buffSize, sizeof(buffSize)); 49 setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); 50 51 if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 52 INIT_LOGE("Bind socket failed, err = %d", errno); 53#ifndef STARTUP_INIT_TEST 54 close(sockfd); 55 return -1; 56#endif 57 } 58 return sockfd; 59} 60 61ssize_t ReadUeventMessage(int sockFd, char *buffer, size_t length) 62{ 63 ssize_t n = -1; 64 struct msghdr msghdr = {}; 65 struct iovec iov; 66 struct sockaddr_nl addr; 67 char credMsg[CMSG_SPACE(sizeof(struct ucred))]; 68 69 // sanity check 70 if (sockFd < 0 || buffer == NULL) { 71 return n; 72 } 73 74 iov.iov_base = buffer; 75 iov.iov_len = length; 76 msghdr.msg_name = &addr; 77 msghdr.msg_namelen = sizeof(addr); 78 msghdr.msg_iov = &iov; 79 msghdr.msg_iovlen = 1; 80 msghdr.msg_control = credMsg; 81 msghdr.msg_controllen = sizeof(credMsg); 82 83 n = recvmsg(sockFd, &msghdr, 0); 84 if (n <= 0) { 85 return n; 86 } 87 struct cmsghdr *cmsghdr = CMSG_FIRSTHDR(&msghdr); 88 if (cmsghdr == NULL || cmsghdr->cmsg_type != SCM_CREDENTIALS) { 89 INIT_LOGE("Unexpected control message, ignored"); 90 // Drop this message 91 *buffer = '\0'; 92 n = -1; 93 } 94 return n; 95} 96