param_selinux.c 7.6 KB
Newer Older
S
sun_fan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
M
Mupceet 已提交
15
#include <dlfcn.h>
S
sun_fan 已提交
16
#include <sys/stat.h>
M
Mupceet 已提交
17
#include <sys/socket.h>
S
sun_fan 已提交
18

19
#include "init_utils.h"
M
Mupceet 已提交
20
#include "param_manager.h"
S
sun_fan 已提交
21 22
#include "param_security.h"
#include "param_utils.h"
M
Mupceet 已提交
23 24 25
#ifdef PARAM_SUPPORT_SELINUX
#include "selinux_parameter.h"
#endif
S
sun_fan 已提交
26

M
Mupceet 已提交
27 28
static SelinuxSpace g_selinuxSpace = {0};
static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
S
sun_fan 已提交
29 30
{
    UNUSED(isInit);
M
Mupceet 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
    PARAM_CHECK(security != NULL, return -1, "Invalid security");
    security->cred.pid = getpid();
    security->cred.uid = geteuid();
    security->cred.gid = getegid();
    security->flags[PARAM_SECURITY_SELINUX] = 0;
#if !(defined STARTUP_INIT_TEST || defined LOCAL_TEST)
    if (g_selinuxSpace.selinuxHandle == NULL) {
        g_selinuxSpace.selinuxHandle = dlopen("/system/lib/libparaperm_checker.z.so", RTLD_LAZY);
        PARAM_CHECK(g_selinuxSpace.selinuxHandle != NULL,
            return -1, "Failed to dlsym selinuxHandle, %s", dlerror());
    }
    void *handle = g_selinuxSpace.selinuxHandle;
    if (g_selinuxSpace.setSelinuxLogCallback == NULL) {
        g_selinuxSpace.setSelinuxLogCallback = (void (*)())dlsym(handle, "SetSelinuxLogCallback");
        PARAM_CHECK(g_selinuxSpace.setSelinuxLogCallback != NULL,
            return -1, "Failed to dlsym setSelinuxLogCallback %s", dlerror());
    }
    if (g_selinuxSpace.setParamCheck == NULL) {
        g_selinuxSpace.setParamCheck = (SelinuxSetParamCheck)dlsym(handle, "SetParamCheck");
        PARAM_CHECK(g_selinuxSpace.setParamCheck != NULL, return -1, "Failed to dlsym setParamCheck %s", dlerror());
    }
    if (g_selinuxSpace.getParamList == NULL) {
M
Mupceet 已提交
53
        g_selinuxSpace.getParamList = (ParamContextsList *(*)()) dlsym(handle, "GetParamList");
M
Mupceet 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        PARAM_CHECK(g_selinuxSpace.getParamList != NULL, return -1, "Failed to dlsym getParamList %s", dlerror());
    }
    if (g_selinuxSpace.getParamLabel == NULL) {
        g_selinuxSpace.getParamLabel = (int (*)(const char *, char **))dlsym(handle, "GetParamLabel");
        PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return -1, "Failed to dlsym getParamLabel %s", dlerror());
    }
    if (g_selinuxSpace.readParamCheck == NULL) {
        g_selinuxSpace.readParamCheck = (int (*)(const char *))dlsym(handle, "ReadParamCheck");
        PARAM_CHECK(g_selinuxSpace.readParamCheck != NULL, return -1, "Failed to dlsym readParamCheck %s", dlerror());
    }
    if (g_selinuxSpace.destroyParamList == NULL) {
        g_selinuxSpace.destroyParamList =
            (void (*)(ParamContextsList **))dlsym(handle, "DestroyParamList");
        PARAM_CHECK(g_selinuxSpace.destroyParamList != NULL,
            return -1, "Failed to dlsym destroyParamList %s", dlerror());
    }
#endif
    PARAM_LOGV("Load sulinux lib success.");
S
sun_fan 已提交
72 73 74 75 76 77 78 79
    return 0;
}

static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
{
    return 0;
}

