param_selinux.c 9.3 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
#include "param_base.h"
M
Mupceet 已提交
24 25
#ifdef PARAM_SUPPORT_SELINUX
#include "selinux_parameter.h"
M
Mupceet 已提交
26 27
#include <policycoreutils.h>
#include <selinux/selinux.h>
M
Mupceet 已提交
28
#endif
S
sun_fan 已提交
29

M
Mupceet 已提交
30 31
#ifdef __aarch64__
#define CHECKER_LIB_NAME "/system/lib64/libparaperm_checker.z.so"
U
unknown 已提交
32
#define CHECKER_UPDATER_LIB_NAME "/lib64/libparaperm_checker.z.so"
M
Mupceet 已提交
33 34
#else
#define CHECKER_LIB_NAME "/system/lib/libparaperm_checker.z.so"
U
unknown 已提交
35
#define CHECKER_UPDATER_LIB_NAME "/lib/libparaperm_checker.z.so"
M
Mupceet 已提交
36 37
#endif

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

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

M
Mupceet 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104
static void SetSelinuxFileCon(const char *name, const char *context)
{
    static char buffer[FILENAME_LEN_MAX] = {0};
    int len = ParamSprintf(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, context);
    if (len > 0) {
        buffer[len] = '\0';
        PARAM_LOGI("setfilecon name %s path: %s %s ", name, context, buffer);
        if (setfilecon(buffer, context) < 0) {
            PARAM_LOGE("Failed to setfilecon %s ", context);
        }
    }
}

105
static int SelinuxGetAllLabel(int readOnly)
S
sun_fan 已提交
106
{
M
Mupceet 已提交
107 108 109
    PARAM_CHECK(g_selinuxSpace.getParamList != NULL, return DAC_RESULT_FORBIDED, "Invalid getParamList");
    ParamContextsList *head = g_selinuxSpace.getParamList();
    ParamContextsList *node = head;
M
Mupceet 已提交
110

M
Mupceet 已提交
111 112 113 114 115
    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 已提交
116 117
            continue;
        }
118
        int ret = AddWorkSpace(node->info.paraContext, readOnly, PARAM_WORKSPACE_DEF);
M
Mupceet 已提交
119 120 121 122 123
        if (ret != 0) {
            PARAM_LOGE("Forbid to add selinux workspace %s %s", node->info.paraName, node->info.paraContext);
            node = node->next;
            continue;
        }
M
Mupceet 已提交
124
        count++;
M
Mupceet 已提交
125 126 127 128 129 130 131
        if (readOnly != 0) {
            node = node->next;
            continue;
        }
        // set selinx label
        SetSelinuxFileCon(node->info.paraName, node->info.paraContext);
        node = node->next;
4
411148299@qq.com 已提交
132
    }
M
Mupceet 已提交
133

134
    int ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, readOnly, PARAM_WORKSPACE_MAX);
M
Mupceet 已提交
135
    PARAM_CHECK(ret == 0, return -1,
M
Mupceet 已提交
136
        "Failed to add selinux workspace %s", WORKSPACE_NAME_DEF_SELINUX);
M
Mupceet 已提交
137 138 139
    if (readOnly == 0) {
        SetSelinuxFileCon(WORKSPACE_NAME_DEF_SELINUX, WORKSPACE_NAME_DEF_SELINUX);
    }
M
Mupceet 已提交
140
    PARAM_LOGI("SelinuxGetAllLabel count %d", count);
M
Mupceet 已提交
141
    return 0;
S
sun_fan 已提交
142 143
}

144 145 146 147 148 149
static int SelinuxGetParamSecurityLabel(const char *path)
{
    UNUSED(path);
    return SelinuxGetAllLabel(0);
}

S
sun_fan 已提交
150 151 152 153 154 155 156
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;
}

