/* * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors may be used * to endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "mqueue.h" #include #include #include #include "time_posix.h" #include "user_copy.h" #include "los_signal.h" #include "los_strncpy_from_user.h" #include "fs/file.h" #define MQUEUE_FD_U2K(id) \ do { \ int sysFd = GetAssociatedSystemFd((INTPTR)(id)); \ (id) = (mqd_t)sysFd; \ } while (0) #define MQUEUE_FD_K2U(id) \ do { \ int procFd = AllocAndAssocProcessFd((INTPTR)(id), MIN_START_FD); \ if (procFd == -1) { \ mq_close(id); \ set_errno(EMFILE); \ (id) = (mqd_t)(-EMFILE); \ } else { \ (id) = (mqd_t)procFd; \ } \ } while (0) mqd_t SysMqOpen(const char *mqName, int openFlag, mode_t mode, struct mq_attr *attr) { mqd_t ret; int retValue; char kMqName[PATH_MAX + 1] = { 0 }; retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); if (retValue < 0) { return retValue; } ret = mq_open(kMqName, openFlag, mode, attr); if (ret == -1) { return (mqd_t)-get_errno(); } /* SysFd to procFd */ MQUEUE_FD_K2U(ret); return ret; } int SysMqClose(mqd_t personal) { int ret; MQUEUE_FD_U2K(personal); ret = mq_close(personal); if (ret < 0) { return -get_errno(); } return ret; } int SysMqGetSetAttr(mqd_t mqd, const struct mq_attr *new, struct mq_attr *old) { int ret; struct mq_attr knew, kold; if (new != NULL) { ret = LOS_ArchCopyFromUser(&knew, new, sizeof(struct mq_attr)); if (ret != 0) { return -EFAULT; } } MQUEUE_FD_U2K(mqd); ret = mq_getsetattr(mqd, new ? &knew : NULL, old ? &kold : NULL); if (ret < 0) { return -get_errno(); } if (old != NULL) { ret = LOS_ArchCopyToUser(old, &kold, sizeof(struct mq_attr)); if (ret != 0) { return -EFAULT; } } return ret; } int SysMqUnlink(const char *mqName) { int ret; int retValue; char kMqName[PATH_MAX + 1] = { 0 }; retValue = LOS_StrncpyFromUser(kMqName, mqName, PATH_MAX); if (retValue < 0) { return retValue; } ret = mq_unlink(kMqName); if (ret < 0) { return -get_errno(); } return ret; } int SysMqTimedSend(mqd_t personal, const char *msg, size_t msgLen, unsigned int msgPrio, const struct timespec *absTimeout) { int ret; struct timespec timeout; char *msgIntr = NULL; if (absTimeout != NULL) { ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); if (ret != 0) { return -EFAULT; } } if (msgLen == 0) { return -EINVAL; } msgIntr = (char *)malloc(msgLen); if (msgIntr == NULL) { return -ENOMEM; } ret = LOS_ArchCopyFromUser(msgIntr, msg, msgLen); if (ret != 0) { free(msgIntr); return -EFAULT; } MQUEUE_FD_U2K(personal); ret = mq_timedsend(personal, msgIntr, msgLen, msgPrio, absTimeout ? &timeout : NULL); free(msgIntr); if (ret < 0) { return -get_errno(); } return ret; } ssize_t SysMqTimedReceive(mqd_t personal, char *msg, size_t msgLen, unsigned int *msgPrio, const struct timespec *absTimeout) { int ret, receiveLen; struct timespec timeout; char *msgIntr = NULL; unsigned int kMsgPrio; if (absTimeout != NULL) { ret = LOS_ArchCopyFromUser(&timeout, absTimeout, sizeof(struct timespec)); if (ret != 0) { return -EFAULT; } } if (msgLen == 0) { return -EINVAL; } msgIntr = (char *)malloc(msgLen); if (msgIntr == NULL) { return -ENOMEM; } MQUEUE_FD_U2K(personal); receiveLen = mq_timedreceive(personal, msgIntr, msgLen, &kMsgPrio, absTimeout ? &timeout : NULL); if (receiveLen < 0) { free(msgIntr); return -get_errno(); } if (msgPrio != NULL) { ret = LOS_ArchCopyToUser(msgPrio, &kMsgPrio, sizeof(unsigned int)); if (ret != 0) { free(msgIntr); return -EFAULT; } } ret = LOS_ArchCopyToUser(msg, msgIntr, receiveLen); free(msgIntr); if (ret != 0) { return -EFAULT; } return receiveLen; } int SysSigAction(int sig, const sigaction_t *restrict sa, sigaction_t *restrict old, size_t sigsetsize) { return OsSigAction(sig, sa, old); } int SysSigprocMask(int how, const sigset_t_l *restrict setl, sigset_t_l *restrict oldl, size_t sigsetsize) { /* Let nxsig_procmask do all of the work */ return OsSigprocMask(how, setl, oldl); } int SysKill(pid_t pid, int sig) { return OsKillLock(pid, sig); } int SysPthreadKill(pid_t pid, int sig) { return OsPthreadKill(pid, sig); } int SysSigTimedWait(const sigset_t_l *setl, siginfo_t *info, const struct timespec *timeout, size_t sigsetsize) { sigset_t set; unsigned int tick; int retVal, ret; siginfo_t infoIntr; struct timespec timeoutIntr; retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); if (retVal != 0) { return -EFAULT; } if (timeout == NULL) { tick = LOS_WAIT_FOREVER; } else { retVal = LOS_ArchCopyFromUser(&timeoutIntr, timeout, sizeof(struct timespec)); if (retVal != 0) { return -EFAULT; } if (!ValidTimeSpec(&timeoutIntr)) { return -EINVAL; } tick = OsTimeSpec2Tick(&timeoutIntr); } ret = OsSigTimedWait(&set, &infoIntr, tick); if (ret < 0) { return ret; } if (info != NULL) { retVal = LOS_ArchCopyToUser(info, &infoIntr, sizeof(siginfo_t)); if (retVal != 0) { return -EFAULT; } } return (ret == 0 ? infoIntr.si_signo : ret); } int SysPause(void) { return OsPause(); } int SysSigPending(sigset_t_l *setl) { sigset_t set; int ret; ret = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); if (ret != 0) { return -EFAULT; } ret = OsSigPending(&set); if (ret != LOS_OK) { return ret; } ret = LOS_ArchCopyToUser(&(setl->sig[0]), &set, sizeof(sigset_t)); if (ret != LOS_OK) { return -EFAULT; } return ret; } int SysSigSuspend(sigset_t_l *setl) { sigset_t set; int retVal; retVal = LOS_ArchCopyFromUser(&set, &(setl->sig[0]), sizeof(sigset_t)); if (retVal != 0) { return -EFAULT; } return OsSigSuspend(&set); } #ifdef LOSCFG_KERNEL_PIPE int SysMkFifo(const char *pathName, mode_t mode) { int retValue; char kPathName[PATH_MAX + 1] = { 0 }; retValue = LOS_StrncpyFromUser(kPathName, pathName, PATH_MAX); if (retValue < 0) { return retValue; } return mkfifo(kPathName, mode); } #endif