M
Mupceet 已提交
80
static int SelinuxGetParamSecurityLabel(const char *path)
S
sun_fan 已提交
81
{
M
Mupceet 已提交
82 83 84 85 86 87 88 89 90
    UNUSED(path);
    PARAM_CHECK(g_selinuxSpace.getParamList != NULL, return DAC_RESULT_FORBIDED, "Invalid getParamList");
    ParamContextsList *head = g_selinuxSpace.getParamList();
    ParamContextsList *node = head;
    int count = 0;
    while (node != NULL) {
        PARAM_LOGV("GetParamSecurityLabel name %s content %s", node->info.paraName, node->info.paraContext);
        if (node->info.paraContext == NULL || node->info.paraName == NULL) {
            node = node->next;
S
sun_fan 已提交
91 92
            continue;
        }
M
Mupceet 已提交
93 94 95 96 97
        int ret = AddWorkSpace(node->info.paraContext, 0, PARAM_WORKSPACE_DEF);
        PARAM_CHECK(ret == 0, continue,
            "Failed to add selinx workspace %s %s", node->info.paraName, node->info.paraContext);
        node = node->next;
        count++;
4
411148299@qq.com 已提交
98
    }
M
Mupceet 已提交
99 100 101 102
    g_selinuxSpace.destroyParamList(&head);
    int ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, 0, PARAM_WORKSPACE_MAX);
    PARAM_CHECK(ret == 0, return -1,
        "Failed to add selinx workspace %s %s", node->info.paraName, node->info.paraContext);
S
sun_fan 已提交
103

M
Mupceet 已提交
104
    return 0;
S
sun_fan 已提交
105 106 107 108 109 110 111 112 113
}

static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
{
    UNUSED(flags);
    PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param");
    return 0;
}

M
Mupceet 已提交
114
static int SelinuxCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
115
{
M
Mupceet 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
    int ret = DAC_RESULT_FORBIDED;
    PARAM_CHECK(g_selinuxSpace.setSelinuxLogCallback != NULL, return ret, "Invalid setSelinuxLogCallback");
    PARAM_CHECK(g_selinuxSpace.setParamCheck != NULL, return ret, "Invalid setParamCheck");
    PARAM_CHECK(g_selinuxSpace.readParamCheck != NULL, return ret, "Invalid readParamCheck");
    // log
    g_selinuxSpace.setSelinuxLogCallback();

    // check
    struct ucred uc;
    uc.pid = srcLabel->cred.pid;
    uc.uid = srcLabel->cred.uid;
    uc.gid = srcLabel->cred.gid;
    if (mode == DAC_WRITE) {
        ret = g_selinuxSpace.setParamCheck(name, &uc);
    } else {
        ret = g_selinuxSpace.readParamCheck(name);
    }
    if (ret != 0) {
        PARAM_LOGI("Selinux check name %s pid %d uid %d %d result %d", name, uc.pid, uc.uid, uc.gid, ret);
    }
    return ret;
S
sun_fan 已提交
137 138
}

M
Mupceet 已提交
139
int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
140 141
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
M
Mupceet 已提交
142
    int ret = strcpy_s(ops->name, sizeof(ops->name), "selinux");
S
sun_fan 已提交
143 144 145
    ops->securityGetLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
146
    ops->securityCheckParamPermission = SelinuxCheckParamPermission;
S
sun_fan 已提交
147 148
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
M
Mupceet 已提交
149
        ops->securityGetLabel = SelinuxGetParamSecurityLabel;
S
sun_fan 已提交
150
    }
M
Mupceet 已提交
151
    return ret;
S
sun_fan 已提交
152
}
M
Mupceet 已提交
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

const char *GetSelinuxContent(const char *name, char *buffer, uint32_t size)
{
    PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return NULL, "Invalid getParamLabel");
    PARAM_CHECK(g_selinuxSpace.setSelinuxLogCallback != NULL, return NULL, "Invalid setSelinuxLogCallback");
    // log
    g_selinuxSpace.setSelinuxLogCallback();

    char *label = NULL;
    int ret = g_selinuxSpace.getParamLabel(name, &label);
    if (ret == 0 && label != NULL) {
        if (strcpy_s(buffer, size, label) == 0) {
            free(label);
            PARAM_LOGV("GetSelinuxContent name %s label %s", name, buffer);
            return buffer;
        }
        free(label);
    }
    PARAM_LOGE("Failed to get content for name %s ret %d", name, ret);
    strcpy_s(buffer, size, WORKSPACE_NAME_DEF_SELINUX);
    return buffer;
}

#if defined STARTUP_INIT_TEST || defined LOCAL_TEST
void SetSelinuxOps(const SelinuxSpace *space)
S
sun_fan 已提交
178
{
M
Mupceet 已提交
179 180 181 182 183 184
    g_selinuxSpace.setSelinuxLogCallback = space->setSelinuxLogCallback;
    g_selinuxSpace.setParamCheck = space->setParamCheck;
    g_selinuxSpace.getParamLabel = space->getParamLabel;
    g_selinuxSpace.readParamCheck = space->readParamCheck;
    g_selinuxSpace.getParamList = space->getParamList;
    g_selinuxSpace.destroyParamList = space->destroyParamList;
S
sun_fan 已提交
185 186
}
#endif