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