• 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 "seccomp_policy.h"
17 #include "plugin_adapter.h"
18 #include "securec.h"
19 
20 #include <dlfcn.h>
21 #include <sys/syscall.h>
22 #include <unistd.h>
23 #include <ctype.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <linux/audit.h>
27 #include <linux/seccomp.h>
28 #include <linux/filter.h>
29 #include <limits.h>
30 
31 #ifndef SECCOMP_SET_MODE_FILTER
32 #define SECCOMP_SET_MODE_FILTER  (1)
33 #endif
34 
35 #ifdef __aarch64__
36 #define FILTER_LIB_PATH_FORMAT "/system/lib64/lib%s_filter.z.so"
37 #define FILTER_LIB_PATH_HEAD "/system/lib64/lib"
38 #else
39 #define FILTER_LIB_PATH_FORMAT "/system/lib/lib%s_filter.z.so"
40 #define FILTER_LIB_PATH_HEAD "/system/lib/lib"
41 #endif
42 #define FILTER_NAME_FORMAT "g_%sSeccompFilter"
43 #define FILTER_SIZE_STRING "Size"
44 
45 typedef enum {
46     SECCOMP_SUCCESS,
47     INPUT_ERROR,
48     RETURN_NULL,
49     RETURN_ERROR
50 } SeccompErrorCode;
51 
IsSupportFilterFlag(unsigned int filterFlag)52 static bool IsSupportFilterFlag(unsigned int filterFlag)
53 {
54     errno = 0;
55     long ret = syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, filterFlag, NULL);
56     if (ret != -1 || errno != EFAULT) {
57         PLUGIN_LOGE("not support  seccomp flag %u", filterFlag);
58         return false;
59     }
60 
61     return true;
62 }
63 
InstallSeccompPolicy(const struct sock_filter * filter,size_t filterSize,unsigned int filterFlag)64 static bool InstallSeccompPolicy(const struct sock_filter* filter, size_t filterSize, unsigned int filterFlag)
65 {
66     if (filter == NULL) {
67         return false;
68     }
69 
70     unsigned int flag = 0;
71     struct sock_fprog prog = {
72         (unsigned short)filterSize,
73         (struct sock_filter*)filter
74     };
75 
76     if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_TSYNC) && (filterFlag & SECCOMP_FILTER_FLAG_TSYNC)) {
77         flag |= SECCOMP_FILTER_FLAG_TSYNC;
78     }
79 
80     if (IsSupportFilterFlag(SECCOMP_FILTER_FLAG_LOG) && (filterFlag & SECCOMP_FILTER_FLAG_LOG)) {
81         flag |= SECCOMP_FILTER_FLAG_LOG;
82     }
83 
84     if (syscall(__NR_seccomp, SECCOMP_SET_MODE_FILTER, flag, &prog) != 0) {
85         PLUGIN_LOGE("SetSeccompFilter failed");
86         return false;
87     }
88 
89     return true;
90 }
91 
GetFilterFileByName(const char * filterName)92 static char *GetFilterFileByName(const char *filterName)
93 {
94     size_t maxFilterNameLen = PATH_MAX - strlen(FILTER_LIB_PATH_FORMAT) + strlen("%s") - 1;
95     if (filterName == NULL || strlen(filterName) > maxFilterNameLen) {
96         return NULL;
97     }
98 
99     char filterLibPath[PATH_MAX] = {0};
100 
101     int rc = snprintf_s(filterLibPath, sizeof(filterLibPath), \
102                             strlen(filterName) + strlen(FILTER_LIB_PATH_FORMAT) - strlen("%s"), \
103                             FILTER_LIB_PATH_FORMAT, filterName);
104     if (rc == -1) {
105         return NULL;
106     }
107 
108     return realpath(filterLibPath, NULL);
109 }
110 
GetSeccompPolicy(const char * filterName,int ** handler,char * filterLibRealPath,struct sock_fprog * prog)111 static int GetSeccompPolicy(const char *filterName, int **handler,
112                             char *filterLibRealPath, struct sock_fprog *prog)
113 {
114     if (filterName == NULL || filterLibRealPath == NULL || \
115         handler == NULL || prog == NULL) {
116         return INPUT_ERROR;
117     }
118 
119     if (strncmp(filterLibRealPath, FILTER_LIB_PATH_HEAD, strlen(FILTER_LIB_PATH_HEAD))) {
120         return INPUT_ERROR;
121     }
122 
123     char filterVaribleName[PATH_MAX] = {0};
124     struct sock_filter *filter = NULL;
125     size_t *filterSize = NULL;
126     void *policyHanlder = NULL;
127     int ret = SECCOMP_SUCCESS;
128     do {
129         int rc = snprintf_s(filterVaribleName, sizeof(filterVaribleName), \
130                     strlen(filterName) + strlen(FILTER_NAME_FORMAT) - strlen("%s"), \
131                     FILTER_NAME_FORMAT, filterName);
132         if (rc == -1) {
133             ret = RETURN_ERROR;
134             break;
135         }
136 
137         policyHanlder = dlopen(filterLibRealPath, RTLD_LAZY);
138         if (policyHanlder == NULL) {
139             ret = RETURN_NULL;
140             break;
141         }
142 
143         filter = (struct sock_filter *)dlsym(policyHanlder, filterVaribleName);
144         if (filter == NULL) {
145             ret = RETURN_NULL;
146             break;
147         }
148 
149         rc = strcat_s(filterVaribleName, strlen(filterVaribleName) + \
150                       strlen(FILTER_SIZE_STRING) + 1, FILTER_SIZE_STRING);
151         if (rc != 0) {
152             ret = RETURN_ERROR;
153             break;
154         }
155 
156         filterSize = (size_t *)dlsym(policyHanlder, filterVaribleName);
157         if (filterSize == NULL) {
158             ret = RETURN_NULL;
159             break;
160         }
161     } while (0);
162 
163     *handler = (int *)policyHanlder;
164     prog->filter = filter;
165     if (filterSize != NULL) {
166         prog->len = (unsigned short)(*filterSize);
167     }
168 
169     return ret;
170 }
171 
SetSeccompPolicyWithName(const char * filterName)172 bool SetSeccompPolicyWithName(const char *filterName)
173 {
174     if (filterName == NULL) {
175         return false;
176     }
177 
178     void *handler = NULL;
179     char *filterLibRealPath = NULL;
180     struct sock_fprog prog;
181     bool ret = false;
182 
183     filterLibRealPath = GetFilterFileByName(filterName);
184     PLUGIN_CHECK(filterLibRealPath != NULL, return false, "get filter file name faield");
185 
186     int retCode = GetSeccompPolicy(filterName, (int **)&handler, filterLibRealPath, &prog);
187     if (retCode == SECCOMP_SUCCESS) {
188         ret = InstallSeccompPolicy(prog.filter, prog.len, SECCOMP_FILTER_FLAG_LOG);
189     } else {
190         PLUGIN_LOGE("GetSeccompPolicy failed return is %d", retCode);
191     }
192 
193     if (handler != NULL) {
194         dlclose(handler);
195     }
196 
197     if (filterLibRealPath != NULL) {
198         free(filterLibRealPath);
199     }
200 
201     return ret;
202 }
203