• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <errno.h>
16 #include <dlfcn.h>
17 #include <sys/socket.h>
18 
19 #include "init_utils.h"
20 #include "param_manager.h"
21 #include "param_security.h"
22 #include "param_utils.h"
23 #include "param_base.h"
24 #ifdef PARAM_SUPPORT_SELINUX
25 #include "selinux_parameter.h"
26 #endif
27 
28 #if defined (__aarch64__) || defined(__x86_64__) || (defined(__riscv) && __riscv_xlen == 64)
29 #define CHECKER_LIB_NAME "/system/lib64/libparaperm_checker.z.so"
30 #define CHECKER_UPDATER_LIB "/lib64/libparaperm_checker.z.so"
31 #else
32 #define CHECKER_LIB_NAME "/system/lib/libparaperm_checker.z.so"
33 #define CHECKER_UPDATER_LIB "/lib/libparaperm_checker.z.so"
34 #endif
35 typedef int (*SelinuxSetParamCheck)(const char *paraName, const char *destContext, const SrcInfo *info);
36 
37 #if !(defined STARTUP_INIT_TEST || defined LOCAL_TEST)
InitSelinuxOpsForInit(SelinuxSpace * selinuxSpace)38 static int InitSelinuxOpsForInit(SelinuxSpace *selinuxSpace)
39 {
40     if (selinuxSpace->selinuxHandle == NULL) {
41         const char *libname = (GetParamWorkSpace()->ops.updaterMode == 1) ? CHECKER_UPDATER_LIB : CHECKER_LIB_NAME;
42         selinuxSpace->selinuxHandle = dlopen(libname, RTLD_LAZY);
43         PARAM_CHECK(selinuxSpace->selinuxHandle != NULL,
44             return 0, "Failed to dlsym selinuxHandle, %s", dlerror());
45     }
46     void *handle = selinuxSpace->selinuxHandle;
47     if (selinuxSpace->setParamCheck == NULL) {
48         selinuxSpace->setParamCheck = (SelinuxSetParamCheck)dlsym(handle, "SetParamCheck");
49         PARAM_CHECK(selinuxSpace->setParamCheck != NULL, return -1, "Failed to dlsym setParamCheck %s", dlerror());
50     }
51     if (selinuxSpace->getParamList == NULL) {
52         selinuxSpace->getParamList = (ParamContextsList *(*)()) dlsym(handle, "GetParamList");
53         PARAM_CHECK(selinuxSpace->getParamList != NULL, return -1, "Failed to dlsym getParamList %s", dlerror());
54     }
55     if (selinuxSpace->getParamLabel == NULL) {
56         selinuxSpace->getParamLabel = (const char *(*)(const char *))dlsym(handle, "GetParamLabel");
57         PARAM_CHECK(selinuxSpace->getParamLabel != NULL, return -1, "Failed to dlsym getParamLabel %s", dlerror());
58     }
59     if (selinuxSpace->initParamSelinux == NULL) {
60         selinuxSpace->initParamSelinux = (int (*)(int))dlsym(handle, "InitParamSelinux");
61         PARAM_CHECK(selinuxSpace->initParamSelinux != NULL, return -1, "Failed to dlsym initParamSelinux ");
62     }
63     if (selinuxSpace->getParamLabelIndex == NULL) {
64         selinuxSpace->getParamLabelIndex = (int (*)(const char *))dlsym(handle, "GetParamLabelIndex");
65         PARAM_CHECK(selinuxSpace->getParamLabelIndex != NULL, return -1, "Failed to dlsym getParamLabelIndex ");
66     }
67     if (selinuxSpace->setSelinuxLogCallback == NULL) {
68         selinuxSpace->setSelinuxLogCallback = (void (*)())dlsym(handle, "SetInitSelinuxLog");
69     }
70     if (selinuxSpace->destroyParamList == NULL) {
71         selinuxSpace->destroyParamList =
72             (void (*)(ParamContextsList **))dlsym(handle, "DestroyParamList");
73         PARAM_CHECK(selinuxSpace->destroyParamList != NULL,
74             return -1, "Failed to dlsym destroyParamList %s", dlerror());
75     }
76 
77     // init and open avc log
78     int ret = selinuxSpace->initParamSelinux(1);
79     if (selinuxSpace->setSelinuxLogCallback != NULL) {
80         selinuxSpace->setSelinuxLogCallback();
81     }
82     return ret;
83 }
84 #endif
85 
InitLocalSecurityLabel(ParamSecurityLabel * security,int isInit)86 static int InitLocalSecurityLabel(ParamSecurityLabel *security, int isInit)
87 {
88     PARAM_CHECK(GetParamWorkSpace() != NULL, return -1, "Invalid workspace");
89     UNUSED(isInit);
90     PARAM_CHECK(security != NULL, return -1, "Invalid security");
91     security->cred.pid = getpid();
92     security->cred.uid = geteuid();
93     security->cred.gid = getegid();
94     security->flags[PARAM_SECURITY_SELINUX] = 0;
95     PARAM_LOGV("InitLocalSecurityLabel");
96 #if !(defined STARTUP_INIT_TEST || defined LOCAL_TEST)
97     if ((bool)isInit) {
98         int ret = InitSelinuxOpsForInit(&GetParamWorkSpace()->selinuxSpace);
99         PARAM_CHECK(ret == 0, return -1, "Failed to init selinux ops");
100     } else {
101         SelinuxSpace *selinuxSpace = &GetParamWorkSpace()->selinuxSpace;
102         selinuxSpace->initParamSelinux = InitParamSelinux;
103         selinuxSpace->getParamList = GetParamList;
104         selinuxSpace->getParamLabel = GetParamLabel;
105         selinuxSpace->destroyParamList = DestroyParamList;
106         selinuxSpace->getParamLabelIndex = GetParamLabelIndex;
107         // init
108         selinuxSpace->initParamSelinux(isInit);
109     }
110 #endif
111     PARAM_LOGV("Load selinux lib success.");
112     return 0;
113 }
114 
FreeLocalSecurityLabel(ParamSecurityLabel * srcLabel)115 static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
116 {
117     return 0;
118 }
119 
SetSelinuxFileCon(const char * name,const char * context)120 static void SetSelinuxFileCon(const char *name, const char *context)
121 {
122     PARAM_CHECK(GetParamWorkSpace() != NULL && GetParamWorkSpace()->ops.setfilecon != NULL,
123         return, "Invalid workspace or setfilecon");
124     static char buffer[FILENAME_LEN_MAX] = {0};
125     int len = PARAM_SPRINTF(buffer, sizeof(buffer), "%s/%s", PARAM_STORAGE_PATH, context);
126     if (len > 0) {
127         buffer[len] = '\0';
128         PARAM_LOGV("setfilecon name %s path: %s %s ", name, context, buffer);
129         if (GetParamWorkSpace()->ops.setfilecon(buffer, context) < 0) {
130             PARAM_LOGE("Failed to setfilecon %s ", context);
131         }
132     }
133 }
134 
HandleSelinuxLabelForOpen(const ParameterNode * paramNode,int readOnly)135 static void HandleSelinuxLabelForOpen(const ParameterNode *paramNode, int readOnly)
136 {
137     uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE;
138     int ret = OpenWorkSpace(labelIndex, readOnly);
139     if (ret != 0) {
140         PARAM_LOGE("Forbid to add selinux workspace %s %s", paramNode->paraName, paramNode->paraContext);
141         return;
142     }
143     if (!readOnly) {
144         // set selinux label
145         SetSelinuxFileCon(paramNode->paraName, paramNode->paraContext);
146     }
147 }
148 
HandleSelinuxLabelForInit(const ParameterNode * paramNode,int readOnly)149 static void HandleSelinuxLabelForInit(const ParameterNode *paramNode, int readOnly)
150 {
151     uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE;
152     int ret = AddWorkSpace(paramNode->paraContext, labelIndex, readOnly, 0);
153     PARAM_CHECK(ret == 0, return, "Not enough memory for %s", paramNode->paraContext);
154 
155     ParamWorkSpace *paramSpace = GetParamWorkSpace();
156     PARAM_CHECK(paramSpace != NULL, return, "Invalid workspace");
157     if (paramSpace->maxLabelIndex < labelIndex) {
158         paramSpace->maxLabelIndex = labelIndex;
159     }
160 }
161 
SelinuxGetAllLabel(int readOnly,void (* handleSelinuxLabel)(const ParameterNode * paramNode,int readOnly))162 int SelinuxGetAllLabel(int readOnly,
163     void (*handleSelinuxLabel)(const ParameterNode *paramNode, int readOnly))
164 {
165     SelinuxSpace *selinuxSpace = &GetParamWorkSpace()->selinuxSpace;
166     PARAM_CHECK(selinuxSpace->getParamList != NULL, return DAC_RESULT_FORBIDED, "Invalid getParamList");
167     ParamContextsList *node = selinuxSpace->getParamList();
168     int count = 0;
169     while (node != NULL) {
170         PARAM_LOGV("SelinuxGetAllLabel index %d name %s content %s",
171             node->info.index, node->info.paraName, node->info.paraContext);
172         if (node->info.paraContext == NULL || node->info.paraName == NULL) {
173             node = node->next;
174             continue;
175         }
176         handleSelinuxLabel(&node->info, readOnly);
177         count++;
178         node = node->next;
179     }
180     ParameterNode tmpNode = {WORKSPACE_NAME_DEF_SELINUX, WORKSPACE_NAME_DEF_SELINUX, 0};
181     handleSelinuxLabel(&tmpNode, readOnly);
182     PARAM_LOGV("Selinux get all label counts %d.", count);
183     return 0;
184 }
185 
HandleSelinuxLabelForPermission(const ParameterNode * paramNode,int readOnly)186 static void HandleSelinuxLabelForPermission(const ParameterNode *paramNode, int readOnly)
187 {
188     uint32_t labelIndex = paramNode->index + WORKSPACE_INDEX_BASE;
189     if (labelIndex == WORKSPACE_INDEX_BASE) {
190         return;
191     }
192     if (*(paramNode->paraName + strlen(paramNode->paraName) - 1) != '.') {
193         return;
194     }
195     // save selinux index
196     ParamWorkSpace *paramWorkspace = GetParamWorkSpace();
197     PARAM_CHECK(paramWorkspace != NULL && paramWorkspace->workSpace != NULL, return, "Invalid workspace");
198     WorkSpace *space = paramWorkspace->workSpace[WORKSPACE_INDEX_DAC];
199     PARAM_CHECK(space != NULL && space->area != NULL, return, "Failed to get dac space %s", paramNode->paraName);
200     uint32_t index = 0;
201     (void)FindTrieNode(space, paramNode->paraName, strlen(paramNode->paraName), &index);
202     ParamSecurityNode *node = (ParamSecurityNode *)GetTrieNode(space, index);
203     PARAM_CHECK(node != NULL, return, "Can not get security label for %s", paramNode->paraName);
204     PARAM_LOGV("HandleSelinuxLabelForPermission %s selinuxIndex [ %u %u] dac %u %s ",
205         paramNode->paraName, labelIndex, node->selinuxIndex, index, paramNode->paraContext);
206     ParamAuditData auditData = {0};
207     auditData.dacData.gid = node->gid;
208     auditData.dacData.uid = node->uid;
209     auditData.dacData.mode = node->mode;
210     auditData.dacData.paramType = node->type;
211     auditData.selinuxIndex = labelIndex;
212     auditData.name = paramNode->paraName;
213     auditData.memberNum = 1;
214     auditData.members[0] = node->gid;
215     AddSecurityLabel(&auditData);
216 }
217 
SelinuxGetParamSecurityLabel(const char * cmd,int readOnly)218 static int SelinuxGetParamSecurityLabel(const char *cmd, int readOnly)
219 {
220     if (cmd == NULL || strcmp(cmd, "create") == 0) { // for init and other processor
221         return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForInit);
222     }
223     if ((strcmp(cmd, "init") == 0) && (!readOnly)) { // only for init
224         return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForOpen);
225     }
226     if ((strcmp(cmd, "permission") == 0) && (!readOnly)) { // only for init
227         return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForPermission);
228     }
229     if ((strcmp(cmd, "open") == 0) && readOnly) { // for read only
230         static int loadLabels = 0;
231         if (loadLabels) {
232             return 0;
233         }
234         loadLabels = 1;
235         return SelinuxGetAllLabel(readOnly, HandleSelinuxLabelForOpen);
236     }
237     return 0;
238 }
239 
SelinuxGetParamSecurityLabelForInit(const char * path)240 static int SelinuxGetParamSecurityLabelForInit(const char *path)
241 {
242     return SelinuxGetParamSecurityLabel(path, 0);
243 }
244 
CheckFilePermission(const ParamSecurityLabel * localLabel,const char * fileName,int flags)245 static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
246 {
247     UNUSED(flags);
248     UNUSED(localLabel);
249     UNUSED(fileName);
250     return 0;
251 }
252 
UpdaterCheckParamPermission(const ParamLabelIndex * labelIndex,const ParamSecurityLabel * srcLabel,const char * name,uint32_t mode)253 static int UpdaterCheckParamPermission(const ParamLabelIndex *labelIndex,
254     const ParamSecurityLabel *srcLabel, const char *name, uint32_t mode)
255 {
256     return DAC_RESULT_PERMISSION;
257 }
258 
SelinuxGetParamSecurityLabelForOther(const char * path)259 static int SelinuxGetParamSecurityLabelForOther(const char *path)
260 {
261     return SelinuxGetParamSecurityLabel(path, 1);
262 }
263 
RegisterSecuritySelinuxOps(ParamSecurityOps * ops,int isInit)264 INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
265 {
266     PARAM_CHECK(GetParamWorkSpace() != NULL, return -1, "Invalid workspace");
267     PARAM_CHECK(ops != NULL, return -1, "Invalid param");
268     int ret = PARAM_STRCPY(ops->name, sizeof(ops->name), "selinux");
269     ops->securityGetLabel = NULL;
270     ops->securityInitLabel = InitLocalSecurityLabel;
271     ops->securityCheckFilePermission = CheckFilePermission;
272     if (GetParamWorkSpace()->ops.updaterMode == 1) {
273         ops->securityCheckParamPermission = UpdaterCheckParamPermission;
274     } else {
275 #ifdef STARTUP_INIT_TEST
276         ops->securityCheckParamPermission = SelinuxCheckParamPermission;
277 #endif
278     }
279     ops->securityFreeLabel = FreeLocalSecurityLabel;
280     if (isInit != 0) {
281         ops->securityGetLabel = SelinuxGetParamSecurityLabelForInit;
282     } else {
283         ops->securityGetLabel = SelinuxGetParamSecurityLabelForOther;
284     }
285     return ret;
286 }
287