param_selinux.c 7.9 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
#ifdef __aarch64__
#define CHECKER_LIB_NAME "/system/lib64/libparaperm_checker.z.so"
U
unknown 已提交
29
#define CHECKER_UPDATER_LIB_NAME "/lib64/libparaperm_checker.z.so"
M
Mupceet 已提交
30 31
#else
#define CHECKER_LIB_NAME "/system/lib/libparaperm_checker.z.so"
U
unknown 已提交
32
#define CHECKER_UPDATER_LIB_NAME "/lib/libparaperm_checker.z.so"
M
Mupceet 已提交
33 34
#endif

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

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

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

111
    int ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, readOnly, PARAM_WORKSPACE_MAX);
M
Mupceet 已提交
112
    PARAM_CHECK(ret == 0, return -1,
113
        "Failed to add selinux workspace %s %s", node->info.paraName, node->info.paraContext);
M
Mupceet 已提交
114
    return 0;
S
sun_fan 已提交
115 116
}

117 118 119 120 121 122
static int SelinuxGetParamSecurityLabel(const char *path)
{
    UNUSED(path);
    return SelinuxGetAllLabel(0);
}

S
sun_fan 已提交
123 124 125 126 127 128 129
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;
}

130 131
static int SelinuxReadParamCheck(const char *name)
{
132 133
    int ret = DAC_RESULT_FORBIDED;
    PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return ret, "Invalid getParamLabel");
134
    const char *label = g_selinuxSpace.getParamLabel(name);
135 136 137 138 139
    if (label == NULL) { // open file with readonly
        ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, 1, PARAM_WORKSPACE_MAX);
    } else {
        ret = AddWorkSpace(label, 1, PARAM_WORKSPACE_MAX);
    }
140 141 142 143 144 145
    if (ret != 0) {
        return DAC_RESULT_FORBIDED;
    }
    return DAC_RESULT_PERMISSION;
}

M
Mupceet 已提交
146
static int SelinuxCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
147
{
M
Mupceet 已提交
148 149 150 151 152 153 154 155 156 157
    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 {
L
laiguizhong 已提交
158
#ifndef STARTUP_INIT_TEST
159
        ret = SelinuxReadParamCheck(name);
L
laiguizhong 已提交
160 161 162
#else
        ret = g_selinuxSpace.readParamCheck(name);
#endif
M
Mupceet 已提交
163 164 165 166 167
    }
    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 已提交
168 169
}

M
Mupceet 已提交
170
int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
171 172
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
M
Mupceet 已提交
173
    int ret = strcpy_s(ops->name, sizeof(ops->name), "selinux");
S
sun_fan 已提交
174 175 176
    ops->securityGetLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
177
    ops->securityCheckParamPermission = SelinuxCheckParamPermission;
S
sun_fan 已提交
178 179
    ops->securityFreeLabel = FreeLocalSecurityLabel;
    if (isInit) {
M
Mupceet 已提交
180
        ops->securityGetLabel = SelinuxGetParamSecurityLabel;
S
sun_fan 已提交
181
    }
M
Mupceet 已提交
182
    return ret;
S
sun_fan 已提交
183
}
M
Mupceet 已提交
184

M
Mupceet 已提交
185
const char *GetSelinuxContent(const char *name)
M
Mupceet 已提交
186 187
{
    PARAM_CHECK(g_selinuxSpace.getParamLabel != NULL, return NULL, "Invalid getParamLabel");
M
Mupceet 已提交
188
    return g_selinuxSpace.getParamLabel(name);
M
Mupceet 已提交
189 190
}

191 192 193 194 195 196
void OpenPermissionWorkSpace(void)
{
    // open workspace by readonly
    SelinuxGetAllLabel(1);
}

M
Mupceet 已提交
197 198
#if defined STARTUP_INIT_TEST || defined LOCAL_TEST
void SetSelinuxOps(const SelinuxSpace *space)
S
sun_fan 已提交
199
{
M
Mupceet 已提交
200 201 202 203 204 205
    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 已提交
206 207
}
#endif