• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "hap_restorecon.h"
17 
18 #include <cctype>
19 #include <cerrno>
20 #include <climits>
21 #include <clocale>
22 #include <cstdlib>
23 #include <fstream>
24 #include <istream>
25 #include <regex>
26 #include <sstream>
27 #include <streambuf>
28 #include <string>
29 #include <sys/stat.h>
30 #include <type_traits>
31 #include <unordered_map>
32 #include <utility>
33 #include <vector>
34 
35 #include <include/fts.h>
36 #include <pthread.h>
37 #include "selinux/context.h"
38 #include "selinux/selinux.h"
39 
40 #include "src/callbacks.h"
41 #include "selinux_error.h"
42 #include "selinux_log.h"
43 
44 using namespace Selinux;
45 
46 namespace {
47 #ifdef SELINUX_TEST
48 static const std::string SEHAP_CONTEXTS_FILE = "/data/test/sehap_contexts";
49 #else
50 static const std::string SEHAP_CONTEXTS_FILE = "/system/etc/selinux/targeted/contexts/sehap_contexts";
51 #endif // STARTUP_INIT_TEST
52 
53 static const std::string APL_PREFIX = "apl=";
54 static const std::string NAME_PREFIX = "name=";
55 static const std::string DOMAIN_PREFIX = "domain=";
56 static const std::string TYPE_PREFIX = "type=";
57 static const std::string DEBUGGABLE_PREFIX = "debuggable=";
58 static const std::string EXTRA_PREFIX = "extra=";
59 static const std::string EXTENSION_PREFIX = "extension=";
60 static const std::string DEBUGGABLE = "debuggable";
61 static const std::string DLPSANDBOX = "dlp_sandbox";
62 static const std::string INPUT_ISOLATE = "input_isolate";
63 static const char *DEFAULT_CONTEXT = "u:object_r:unlabeled:s0";
64 static const int CONTEXTS_LENGTH_MIN = 20; // sizeof("apl=x domain= type=")
65 static const int CONTEXTS_LENGTH_MAX = 1024;
66 static const uint32_t UID_BASE = 200000;
67 static const char *NORMAL_HAP_TYPE = "normal_hap";
68 static const char *DEBUG_HAP_TYPE = "debug_hap";
69 static const char *NORMAL_HAP_USER = "o";
70 static const int CATEGORY_SEG0_OFFSET = 0;
71 static const int CATEGORY_SEG1_OFFSET = 256;
72 static const int CATEGORY_SEG2_OFFSET = 512;
73 static const int CATEGORY_SEG3_OFFSET = 768;
74 static const int CATEGORY_SEG4_OFFSET = 1024;
75 static const int CATEGORY_MASK = 0xff;
76 static pthread_once_t g_fcOnce = PTHREAD_ONCE_INIT;
77 static std::unique_ptr<SehapContextsTrie> g_sehapContextsTrie = nullptr;
78 std::mutex g_loadContextsLock;
79 } // namespace
80 
SelinuxSetCallback()81 static void SelinuxSetCallback()
82 {
83     SetSelinuxHilogLevel(SELINUX_HILOG_ERROR);
84     union selinux_callback cb;
85     cb.func_log = SelinuxHilog;
86     selinux_set_callback(SELINUX_CB_LOG, cb);
87 }
88 
CouldSkip(const std::string & line)89 static bool CouldSkip(const std::string &line)
90 {
91     if (line.size() <= CONTEXTS_LENGTH_MIN || line.size() > CONTEXTS_LENGTH_MAX) {
92         return true;
93     }
94     int i = 0;
95     while (isspace(line[i])) {
96         i++;
97     }
98     if (line[i] == '#') {
99         return true;
100     }
101     if (line.find(APL_PREFIX) == line.npos) {
102         return true;
103     }
104     return false;
105 }
106 
DecodeString(const std::string & line,bool & isValid)107 static struct SehapInfo DecodeString(const std::string &line, bool &isValid)
108 {
109     std::stringstream input(line);
110     std::string tmp;
111     struct SehapInfo contextBuff;
112     bool aplVisit = false;
113     bool nameVisit = false;
114     bool domainVisit = false;
115     bool typeVisit = false;
116     bool debuggableVisit = false;
117     bool extraVisit = false;
118     bool extensionVisit = false;
119 
120     while (input >> tmp) {
121         size_t pos;
122         if (!aplVisit && (pos = tmp.find(APL_PREFIX)) != tmp.npos) {
123             contextBuff.apl = tmp.substr(pos + APL_PREFIX.size());
124             aplVisit = true;
125         } else if (!nameVisit && (pos = tmp.find(NAME_PREFIX)) != tmp.npos) {
126             contextBuff.name = tmp.substr(pos + NAME_PREFIX.size());
127             nameVisit = true;
128         } else if (!domainVisit && (pos = tmp.find(DOMAIN_PREFIX)) != tmp.npos) {
129             contextBuff.domain = tmp.substr(pos + DOMAIN_PREFIX.size());
130             domainVisit = true;
131         } else if (!typeVisit && (pos = tmp.find(TYPE_PREFIX)) != tmp.npos) {
132             contextBuff.type = tmp.substr(pos + TYPE_PREFIX.size());
133             typeVisit = true;
134         } else if (!debuggableVisit && (pos = tmp.find(DEBUGGABLE_PREFIX)) != tmp.npos) {
135             std::string debuggable = tmp.substr(pos + DEBUGGABLE_PREFIX.size());
136             contextBuff.debuggable = !strcmp(debuggable.c_str(), "true");
137             debuggableVisit = true;
138         } else if (!extensionVisit && (pos = tmp.find(EXTENSION_PREFIX)) != tmp.npos) {
139             contextBuff.extension = tmp.substr(pos + EXTENSION_PREFIX.size());
140             extensionVisit = true;
141         } else if (!extraVisit && (pos = tmp.find(EXTRA_PREFIX)) != tmp.npos) {
142             std::string extra = tmp.substr(pos + EXTRA_PREFIX.size());
143             if (extra == DLPSANDBOX) {
144                 contextBuff.extra |= SELINUX_HAP_DLP;
145             } else if (extra == INPUT_ISOLATE) {
146                 contextBuff.extra |= SELINUX_HAP_INPUT_ISOLATE;
147             } else {
148                 selinux_log(SELINUX_ERROR, "invalid extra %s\n", extra.c_str());
149                 isValid = false;
150                 break;
151             }
152             extraVisit = true;
153         }
154     }
155     return contextBuff;
156 }
157 
CheckPath(const std::string & path)158 static bool CheckPath(const std::string &path)
159 {
160     std::regex pathPrefix1("^/data/app/el[1-5]/[0-9]+/(base|database|sharefiles)/.*");
161     std::regex pathPrefix2("^/data/accounts/account_0/appdata/.*");
162     std::regex pathPrefix3("^/data/service/el[1-5]/[0-9]+/backup/bundles/.*");
163     if (std::regex_match(path, pathPrefix1) || std::regex_match(path, pathPrefix2) ||
164         std::regex_match(path, pathPrefix3)) {
165         return true;
166     }
167     return false;
168 }
169 
CheckApl(const std::string & apl)170 static bool CheckApl(const std::string &apl)
171 {
172     if (apl == "system_core" || apl == "system_basic" || apl == "normal") {
173         return true;
174     }
175     return false;
176 }
177 
GetHapContextKey(const struct SehapInfo * hapInfo)178 static std::string GetHapContextKey(const struct SehapInfo *hapInfo)
179 {
180     std::string keyPara;
181 
182     if (hapInfo->extra & SELINUX_HAP_INPUT_ISOLATE) {
183         if (hapInfo->debuggable) {
184             keyPara = hapInfo->apl + "." + DEBUGGABLE + "." + INPUT_ISOLATE;
185         } else {
186             keyPara = hapInfo->apl + "." + INPUT_ISOLATE;
187         }
188     } else if (hapInfo->extra & SELINUX_HAP_DLP) {
189         keyPara = hapInfo->apl + "." + DLPSANDBOX;
190     } else if (hapInfo->debuggable) {
191         keyPara = hapInfo->apl + "." + DEBUGGABLE;
192     } else if (!hapInfo->name.empty()) {
193         keyPara = hapInfo->apl + "." + hapInfo->name;
194     } else {
195         keyPara = hapInfo->apl;
196     }
197 
198     return keyPara;
199 }
200 
HapContextsInsert(const SehapInfo & tmpInfo,int lineNum)201 static bool HapContextsInsert(const SehapInfo &tmpInfo, int lineNum)
202 {
203     std::string keyPara = GetHapContextKey(&tmpInfo);
204     if (keyPara.empty()) {
205         selinux_log(SELINUX_ERROR, "hap_contexts read fail in line %d\n", lineNum);
206         return false;
207     }
208 
209     selinux_log(SELINUX_INFO, "insert keyPara %s\n", keyPara.c_str());
210     bool ret = g_sehapContextsTrie->Insert(keyPara, tmpInfo.domain, tmpInfo.type, tmpInfo.extension);
211     if (!ret) {
212         selinux_log(SELINUX_ERROR, "sehap contexts trie insert fail %s\n", keyPara.c_str());
213         return false;
214     }
215     if (tmpInfo.name.empty() && !tmpInfo.debuggable && !tmpInfo.extra) {
216         keyPara = tmpInfo.apl + ".";
217         ret = g_sehapContextsTrie->Insert(keyPara, tmpInfo.domain, tmpInfo.type, tmpInfo.extension);
218     }
219     return ret;
220 }
221 
HapContextsLoad()222 static bool HapContextsLoad()
223 {
224     // load sehap_contexts file
225     std::ifstream contextsFile(SEHAP_CONTEXTS_FILE);
226     if (contextsFile) {
227         g_sehapContextsTrie = std::make_unique<SehapContextsTrie>();
228         if (g_sehapContextsTrie == nullptr) {
229             selinux_log(SELINUX_ERROR, "malloc g_sehapContextsTrie fail");
230             return false;
231         }
232         int lineNum = 0;
233         std::string line;
234         while (getline(contextsFile, line)) {
235             lineNum++;
236             if (CouldSkip(line)) {
237                 continue;
238             }
239             bool isValid = true;
240             struct SehapInfo tmpInfo = DecodeString(line, isValid);
241             if (!isValid) {
242                 continue;
243             }
244             if (!HapContextsInsert(tmpInfo, lineNum)) {
245                 g_sehapContextsTrie->Clear();
246                 g_sehapContextsTrie = nullptr;
247                 return false;
248             }
249         }
250     } else {
251         selinux_log(SELINUX_ERROR, "Load hap_contexts fail, no such file: %s\n", SEHAP_CONTEXTS_FILE.c_str());
252         return false;
253     }
254     selinux_log(SELINUX_INFO, "Load hap_contexts succes: %s\n", SEHAP_CONTEXTS_FILE.c_str());
255     contextsFile.close();
256     return true;
257 }
258 
CheckValidCmp(char * oldSecontext,char * newSecontext)259 static bool CheckValidCmp(char *oldSecontext, char *newSecontext)
260 {
261     if (oldSecontext == nullptr || newSecontext == nullptr) {
262         if (oldSecontext != nullptr) {
263             freecon(oldSecontext);
264         }
265         if (newSecontext != nullptr) {
266             freecon(newSecontext);
267         }
268         return false;
269     }
270     return true;
271 }
272 
FreeContext(char * oldTypeContext,context_t con)273 static void FreeContext(char *oldTypeContext, context_t con)
274 {
275     if (oldTypeContext != nullptr) {
276         freecon(oldTypeContext);
277     }
278     if (con != nullptr) {
279         context_free(con);
280     }
281 }
282 
HapContext()283 HapContext::HapContext()
284 {
285     __selinux_once(g_fcOnce, SelinuxSetCallback);
286 }
287 
~HapContext()288 HapContext::~HapContext() {}
289 
HapFileRestorecon(HapFileInfo & hapFileInfo)290 int HapContext::HapFileRestorecon(HapFileInfo& hapFileInfo)
291 {
292     if (hapFileInfo.apl.empty() || hapFileInfo.pathNameOrig.empty() || !CheckApl(hapFileInfo.apl)) {
293         return -SELINUX_ARG_INVALID;
294     }
295     bool failFlag = false;
296     for (auto pathname : hapFileInfo.pathNameOrig) {
297         int res = HapFileRestorecon(pathname.c_str(), hapFileInfo);
298         if (res != SELINUX_SUCC) {
299             failFlag = true;
300             selinux_log(SELINUX_ERROR, "HapFileRestorecon fail for path: %s, errorNo: %d", pathname.c_str(), res);
301         }
302     }
303     return failFlag ? -SELINUX_RESTORECON_ERROR : SELINUX_SUCC;
304 }
305 
HapFileRestorecon(const std::string & pathNameOrig,HapFileInfo & hapFileInfo)306 int HapContext::HapFileRestorecon(const std::string &pathNameOrig, HapFileInfo& hapFileInfo)
307 {
308     if (hapFileInfo.apl.empty() || pathNameOrig.empty() || !CheckApl(hapFileInfo.apl)) {
309         return -SELINUX_ARG_INVALID;
310     }
311     if (is_selinux_enabled() < 1) {
312         selinux_log(SELINUX_INFO, "Selinux not enbaled");
313         return SELINUX_SUCC;
314     }
315 
316     char realPath[PATH_MAX];
317     if (realpath(pathNameOrig.c_str(), realPath) == nullptr) {
318         return -SELINUX_PATH_INVALID;
319     }
320 
321     if (!CheckPath(realPath)) {
322         return -SELINUX_PATH_INVALID;
323     }
324 
325     char *newSecontext = nullptr;
326     char *oldSecontext = nullptr;
327     int res = GetSecontext(hapFileInfo, pathNameOrig, &newSecontext, &oldSecontext);
328     if (res < 0) {
329         return res;
330     }
331     if (!CheckValidCmp(oldSecontext, newSecontext)) {
332         selinux_log(SELINUX_ERROR, "oldSecontext or newSecontext is null");
333         return -SELINUX_PTR_NULL;
334     }
335     if (strcmp(oldSecontext, newSecontext) == 0) {
336         freecon(newSecontext);
337         freecon(oldSecontext);
338         return SELINUX_SUCC;
339     }
340     freecon(newSecontext);
341     freecon(oldSecontext);
342     // determine whether needs recurse
343     bool recurse = (hapFileInfo.flags & SELINUX_HAP_RESTORECON_RECURSE) ? true : false;
344     if (!recurse) {
345         int ret = RestoreconSb(realPath, hapFileInfo);
346         if (ret < 0) {
347             selinux_log(SELINUX_ERROR, "RestoreconSb failed");
348         }
349         return ret;
350     }
351     return HapFileRecurseRestorecon(realPath, hapFileInfo);
352 }
353 
HapFileRecurseRestorecon(const std::string & realPath,HapFileInfo & hapFileInfo)354 int HapContext::HapFileRecurseRestorecon(const std::string &realPath, HapFileInfo& hapFileInfo)
355 {
356     char *paths[2] = {nullptr, nullptr};
357     paths[0] = strdup(realPath.c_str());
358     if (paths[0] == nullptr) {
359         return -SELINUX_PTR_NULL;
360     }
361 
362     int ftsFlags = FTS_PHYSICAL | FTS_NOCHDIR;
363     FTS *fts = fts_open(paths, ftsFlags, nullptr);
364     if (fts == nullptr) {
365         selinux_log(SELINUX_ERROR, "%s on %s: %s\n", GetErrStr(SELINUX_FTS_OPEN_ERROR), paths[0], strerror(errno));
366         free(paths[0]);
367         return -SELINUX_FTS_OPEN_ERROR;
368     }
369 
370     FTSENT *ftsent = nullptr;
371     int error = 0;
372     while ((ftsent = fts_read(fts)) != nullptr) {
373         switch (ftsent->fts_info) {
374             case FTS_DC:
375                 (void)fts_close(fts);
376                 free(paths[0]);
377                 return -SELINUX_FTS_ELOOP;
378             case FTS_DP:
379                 continue;
380             case FTS_DNR:
381                 fts_set(fts, ftsent, FTS_SKIP);
382                 continue;
383             case FTS_ERR:
384                 fts_set(fts, ftsent, FTS_SKIP);
385                 continue;
386             case FTS_NS:
387                 fts_set(fts, ftsent, FTS_SKIP);
388                 continue;
389             case FTS_D:
390             default:
391                 if (RestoreconSb(ftsent->fts_path, hapFileInfo) != 0) {
392                     error = -SELINUX_RESTORECON_ERROR;
393                 }
394                 break;
395         }
396     }
397     (void)fts_close(fts);
398     free(paths[0]);
399     return error;
400 }
401 
RestoreconSb(const std::string & pathNameOrig,HapFileInfo & hapFileInfo)402 int HapContext::RestoreconSb(const std::string &pathNameOrig, HapFileInfo& hapFileInfo)
403 {
404     char *newSecontext = nullptr;
405     char *oldSecontext = nullptr;
406     int res = GetSecontext(hapFileInfo, pathNameOrig, &newSecontext, &oldSecontext);
407     if (res < 0) {
408         return res;
409     }
410 
411     if (!CheckValidCmp(oldSecontext, newSecontext)) {
412         selinux_log(SELINUX_ERROR, "oldSecontext or newSecontext is null");
413         return -SELINUX_PTR_NULL;
414     }
415 
416     if (strcmp(oldSecontext, newSecontext)) {
417         if (lsetfilecon(pathNameOrig.c_str(), newSecontext) < 0) {
418             freecon(newSecontext);
419             freecon(oldSecontext);
420             return -SELINUX_SET_CONTEXT_ERROR;
421         }
422     }
423     freecon(newSecontext);
424     freecon(oldSecontext);
425     return SELINUX_SUCC;
426 }
427 
GetSecontext(HapFileInfo & hapFileInfo,const std::string & pathNameOrig,char ** newSecontext,char ** oldSecontext)428 int HapContext::GetSecontext(HapFileInfo& hapFileInfo, const std::string &pathNameOrig,
429     char **newSecontext, char **oldSecontext)
430 {
431     if (lgetfilecon(pathNameOrig.c_str(), oldSecontext) < 0) {
432         return -SELINUX_GET_CONTEXT_ERROR;
433     }
434 
435     int res = HapLabelLookup(hapFileInfo.apl, hapFileInfo.packageName, newSecontext, hapFileInfo.hapFlags);
436     if (res < 0) {
437         freecon(*oldSecontext);
438         return res;
439     }
440     return SELINUX_SUCC;
441 }
442 
HapLabelLookup(const std::string & apl,const std::string & packageName,char ** secontextPtr,unsigned int hapFlags)443 int HapContext::HapLabelLookup(const std::string &apl, const std::string &packageName,
444     char **secontextPtr, unsigned int hapFlags)
445 {
446     *secontextPtr = strdup(DEFAULT_CONTEXT);
447     if (*secontextPtr == nullptr) {
448         return -SELINUX_PTR_NULL;
449     }
450     const char *secontext = *secontextPtr;
451     context_t con = context_new(secontext);
452     if (con == nullptr) {
453         freecon(*secontextPtr);
454         *secontextPtr = nullptr;
455         return -SELINUX_PTR_NULL;
456     }
457     HapContextParams params = {apl, packageName, hapFlags};
458     int res = HapContextsLookup(params, false, con);
459     if (res < 0) {
460         freecon(*secontextPtr);
461         *secontextPtr = nullptr;
462         context_free(con);
463         return res;
464     }
465     secontext = context_str(con);
466     if (secontext == nullptr) {
467         freecon(*secontextPtr);
468         *secontextPtr = nullptr;
469         context_free(con);
470         return -SELINUX_PTR_NULL;
471     }
472     // if new contexts is same as old
473     if (!strcmp(secontext, *secontextPtr)) {
474         freecon(*secontextPtr);
475         *secontextPtr = nullptr;
476         context_free(con);
477         return SELINUX_SUCC;
478     }
479     // check whether the context is valid
480     if (security_check_context(secontext) < 0) {
481         selinux_log(SELINUX_ERROR, "context: %s, %s\n", secontext, GetErrStr(SELINUX_CHECK_CONTEXT_ERROR));
482         freecon(*secontextPtr);
483         *secontextPtr = nullptr;
484         context_free(con);
485         return -SELINUX_CHECK_CONTEXT_ERROR;
486     }
487     freecon(*secontextPtr);
488     *secontextPtr = strdup(secontext);
489     if (*secontextPtr == nullptr) {
490         context_free(con);
491         return -SELINUX_PTR_NULL;
492     }
493     context_free(con);
494     return SELINUX_SUCC;
495 }
496 
HapDomainSetcontext(HapDomainInfo & hapDomainInfo)497 int HapContext::HapDomainSetcontext(HapDomainInfo& hapDomainInfo)
498 {
499     if (hapDomainInfo.apl.empty() || !CheckApl(hapDomainInfo.apl)) {
500         return -SELINUX_ARG_INVALID;
501     }
502 
503     if (is_selinux_enabled() < 1) {
504         selinux_log(SELINUX_INFO, "Selinux not enabled");
505         return SELINUX_SUCC;
506     }
507 
508     char *oldTypeContext = nullptr;
509     if (getcon(&oldTypeContext)) {
510         return -SELINUX_GET_CONTEXT_ERROR;
511     }
512 
513     context_t con = nullptr;
514     con = context_new(oldTypeContext);
515     if (con == nullptr) {
516         FreeContext(oldTypeContext, con);
517         return -SELINUX_PTR_NULL;
518     }
519 
520     HapContextParams params = {hapDomainInfo.apl, hapDomainInfo.packageName,
521         hapDomainInfo.hapFlags, hapDomainInfo.extensionType};
522     int res = HapContextsLookup(params, con, hapDomainInfo.uid);
523     if (res < 0) {
524         FreeContext(oldTypeContext, con);
525         return res;
526     }
527 
528     const char *typeContext = context_str(con);
529     if (typeContext == nullptr) {
530         FreeContext(oldTypeContext, con);
531         return -SELINUX_PTR_NULL;
532     }
533 
534     selinux_log(SELINUX_INFO, "Hap type for %s is changing from %s to %s\n",
535         hapDomainInfo.packageName.c_str(), oldTypeContext, typeContext);
536 
537     if (security_check_context(typeContext) < 0) {
538         selinux_log(SELINUX_ERROR, "context: %s, %s\n", typeContext, GetErrStr(SELINUX_CHECK_CONTEXT_ERROR));
539         FreeContext(oldTypeContext, con);
540         return -SELINUX_CHECK_CONTEXT_ERROR;
541     }
542 
543     if (strcmp(typeContext, oldTypeContext)) {
544         if (setcon(typeContext) < 0) {
545             FreeContext(oldTypeContext, con);
546             return -SELINUX_SET_CONTEXT_ERROR;
547         }
548     }
549     selinux_log(SELINUX_INFO, "Hap setcon finish for %s\n", hapDomainInfo.packageName.c_str());
550 
551     FreeContext(oldTypeContext, con);
552     return SELINUX_SUCC;
553 }
554 
HapContextsLookup(const HapContextParams & params,bool isDomain,context_t con)555 int HapContext::HapContextsLookup(const HapContextParams &params, bool isDomain, context_t con)
556 {
557     {
558         std::lock_guard<std::mutex> lock(g_loadContextsLock);
559         if (g_sehapContextsTrie == nullptr) {
560             if (!HapContextsLoad()) {
561                 return -SELINUX_CONTEXTS_FILE_LOAD_ERROR;
562             }
563         }
564     }
565 
566     std::string keyPara;
567     if (params.hapFlags & SELINUX_HAP_INPUT_ISOLATE) {
568         if (params.hapFlags & SELINUX_HAP_DEBUGGABLE) {
569             keyPara = params.apl + "." + DEBUGGABLE + "." + INPUT_ISOLATE;
570             selinux_log(SELINUX_INFO, "input_isolate debug hap, keyPara: %s", keyPara.c_str());
571         } else {
572             keyPara = params.apl + "." + INPUT_ISOLATE;
573             selinux_log(SELINUX_INFO, "input_isolate isolate hap, keyPara: %s", keyPara.c_str());
574         }
575     } else if (params.hapFlags & SELINUX_HAP_DLP) {
576         keyPara = params.apl + "." + DLPSANDBOX;
577         selinux_log(SELINUX_INFO, "dlpsandbox hap, keyPara: %s", keyPara.c_str());
578     } else if (params.hapFlags & SELINUX_HAP_RESTORECON_PREINSTALLED_APP) {
579         keyPara = params.apl + "." + params.packageName;
580         selinux_log(SELINUX_INFO, "preinstall hap, keyPara: %s", keyPara.c_str());
581     } else if (params.hapFlags & SELINUX_HAP_DEBUGGABLE) {
582         keyPara = params.apl + "." + DEBUGGABLE;
583         selinux_log(SELINUX_INFO, "debuggable hap, keyPara: %s", keyPara.c_str());
584     } else {
585         selinux_log(SELINUX_INFO, "not a preinstall hap, apl: %s", params.apl.c_str());
586         keyPara = params.apl;
587     }
588 
589     std::string type = g_sehapContextsTrie->Search(keyPara, isDomain, params.extension);
590     if (!type.empty()) {
591         return TypeSet(type, con);
592     }
593     return -SELINUX_KEY_NOT_FOUND;
594 }
595 
HapContextsLookup(const HapContextParams & params,context_t con,uint32_t uid)596 int HapContext::HapContextsLookup(const HapContextParams &params, context_t con, uint32_t uid)
597 {
598     int res = HapContextsLookup(params, true, con);
599     if (res < 0) {
600         return res;
601     }
602     res = UserAndMCSRangeSet(uid, con);
603     if (res < 0) {
604         return res;
605     }
606     return SELINUX_SUCC;
607 }
608 
TypeSet(const std::string & type,context_t con)609 int HapContext::TypeSet(const std::string &type, context_t con)
610 {
611     if (type.empty()) {
612         selinux_log(SELINUX_ERROR, "type is empty in contexts file");
613         return -SELINUX_ARG_INVALID;
614     }
615     if (context_type_set(con, type.c_str())) {
616         selinux_log(SELINUX_ERROR, "%s %s\n", GetErrStr(SELINUX_SET_CONTEXT_TYPE_ERROR), type.c_str());
617         return -SELINUX_SET_CONTEXT_TYPE_ERROR;
618     }
619     return SELINUX_SUCC;
620 }
621 
UserAndMCSRangeSet(uint32_t uid,context_t con)622 int HapContext::UserAndMCSRangeSet(uint32_t uid, context_t con)
623 {
624     if (uid < UID_BASE) {
625         return SELINUX_SUCC;
626     }
627     const char *currentType = context_type_get(con);
628     if (currentType == nullptr) {
629         selinux_log(SELINUX_ERROR, "Failed to get context type.");
630         return -SELINUX_SET_CONTEXT_USER_ERROR;
631     }
632     std::string typeStr = std::string(currentType);
633     if ((typeStr != NORMAL_HAP_TYPE) && (typeStr != DEBUG_HAP_TYPE)) {
634         return SELINUX_SUCC;
635     }
636     int ret = context_user_set(con, NORMAL_HAP_USER);
637     if (ret != 0) {
638         selinux_log(SELINUX_ERROR, "Failed to set context user %s\n", NORMAL_HAP_USER);
639         return -SELINUX_SET_CONTEXT_USER_ERROR;
640     }
641     uint32_t userId = uid / UID_BASE;
642     uint32_t appId = uid % UID_BASE;
643     std::string level = "s0:x" + std::to_string(CATEGORY_SEG0_OFFSET + (appId & CATEGORY_MASK)) +
644                 ",x" + std::to_string(CATEGORY_SEG1_OFFSET + ((appId >> 8) & CATEGORY_MASK)) +
645                 ",x" + std::to_string(CATEGORY_SEG2_OFFSET + ((appId >> 16) & CATEGORY_MASK)) +
646                 ",x" + std::to_string(CATEGORY_SEG3_OFFSET + (userId & CATEGORY_MASK)) +
647                 ",x" + std::to_string(CATEGORY_SEG4_OFFSET + ((userId >> 8) & CATEGORY_MASK));
648     ret = context_range_set(con, level.c_str());
649     if (ret != 0) {
650         selinux_log(SELINUX_ERROR, "Failed to set context range %s\n", level.c_str());
651         return -SELINUX_SET_CONTEXT_RANGE_ERROR;
652     }
653     return SELINUX_SUCC;
654 }
655