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/fs.h>
14 #include <linux/namei.h>
15 #include <linux/blackbox_common.h>
16
sys_reset(void)17 void sys_reset(void)
18 {
19 bbox_print_info("reset the system now!\n");
20 emergency_restart();
21 bbox_print_info("reset the system failed!\n");
22 }
23
change_own(char * path,int uid,int gid)24 void change_own(char *path, int uid, int gid)
25 {
26 mm_segment_t old_fs;
27 int ret = -1;
28
29 if (unlikely(!path || uid == -1 || gid == -1)) {
30 bbox_print_err("path or uid or gid error.\n");
31 return;
32 }
33
34 old_fs = get_fs();
35 set_fs(KERNEL_DS);
36 ret = ksys_chown(path, uid, gid);
37 if (ret != 0)
38 bbox_print_err("ksys_chown [%s] failed, ret: %d\n", path, ret);
39
40 set_fs(old_fs);
41 }
42
full_write_file(const char * pfile_path,char * buf,size_t buf_size,bool is_append)43 int full_write_file(const char *pfile_path, char *buf,
44 size_t buf_size, bool is_append)
45 {
46 struct file *filp = NULL;
47 char *pathname = NULL;
48 mm_segment_t old_fs;
49 loff_t pos = 0;
50 int ret = -1;
51
52 if (unlikely(!pfile_path || !buf)) {
53 bbox_print_err("pfile_path or buf is NULL!\n");
54 return -EINVAL;
55 }
56
57 filp = file_open(pfile_path, O_CREAT | O_RDWR |
58 (is_append ? O_APPEND : O_TRUNC), BBOX_FILE_LIMIT);
59 if (IS_ERR(filp)) {
60 bbox_print_err("open %s failed! [%ld]\n", pfile_path, PTR_ERR(filp));
61 return -EBADF;
62 }
63
64 old_fs = get_fs();
65 set_fs(KERNEL_DS);
66
67 ret = vfs_write(filp, buf, buf_size, &pos);
68
69 set_fs(old_fs);
70
71 file_close(filp);
72
73 if (ret < 0) {
74 pathname = getfullpath(filp);
75 bbox_print_err("write [%s] failed! [%d]\n", pathname ? pathname : "", ret);
76 return ret;
77 }
78
79 return 0;
80 }
81
file_exists(const char * name)82 int file_exists(const char *name)
83 {
84 struct path path;
85 int ret;
86
87 ret = kern_path(name, LOOKUP_FOLLOW, &path);
88 if (ret)
89 return ret;
90
91 ret = inode_permission(d_inode(path.dentry), MAY_ACCESS);
92 path_put(&path);
93 return ret;
94 }
95
create_new_dir(char * name)96 static int create_new_dir(char *name)
97 {
98 struct dentry *dentry;
99 struct path path;
100 int ret;
101
102 if (unlikely(!name)) {
103 bbox_print_err("name is NULL!\n");
104 return -EINVAL;
105 }
106
107 ret = file_exists(name);
108 if (ret) {
109 dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY);
110 if (IS_ERR(dentry))
111 return PTR_ERR(dentry);
112
113 ret = vfs_mkdir(d_inode(path.dentry), dentry, BBOX_DIR_LIMIT);
114 if (ret && ret != -EEXIST)
115 bbox_print_err("Create dir [%s] failed! ret: %d\n", name, ret);
116
117 done_path_create(&path, dentry);
118 }
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 = kmalloc(PATH_MAX_LEN + 1, GFP_KERNEL);
136 if (unlikely(!cur_path)) {
137 bbox_print_err("kmalloc 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 kfree(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 EXPORT_SYMBOL_GPL(get_timestamp);
179
get_ticks(void)180 unsigned long long get_ticks(void)
181 {
182 /* use only one int value to save time: */
183
184 struct timespec64 uptime;
185
186 ktime_get_ts64(&uptime);
187
188 ktime_get_boottime_ts64(&uptime);
189
190 return (u64)uptime.tv_sec;
191 }
192
lock_parent(struct dentry * dentry)193 static inline struct dentry *lock_parent(struct dentry *dentry)
194 {
195 struct dentry *dir = dget_parent(dentry);
196
197 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
198 return dir;
199 }
200
unlock_dir(struct dentry * dentry)201 static inline void unlock_dir(struct dentry *dentry)
202 {
203 inode_unlock(d_inode(dentry));
204 dput(dentry);
205 }
206
file_open(const char * filename,int open_mode,int mode)207 struct file *file_open(const char *filename, int open_mode, int mode)
208 {
209 struct file *filp = NULL;
210 mm_segment_t old_fs;
211
212 old_fs = get_fs();
213 set_fs(KERNEL_DS);
214
215 filp = filp_open(filename, open_mode, mode);
216 set_fs(old_fs);
217
218 return filp;
219 }
220
file_close(struct file * filp)221 void file_close(struct file *filp)
222 {
223 if (likely(filp))
224 filp_close(filp, NULL);
225 }
226
file_delete(struct file * filp)227 int file_delete(struct file *filp)
228 {
229 struct dentry *dentry = NULL;
230 struct dentry *parent = NULL;
231 int ret = 0;
232
233 if (unlikely(!filp)) {
234 bbox_print_err("file is NULL!\n");
235 return -EINVAL;
236 }
237
238 dentry = file_dentry(filp);
239 parent = lock_parent(dentry);
240
241 if (dentry->d_parent == parent) {
242 dget(dentry);
243 ret = vfs_unlink(d_inode(parent), dentry, NULL);
244 dput(dentry);
245 }
246
247 unlock_dir(parent);
248
249 return ret;
250 }
251
getfullpath(struct file * filp)252 char *getfullpath(struct file *filp)
253 {
254 char *buf = NULL, *path = NULL;
255
256 if (unlikely(!filp))
257 return NULL;
258
259 buf = kmalloc(PATH_MAX, GFP_KERNEL);
260 if (unlikely(!buf))
261 return NULL;
262 memset(buf, 0, PATH_MAX);
263
264 // get the path
265 path = d_path(&filp->f_path, buf, PATH_MAX);
266
267 kfree(buf);
268
269 return path;
270 }
271