157 158
static int SelinuxReadParamCheck(const char *name)
{
159
    int ret = DAC_RESULT_FORBIDED;
M
Mupceet 已提交
160 161 162 163
    if (g_selinuxSpace.readParamCheck != NULL) {
        ret = g_selinuxSpace.readParamCheck(name);
        PARAM_LOGI("SelinuxReadParamCheck name %s ret %d", name, ret);
    }
M
Mupceet 已提交
164
    const char *label = GetSelinuxContent(name);
165 166 167
    if (label == NULL) { // open file with readonly
        ret = AddWorkSpace(WORKSPACE_NAME_DEF_SELINUX, 1, PARAM_WORKSPACE_MAX);
    } else {
M
Mupceet 已提交
168
        PARAM_LOGI("SelinuxReadParamCheck name %s label %s", name, label);
169 170
        ret = AddWorkSpace(label, 1, PARAM_WORKSPACE_MAX);
    }
171 172 173 174 175 176
    if (ret != 0) {
        return DAC_RESULT_FORBIDED;
    }
    return DAC_RESULT_PERMISSION;
}

M
Mupceet 已提交
177
static int SelinuxCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
S
sun_fan 已提交
178
{
M
Mupceet 已提交
179 180 181 182 183 184 185 186 187 188
    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 已提交
189
#ifndef STARTUP_INIT_TEST
190
        ret = SelinuxReadParamCheck(name);
L
laiguizhong 已提交
191 192 193
#else
        ret = g_selinuxSpace.readParamCheck(name);
#endif
M
Mupceet 已提交
194 195 196 197 198
    }
    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 已提交
199 200
}

M
Mupceet 已提交
201 202 203 204 205
static int UpdaterCheckParamPermission(const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
{
    return DAC_RESULT_PERMISSION;
}

M
Mupceet 已提交
206
INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
S
sun_fan 已提交
207 208
{
    PARAM_CHECK(ops != NULL, return -1, "Invalid param");
M
Mupceet 已提交
209
    int ret = ParamStrCpy(ops->name, sizeof(ops->name), "selinux");
S
sun_fan 已提交
210 211 212
    ops->securityGetLabel = NULL;
    ops->securityInitLabel = InitLocalSecurityLabel;
    ops->securityCheckFilePermission = CheckFilePermission;
M
Mupceet 已提交
213 214 215 216 217
    if (InUpdaterMode() == 1) {
        ops->securityCheckParamPermission = UpdaterCheckParamPermission;
    } else {
        ops->securityCheckParamPermission = SelinuxCheckParamPermission;
    }
S
sun_fan 已提交
218
    ops->securityFreeLabel = FreeLocalSecurityLabel;
219
    if (isInit != 0) {
M
Mupceet 已提交
220
        ops->securityGetLabel = SelinuxGetParamSecurityLabel;
S
sun_fan 已提交
221
    }
M
Mupceet 已提交
222
    return ret;
S
sun_fan 已提交
223
}
M
Mupceet 已提交
224

M
Mupceet 已提交
225
INIT_INNER_API const char *GetSelinuxContent(const char *name)
M
Mupceet 已提交
226
{
M
Mupceet 已提交
227 228 229 230 231 232
    if (g_selinuxSpace.getParamLabel != NULL) {
        return g_selinuxSpace.getParamLabel(name);
    } else {
        PARAM_LOGE("Can not init selinux");
        return WORKSPACE_NAME_DEF_SELINUX;
    }
M
Mupceet 已提交
233 234
}

M
Mupceet 已提交
235
INIT_LOCAL_API void OpenPermissionWorkSpace(void)
236 237 238 239 240
{
    // open workspace by readonly
    SelinuxGetAllLabel(1);
}

M
Mupceet 已提交
241 242
#if defined STARTUP_INIT_TEST || defined LOCAL_TEST
void SetSelinuxOps(const SelinuxSpace *space)
S
sun_fan 已提交
243
{
M
Mupceet 已提交
244 245 246 247 248 249
    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 已提交
250 251
}
#endif