1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2021 Huawei Technologies Co., Ltd. All rights reserved.
4 */
5
6 #include <linux/blackbox.h>
7 #include <linux/kernel.h>
8 #include <linux/delay.h>
9 #include <linux/reboot.h>
10 #include <linux/syscalls.h>
11 #include <linux/rtc.h>
12 #include <linux/time.h>
13 #include <linux/vmalloc.h>
14 #include <linux/blackbox_common.h>
15
sys_reset(void)16 void sys_reset(void)
17 {
18 bbox_print_info("reset the system now!\n");
19 emergency_restart();
20 bbox_print_info("reset the system failed!\n");
21 }
22
change_own_mode(char * path,int uid,int gid,int mode)23 void change_own_mode(char *path, int uid, int gid, int mode)
24 {
25 mm_segment_t old_fs;
26 int ret = -1;
27
28 if (unlikely(!path || uid == -1 || gid == -1)) {
29 bbox_print_err("path or uid or gid error.\n");
30 return;
31 }
32
33 old_fs = get_fs();
34 set_fs(KERNEL_DS);
35 ret = sys_chown(path, uid, gid);
36 if (ret != 0) {
37 bbox_print_err("sys_chown [%s] failed, ret: %d\n", path, ret);
38 goto __out;
39 }
40
41 ret = sys_chmod(path, mode);
42 if (ret != 0) {
43 bbox_print_err("sys_chmod [%s] failed, ret: %d\n", path, ret);
44 goto __out;
45 }
46
47 __out:
48 set_fs(old_fs);
49 }
50
full_write_file(const char * pfile_path,char * buf,size_t buf_size,bool is_append)51 int full_write_file(const char *pfile_path, char *buf,
52 size_t buf_size, bool is_append)
53 {
54 mm_segment_t old_fs;
55 long total_to_write = (long)buf_size;
56 long total_write = 0;
57 long write_this_time;
58 char *ptemp = buf;
59 int fd = -1;
60
61 if (unlikely(!pfile_path || !buf)) {
62 bbox_print_err("fd or buf is NULL!\n");
63 return -EINVAL;
64 }
65
66 old_fs = get_fs();
67 set_fs(KERNEL_DS);
68 fd = sys_open(pfile_path, O_CREAT | O_RDWR |
69 (is_append ? O_APPEND : O_TRUNC), 0);
70 if (fd < 0) {
71 bbox_print_err("Create file [%s] failed! ret: %d\n", pfile_path, fd);
72 goto __out;
73 }
74
75 while (total_to_write > 0) {
76 write_this_time = ksys_write(fd, ptemp, total_to_write);
77 if (write_this_time < 0) {
78 bbox_print_err("%s\n", "Failed to write file!\n");
79 break;
80 }
81 ptemp += write_this_time;
82 total_to_write -= write_this_time;
83 total_write += write_this_time;
84 }
85
86 __out:
87 if (fd >= 0) {
88 ksys_sync();
89 ksys_close(fd);
90 }
91 set_fs(old_fs);
92
93 return total_write == (long)buf_size ? 0 : -1;
94 }
95
create_new_dir(char * path)96 static int create_new_dir(char *path)
97 {
98 int ret;
99 mm_segment_t old_fs;
100
101 if (unlikely(!path)) {
102 bbox_print_err("path is NULL!\n");
103 return -EINVAL;
104 }
105
106 old_fs = get_fs();
107 set_fs(KERNEL_DS);
108 ret = sys_access(path, 0);
109 if (ret != 0) {
110 ret = sys_mkdir(path, BBOX_DIR_LIMIT);
111 if (ret < 0) {
112 bbox_print_err("Create dir [%s] failed! ret: %d\n", path, ret);
113 set_fs(old_fs);
114 return -EINVAL;
115 }
116 change_own_mode(path, AID_ROOT, AID_SYSTEM, BBOX_DIR_LIMIT);
117 }
118 set_fs(old_fs);
119
120 return 0;
121 }
122
create_log_dir(const char * path)123 int create_log_dir(const char *path)
124 {
125 char *cur_path = NULL;
126 int index = 0;
127
128 if (unlikely(!path)) {
129 bbox_print_err("path is NULL!\n");
130 return -EINVAL;
131 }
132
133 if (*path != '/')
134 return -EINVAL;
135 cur_path = vmalloc(PATH_MAX_LEN + 1);
136 if (!cur_path) {
137 bbox_print_err("vmalloc failed!\n");
138 return -ENOMEM;
139 }
140 memset(cur_path, 0, PATH_MAX_LEN + 1);
141 cur_path[index++] = *path++;
142 while (*path != '\0') {
143 if (*path == '/')
144 create_new_dir(cur_path);
145 cur_path[index] = *path;
146 path++;
147 index++;
148 }
149 create_new_dir(cur_path);
150 vfree(cur_path);
151
152 return 0;
153 }
154
get_timestamp(char * buf,size_t buf_size)155 void get_timestamp(char *buf, size_t buf_size)
156 {
157 struct rtc_time tm;
158 struct timespec64 tv;
159
160 if (unlikely(!buf || buf_size == 0)) {
161 bbox_print_err("buf: %p, buf_size: %u\n", buf, (unsigned int)buf_size);
162 return;
163 }
164
165 memset(buf, 0, buf_size);
166 memset(&tm, 0, sizeof(tm));
167
168 memset(&tv, 0, sizeof(tv));
169 ktime_get_real_ts64(&tv);
170 tv.tv_sec -= (long)sys_tz.tz_minuteswest * SECONDS_PER_MINUTE;
171 rtc_time64_to_tm(tv.tv_sec, &tm);
172
173 (void)scnprintf(buf, buf_size, TIMESTAMP_FORMAT,
174 tm.tm_year + YEAR_BASE, tm.tm_mon + 1, tm.tm_mday,
175 tm.tm_hour, tm.tm_min, tm.tm_sec, get_ticks());
176 buf[buf_size - 1] = '\0';
177 }
178
get_ticks(void)179 unsigned long long get_ticks(void)
180 {
181 /* use only one int value to save time: */
182
183 struct timespec64 uptime;
184
185 ktime_get_ts64(&uptime);
186
187 ktime_get_boottime_ts64(&uptime);
188
189 return (u64)uptime.tv_sec;
190 }
191