1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include <fcntl.h> 17d9f0492fSopenharmony_ci#include <unistd.h> 18d9f0492fSopenharmony_ci#include <sys/types.h> 19d9f0492fSopenharmony_ci#include <sys/socket.h> 20d9f0492fSopenharmony_ci 21d9f0492fSopenharmony_ci#include "beget_ext.h" 22d9f0492fSopenharmony_ci#include "control_fd.h" 23d9f0492fSopenharmony_ci#include "init_utils.h" 24d9f0492fSopenharmony_ci#include "securec.h" 25d9f0492fSopenharmony_ci 26d9f0492fSopenharmony_cistatic CmdService g_cmdService; 27d9f0492fSopenharmony_cistatic LoopHandle g_controlFdLoop = NULL; 28d9f0492fSopenharmony_ci 29d9f0492fSopenharmony_ciCallbackControlFdProcess g_controlFdFunc = NULL; 30d9f0492fSopenharmony_ci 31d9f0492fSopenharmony_cistatic void OnClose(const TaskHandle task) 32d9f0492fSopenharmony_ci{ 33d9f0492fSopenharmony_ci CmdTask *agent = (CmdTask *)LE_GetUserData(task); 34d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent"); 35d9f0492fSopenharmony_ci OH_ListRemove(&agent->item); 36d9f0492fSopenharmony_ci OH_ListInit(&agent->item); 37d9f0492fSopenharmony_ci} 38d9f0492fSopenharmony_ci 39d9f0492fSopenharmony_ciCONTROL_FD_STATIC int CheckSocketPermission(const TaskHandle task) 40d9f0492fSopenharmony_ci{ 41d9f0492fSopenharmony_ci struct ucred uc = {-1, -1, -1}; 42d9f0492fSopenharmony_ci socklen_t len = sizeof(uc); 43d9f0492fSopenharmony_ci if (getsockopt(LE_GetSocketFd(task), SOL_SOCKET, SO_PEERCRED, &uc, &len) < 0) { 44d9f0492fSopenharmony_ci BEGET_LOGE("Failed to get socket option. err = %d", errno); 45d9f0492fSopenharmony_ci return -1; 46d9f0492fSopenharmony_ci } 47d9f0492fSopenharmony_ci // Only root is permitted to use control fd of init. 48d9f0492fSopenharmony_ci if (uc.uid != 0) { // non-root user 49d9f0492fSopenharmony_ci errno = EPERM; 50d9f0492fSopenharmony_ci return -1; 51d9f0492fSopenharmony_ci } 52d9f0492fSopenharmony_ci return 0; 53d9f0492fSopenharmony_ci} 54d9f0492fSopenharmony_ci 55d9f0492fSopenharmony_ciCONTROL_FD_STATIC void CmdOnRecvMessage(const TaskHandle task, const uint8_t *buffer, uint32_t buffLen) 56d9f0492fSopenharmony_ci{ 57d9f0492fSopenharmony_ci if (buffer == NULL) { 58d9f0492fSopenharmony_ci return; 59d9f0492fSopenharmony_ci } 60d9f0492fSopenharmony_ci CmdTask *agent = (CmdTask *)LE_GetUserData(task); 61d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(agent != NULL, return, "[control_fd] Can not get agent"); 62d9f0492fSopenharmony_ci 63d9f0492fSopenharmony_ci // parse msg to exec 64d9f0492fSopenharmony_ci CmdMessage *msg = (CmdMessage *)buffer; 65d9f0492fSopenharmony_ci if ((msg->type >= ACTION_MAX) || (msg->cmd[0] == '\0') || (msg->ptyName[0] == '\0')) { 66d9f0492fSopenharmony_ci BEGET_LOGE("[control_fd] Received msg is invalid"); 67d9f0492fSopenharmony_ci return; 68d9f0492fSopenharmony_ci } 69d9f0492fSopenharmony_ci 70d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(CheckSocketPermission(task) >= 0, return, "Check socket permission failed, err = %d", errno); 71d9f0492fSopenharmony_ci 72d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 73d9f0492fSopenharmony_ci agent->pid = fork(); 74d9f0492fSopenharmony_ci if (agent->pid == 0) { 75d9f0492fSopenharmony_ci OpenConsole(); 76d9f0492fSopenharmony_ci char *realPath = GetRealPath(msg->ptyName); 77d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(realPath != NULL, _exit(1), "Failed get realpath, err=%d", errno); 78d9f0492fSopenharmony_ci int n = strncmp(realPath, "/dev/pts/", strlen("/dev/pts/")); 79d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(n == 0, free(realPath); _exit(1), "pts path %s is invaild", realPath); 80d9f0492fSopenharmony_ci int fd = open(realPath, O_RDWR); 81d9f0492fSopenharmony_ci free(realPath); 82d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(fd >= 0, _exit(1), "Failed open %s, err=%d", msg->ptyName, errno); 83d9f0492fSopenharmony_ci (void)dup2(fd, STDIN_FILENO); 84d9f0492fSopenharmony_ci (void)dup2(fd, STDOUT_FILENO); 85d9f0492fSopenharmony_ci (void)dup2(fd, STDERR_FILENO); // Redirect fd to 0, 1, 2 86d9f0492fSopenharmony_ci (void)close(fd); 87d9f0492fSopenharmony_ci if (g_controlFdFunc != NULL) { 88d9f0492fSopenharmony_ci g_controlFdFunc(msg->type, msg->cmd, NULL); 89d9f0492fSopenharmony_ci } 90d9f0492fSopenharmony_ci _exit(0); 91d9f0492fSopenharmony_ci } else if (agent->pid < 0) { 92d9f0492fSopenharmony_ci BEGET_LOGE("[control_fd] Failed to fork child process, err = %d", errno); 93d9f0492fSopenharmony_ci } 94d9f0492fSopenharmony_ci#endif 95d9f0492fSopenharmony_ci return; 96d9f0492fSopenharmony_ci} 97d9f0492fSopenharmony_ci 98d9f0492fSopenharmony_ciCONTROL_FD_STATIC int SendMessage(LoopHandle loop, TaskHandle task, const char *message) 99d9f0492fSopenharmony_ci{ 100d9f0492fSopenharmony_ci if (message == NULL) { 101d9f0492fSopenharmony_ci BEGET_LOGE("[control_fd] Invalid parameter"); 102d9f0492fSopenharmony_ci return -1; 103d9f0492fSopenharmony_ci } 104d9f0492fSopenharmony_ci BufferHandle handle = NULL; 105d9f0492fSopenharmony_ci uint32_t bufferSize = strlen(message) + 1; 106d9f0492fSopenharmony_ci handle = LE_CreateBuffer(loop, bufferSize); 107d9f0492fSopenharmony_ci char *buff = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize); 108d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(buff != NULL, return -1, "[control_fd] Failed get buffer info"); 109d9f0492fSopenharmony_ci int ret = memcpy_s(buff, bufferSize, message, strlen(message) + 1); 110d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret == 0, LE_FreeBuffer(g_controlFdLoop, task, handle); 111d9f0492fSopenharmony_ci return -1, "[control_fd] Failed memcpy_s err=%d", errno); 112d9f0492fSopenharmony_ci LE_STATUS status = LE_Send(loop, task, handle, strlen(message) + 1); 113d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(status == LE_SUCCESS, return -1, "[control_fd] Failed le send msg"); 114d9f0492fSopenharmony_ci return 0; 115d9f0492fSopenharmony_ci} 116d9f0492fSopenharmony_ci 117d9f0492fSopenharmony_ciCONTROL_FD_STATIC int CmdOnIncommingConnect(const LoopHandle loop, const TaskHandle server) 118d9f0492fSopenharmony_ci{ 119d9f0492fSopenharmony_ci TaskHandle client = NULL; 120d9f0492fSopenharmony_ci LE_StreamInfo info = {}; 121d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 122d9f0492fSopenharmony_ci info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; 123d9f0492fSopenharmony_ci#else 124d9f0492fSopenharmony_ci info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT | TASK_TEST; 125d9f0492fSopenharmony_ci#endif 126d9f0492fSopenharmony_ci info.baseInfo.close = OnClose; 127d9f0492fSopenharmony_ci info.baseInfo.userDataSize = sizeof(CmdTask); 128d9f0492fSopenharmony_ci info.disConnectComplete = NULL; 129d9f0492fSopenharmony_ci info.sendMessageComplete = NULL; 130d9f0492fSopenharmony_ci info.recvMessage = CmdOnRecvMessage; 131d9f0492fSopenharmony_ci int ret = LE_AcceptStreamClient(g_controlFdLoop, server, &client, &info); 132d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed accept stream") 133d9f0492fSopenharmony_ci CmdTask *agent = (CmdTask *)LE_GetUserData(client); 134d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(agent != NULL, return -1, "[control_fd] Invalid agent"); 135d9f0492fSopenharmony_ci agent->task = client; 136d9f0492fSopenharmony_ci OH_ListInit(&agent->item); 137d9f0492fSopenharmony_ci ret = SendMessage(g_controlFdLoop, agent->task, "connect success."); 138d9f0492fSopenharmony_ci BEGET_ERROR_CHECK(ret == 0, return -1, "[control_fd] Failed send msg"); 139d9f0492fSopenharmony_ci OH_ListAddTail(&g_cmdService.head, &agent->item); 140d9f0492fSopenharmony_ci return 0; 141d9f0492fSopenharmony_ci} 142d9f0492fSopenharmony_ci 143d9f0492fSopenharmony_civoid CmdServiceInit(const char *socketPath, CallbackControlFdProcess func, LoopHandle loop) 144d9f0492fSopenharmony_ci{ 145d9f0492fSopenharmony_ci if ((socketPath == NULL) || (func == NULL) || (loop == NULL)) { 146d9f0492fSopenharmony_ci BEGET_LOGE("[control_fd] Invalid parameter"); 147d9f0492fSopenharmony_ci return; 148d9f0492fSopenharmony_ci } 149d9f0492fSopenharmony_ci OH_ListInit(&g_cmdService.head); 150d9f0492fSopenharmony_ci LE_StreamServerInfo info = {}; 151d9f0492fSopenharmony_ci info.baseInfo.flags = TASK_STREAM | TASK_SERVER | TASK_PIPE; 152d9f0492fSopenharmony_ci info.server = (char *)socketPath; 153d9f0492fSopenharmony_ci info.socketId = -1; 154d9f0492fSopenharmony_ci info.baseInfo.close = NULL; 155d9f0492fSopenharmony_ci info.disConnectComplete = NULL; 156d9f0492fSopenharmony_ci info.incommingConnect = CmdOnIncommingConnect; 157d9f0492fSopenharmony_ci info.sendMessageComplete = NULL; 158d9f0492fSopenharmony_ci info.recvMessage = NULL; 159d9f0492fSopenharmony_ci g_controlFdFunc = func; 160d9f0492fSopenharmony_ci if (g_controlFdLoop == NULL) { 161d9f0492fSopenharmony_ci g_controlFdLoop = loop; 162d9f0492fSopenharmony_ci } 163d9f0492fSopenharmony_ci (void)LE_CreateStreamServer(g_controlFdLoop, &g_cmdService.serverTask, &info); 164d9f0492fSopenharmony_ci} 165d9f0492fSopenharmony_ci 166d9f0492fSopenharmony_cistatic int ClientTraversalProc(ListNode *node, void *data) 167d9f0492fSopenharmony_ci{ 168d9f0492fSopenharmony_ci CmdTask *info = ListEntry(node, CmdTask, item); 169d9f0492fSopenharmony_ci int pid = *(int *)data; 170d9f0492fSopenharmony_ci return pid - info->pid; 171d9f0492fSopenharmony_ci} 172d9f0492fSopenharmony_ci 173d9f0492fSopenharmony_civoid CmdServiceProcessDelClient(pid_t pid) 174d9f0492fSopenharmony_ci{ 175d9f0492fSopenharmony_ci ListNode *node = OH_ListFind(&g_cmdService.head, (void *)&pid, ClientTraversalProc); 176d9f0492fSopenharmony_ci if (node != NULL) { 177d9f0492fSopenharmony_ci CmdTask *agent = ListEntry(node, CmdTask, item); 178d9f0492fSopenharmony_ci OH_ListRemove(&agent->item); 179d9f0492fSopenharmony_ci OH_ListInit(&agent->item); 180d9f0492fSopenharmony_ci LE_CloseTask(g_controlFdLoop, agent->task); 181d9f0492fSopenharmony_ci } 182d9f0492fSopenharmony_ci} 183d9f0492fSopenharmony_ci 184d9f0492fSopenharmony_cistatic void CmdServiceDestroyProc(ListNode *node) 185d9f0492fSopenharmony_ci{ 186d9f0492fSopenharmony_ci if (node == NULL) { 187d9f0492fSopenharmony_ci return; 188d9f0492fSopenharmony_ci } 189d9f0492fSopenharmony_ci CmdTask *agent = ListEntry(node, CmdTask, item); 190d9f0492fSopenharmony_ci OH_ListRemove(&agent->item); 191d9f0492fSopenharmony_ci OH_ListInit(&agent->item); 192d9f0492fSopenharmony_ci LE_CloseTask(g_controlFdLoop, agent->task); 193d9f0492fSopenharmony_ci} 194d9f0492fSopenharmony_ci 195d9f0492fSopenharmony_civoid CmdServiceProcessDestroyClient(void) 196d9f0492fSopenharmony_ci{ 197d9f0492fSopenharmony_ci OH_ListRemoveAll(&g_cmdService.head, CmdServiceDestroyProc); 198d9f0492fSopenharmony_ci LE_StopLoop(g_controlFdLoop); 199d9f0492fSopenharmony_ci} 200