param_selinux.c 7.5 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 29 30 31 32
#ifdef __aarch64__
#define CHECKER_LIB_NAME "/system/lib64/libparaperm_checker.z.so"
#else
#define CHECKER_LIB_NAME "/system/lib/libparaperm_checker.z.so"
#endif

M
Mupceet 已提交
33 34
static SelinuxSpace g_selinuxSpace = {0};
static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
S
sun_fan 已提交
35 36
{
    UNUSED(isInit);
M
Mupceet 已提交
37 38 39 40 41 42 43
    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) {
M
Mupceet 已提交
44
        g_selinuxSpace.selinuxHandle = dlopen(CHECKER_LIB_NAME, RTLD_LAZY);
M
Mupceet 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58
        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 已提交
59
        g_selinuxSpace.getParamList = (ParamContextsList *(*)()) dlsym(handle, "GetParamList");
M
Mupceet 已提交
60 61 62
        PARAM_CHECK(g_selinuxSpace.getParamList != NULL, return -1, "Failed to dlsym getParamList %s", dlerror());
    }
    if (g_selinuxSpace.getParamLabel == NULL) {
M
Mupceet 已提交
63
        g_selinuxSpace.getParamLabel = (const char * (*)(const char *))dlsym(handle, "GetParamLabel");
M
Mupceet 已提交
64 65 66 67 68 69 70 71 72 73 74 75
        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());
    }
76
    if (isInit) { // log
L
laiguizhong 已提交
77 78
        g_selinuxSpace.setSelinuxLogCallback();
    }
M
Mupceet 已提交
79 80
#endif
    PARAM_LOGV("Load sulinux lib success.");
S
sun_fan 已提交
81 82 83 84 85 86 87 88
    return 0;
}

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

89
static int SelinuxGetAllLabel(int readOnly)
S
sun_fan 已提交
90
{
M
Mupceet 已提交
91 92 93 94 95 96 97 98
    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 已提交
99 100
            continue;
        }
101
        int ret = AddWorkSpace(node->info.paraContext, readOnly, PARAM_WORKSPACE_DEF);
M
Mupceet 已提交
102
        PARAM_CHECK(ret == 0, continue,
103
            "Failed to add selinux workspace %s %s", node->info.paraName, node->info.paraContext);
M
Mupceet 已提交
104 105
        node = node->next;
        count++;
4
411148299@qq.com 已提交
106
    }
M
Mupceet 已提交
107
    g_selinuxSpace.destroyParamList(&head);
108
    int ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, readOnly, PARAM_WORKSPACE_MAX);
M
Mupceet 已提交
109
    PARAM_CHECK(ret == 0, return -1,
110
        "Failed to add selinux workspace %s %s", node->info.paraName, node->info.paraContext);
M
Mupceet 已提交
111
    return 0;
S
sun_fan 已提交
112 113
}

114 115 116 117 118 119
static int SelinuxGetParamSecurityLabel(const char *path)
{
    UNUSED(path);
    return SelinuxGetAllLabel(0);
}

S
sun_fan 已提交
120 121 122 123 124 125 126
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;
}

127 128 129 130 131 132 133 134 135 136 137 138
static int SelinuxReadParamCheck(const char *name)
{
    PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return NULL, "Invalid getParamLabel");
    const char *label = g_selinuxSpace.getParamLabel(name);
    // open file with readonly
    int ret = AddWorkSpace(label, 1, PARAM_WORKSPACE_MAX);
    if (ret != 0) {
        return DAC_RESULT_FORBIDED;
    }
    return DAC_RESULT_PERMISSION;
}

M
Mupceet 已提交
139
static int SelinuxCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
140
{
M
Mupceet 已提交
141 142 143 144 145 146 147 148 149 150
    int ret = DAC_RESULT_FORBIDED;
    PARAM_CHECK(g_selinuxSpace.setParamCheck != NULL, return ret, "Invalid setParamCheck");
    // 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 {
151
        ret = SelinuxReadParamCheck(name);
M
Mupceet 已提交
152 153 154 155 156
    }
    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 已提交
157 158
}

M
Mupceet 已提交
159
int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
160 161
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
M
Mupceet 已提交
162
    int ret = strcpy_s(ops->name, sizeof(ops->name), "selinux");
S
sun_fan 已提交
163 164 165
    ops->securityGetLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
166
    ops->securityCheckParamPermission = SelinuxCheckParamPermission;
S
sun_fan 已提交
167 168
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
M
Mupceet 已提交
169
        ops->securityGetLabel = SelinuxGetParamSecurityLabel;
S
sun_fan 已提交
170
    }
M
Mupceet 已提交
171
    return ret;
S
sun_fan 已提交
172
}
M
Mupceet 已提交
173

M
Mupceet 已提交
174
const char *GetSelinuxContent(const char *name)
M
Mupceet 已提交
175 176
{
    PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return NULL, "Invalid getParamLabel");
M
Mupceet 已提交
177
    return g_selinuxSpace.getParamLabel(name);
M
Mupceet 已提交
178 179
}

180 181 182 183 184 185
void OpenPermissionWorkSpace(void)
{
    // open workspace by readonly
    SelinuxGetAllLabel(1);
}

M
Mupceet 已提交
186 187
#if defined STARTUP_INIT_TEST || defined LOCAL_TEST
void SetSelinuxOps(const SelinuxSpace *space)
S
sun_fan 已提交
188
{
M
Mupceet 已提交
189 190 191 192 193 194
    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 已提交
195 196
}
#endif