• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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