• 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 "selinux_klog.h"
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include "securec.h"
20 
21 #define MAX_LOG_SIZE 1024
22 #define MAX_LEVEL_SIZE 4
23 
24 static int g_logLevel = SELINUX_KERROR;
25 static const char *LOG_LEVEL_STR[] = {"ERROR", "WARNING", "INFO", "AVC"};
26 
27 #ifndef UNLIKELY
28 #define UNLIKELY(x) __builtin_expect(!!(x), 0)
29 #endif
30 
SetSelinuxKmsgLevel(int logLevel)31 void SetSelinuxKmsgLevel(int logLevel)
32 {
33     g_logLevel = logLevel;
34 }
35 
36 static int g_fd = -1;
SelinuxOpenLogDevice(void)37 static void SelinuxOpenLogDevice(void)
38 {
39     int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IRGRP);
40     if (fd >= 0) {
41         g_fd = fd;
42     }
43     return;
44 }
45 
SelinuxKmsg(int logLevel,const char * fmt,...)46 int SelinuxKmsg(int logLevel, const char *fmt, ...)
47 {
48     if (logLevel != SELINUX_KAVC && logLevel > g_logLevel) {
49         return -1;
50     }
51 
52     if ((logLevel < 0) || (logLevel >= MAX_LEVEL_SIZE)) {
53         return -1;
54     }
55     if (UNLIKELY(g_fd < 0)) {
56         SelinuxOpenLogDevice();
57         if (g_fd < 0) {
58             return -1;
59         }
60     }
61     va_list vargs;
62     va_start(vargs, fmt);
63     char tmpFmt[MAX_LOG_SIZE];
64     if (vsnprintf_s(tmpFmt, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, fmt, vargs) == -1) {
65         close(g_fd);
66         g_fd = -1;
67         va_end(vargs);
68         return -1;
69     }
70 
71     char logInfo[MAX_LOG_SIZE];
72     int res = 0;
73     if (logLevel != SELINUX_KAVC) {
74         res = snprintf_s(logInfo, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, "[pid=%d][%s][%s] %s", getpid(), "SELINUX",
75                          LOG_LEVEL_STR[logLevel], tmpFmt);
76     } else {
77         res = snprintf_s(logInfo, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, "%s", tmpFmt);
78     }
79     if (res == -1) {
80         close(g_fd);
81         g_fd = -1;
82         va_end(vargs);
83         return -1;
84     }
85     va_end(vargs);
86 
87     if (write(g_fd, logInfo, strlen(logInfo)) < 0) {
88         close(g_fd);
89         g_fd = -1;
90     }
91     return 0;
92 }
93