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 "param_checker.h"
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include "errno.h"
20 #include "securec.h"
21 #include "selinux_error.h"
22 #include "selinux_klog.h"
23 #include "src/callbacks.h"
24
25 static pthread_once_t g_setLogOnce = PTHREAD_ONCE_INIT;
26 #define BUF_SIZE 512
27
28 typedef struct AuditMsg {
29 const struct ucred *ucred;
30 const char *name;
31 } AuditMsg;
32
SelinuxAuditCallback(void * data,security_class_t cls,char * buf,size_t len)33 static int SelinuxAuditCallback(void *data, security_class_t cls, char *buf, size_t len)
34 {
35 if (data == NULL || buf == NULL || len == 0) {
36 return -1;
37 }
38 AuditMsg *msg = (AuditMsg *)data;
39 if (!msg->name || !msg->ucred) {
40 selinux_log(SELINUX_ERROR, "Selinux audit msg invalid argument\n");
41 return -1;
42 }
43 if (snprintf_s(buf, len, len - 1, "parameter=%s pid=%d uid=%u gid=%u", msg->name, msg->ucred->pid, msg->ucred->uid,
44 msg->ucred->gid) <= 0) {
45 return -1;
46 }
47 return 0;
48 }
49
SelinuxSetCallback(void)50 static void SelinuxSetCallback(void)
51 {
52 SetSelinuxKmsgLevel(SELINUX_KWARN);
53 union selinux_callback cb;
54 cb.func_log = SelinuxKmsg;
55 selinux_set_callback(SELINUX_CB_LOG, cb);
56 cb.func_audit = SelinuxAuditCallback;
57 selinux_set_callback(SELINUX_CB_AUDIT, cb);
58 }
59
CheckPerm(const char * paraName,const char * srcContext,const char * destContext,const struct ucred * uc)60 static int CheckPerm(const char *paraName, const char *srcContext, const char *destContext, const struct ucred *uc)
61 {
62 if (srcContext == NULL || uc == NULL) {
63 selinux_log(SELINUX_ERROR, "args empty!\n");
64 return -SELINUX_PTR_NULL;
65 }
66 selinux_log(SELINUX_INFO, "srcContext[%s] is setting param[%s] destContext[%s]\n", srcContext, paraName,
67 destContext);
68 AuditMsg msg;
69 msg.name = paraName;
70 msg.ucred = uc;
71 int res = selinux_check_access(srcContext, destContext, "parameter_service", "set", &msg);
72 return res == 0 ? SELINUX_SUCC : -SELINUX_PERMISSION_DENY;
73 }
74
SetInitSelinuxLog(void)75 void SetInitSelinuxLog(void)
76 {
77 if (getpid() == 1) {
78 __selinux_once(g_setLogOnce, SelinuxSetCallback);
79 }
80 }
81
SetParamCheck(const char * paraName,const char * destContext,const SrcInfo * info)82 int SetParamCheck(const char *paraName, const char *destContext, const SrcInfo *info)
83 {
84 if (paraName == NULL || destContext == NULL || info == NULL) {
85 selinux_log(SELINUX_ERROR, "input param is null!\n");
86 return -SELINUX_PTR_NULL;
87 }
88
89 char *srcContext = NULL;
90 int rc = getpeercon(info->sockFd, &srcContext);
91 if (rc < 0) {
92 selinux_log(SELINUX_ERROR, "getpeercon failed: %s\n", strerror(errno));
93 return -SELINUX_GET_CONTEXT_ERROR;
94 }
95
96 int res = CheckPerm(paraName, srcContext, destContext, &(info->uc));
97 freecon(srcContext);
98 return res;
99 }
100