• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018 Google LLC
4  */
5 #include <dirent.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <poll.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 #include <sys/ioctl.h>
15 #include <sys/mount.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 
19 #include <openssl/sha.h>
20 #include <openssl/md5.h>
21 
22 #include "utils.h"
23 
24 #ifndef __S_IFREG
25 #define __S_IFREG S_IFREG
26 #endif
27 
mount_fs(const char * mount_dir,const char * backing_dir,int read_timeout_ms)28 int mount_fs(const char *mount_dir, const char *backing_dir,
29 	     int read_timeout_ms)
30 {
31 	static const char fs_name[] = INCFS_NAME;
32 	char mount_options[512];
33 	int result;
34 
35 	snprintf(mount_options, ARRAY_SIZE(mount_options),
36 		 "read_timeout_ms=%u",
37 		  read_timeout_ms);
38 
39 	result = mount(backing_dir, mount_dir, fs_name, 0, mount_options);
40 	if (result != 0)
41 		perror("Error mounting fs.");
42 	return result;
43 }
44 
mount_fs_opt(const char * mount_dir,const char * backing_dir,const char * opt,bool remount)45 int mount_fs_opt(const char *mount_dir, const char *backing_dir,
46 		 const char *opt, bool remount)
47 {
48 	static const char fs_name[] = INCFS_NAME;
49 	int result;
50 
51 	result = mount(backing_dir, mount_dir, fs_name,
52 		       remount ? MS_REMOUNT : 0, opt);
53 	if (result != 0)
54 		perror("Error mounting fs.");
55 	return result;
56 }
57 
58 struct hash_section {
59 	uint32_t algorithm;
60 	uint8_t log2_blocksize;
61 	uint32_t salt_size;
62 	/* no salt */
63 	uint32_t hash_size;
64 	uint8_t hash[SHA256_DIGEST_SIZE];
65 } __packed;
66 
67 struct signature_blob {
68 	uint32_t version;
69 	uint32_t hash_section_size;
70 	struct hash_section hash_section;
71 	uint32_t signing_section_size;
72 	uint8_t signing_section[];
73 } __packed;
74 
format_signature(void ** buf,const char * root_hash,const char * add_data)75 size_t format_signature(void **buf, const char *root_hash, const char *add_data)
76 {
77 	size_t size = sizeof(struct signature_blob) + strlen(add_data) + 1;
78 	struct signature_blob *sb = malloc(size);
79 
80 	*sb = (struct signature_blob){
81 		.version = INCFS_SIGNATURE_VERSION,
82 		.hash_section_size = sizeof(struct hash_section),
83 		.hash_section =
84 			(struct hash_section){
85 				.algorithm = INCFS_HASH_TREE_SHA256,
86 				.log2_blocksize = 12,
87 				.salt_size = 0,
88 				.hash_size = SHA256_DIGEST_SIZE,
89 			},
90 		.signing_section_size = sizeof(uint32_t) + strlen(add_data) + 1,
91 	};
92 
93 	memcpy(sb->hash_section.hash, root_hash, SHA256_DIGEST_SIZE);
94 	memcpy((char *)sb->signing_section, add_data, strlen(add_data) + 1);
95 	*buf = sb;
96 	return size;
97 }
98 
crypto_emit_file(int fd,const char * dir,const char * filename,incfs_uuid_t * id_out,size_t size,const char * root_hash,const char * add_data)99 int crypto_emit_file(int fd, const char *dir, const char *filename,
100 		     incfs_uuid_t *id_out, size_t size, const char *root_hash,
101 		     const char *add_data)
102 {
103 	int mode = __S_IFREG | 0555;
104 	void *signature;
105 	int error = 0;
106 
107 	struct incfs_new_file_args args = {
108 			.size = size,
109 			.mode = mode,
110 			.file_name = ptr_to_u64(filename),
111 			.directory_path = ptr_to_u64(dir),
112 			.file_attr = 0,
113 			.file_attr_len = 0
114 	};
115 
116 	args.signature_size = format_signature(&signature, root_hash, add_data);
117 	args.signature_info = ptr_to_u64(signature);
118 
119 	md5(filename, strlen(filename), (char *)args.file_id.bytes);
120 
121 	if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0) {
122 		error = -errno;
123 		goto out;
124 	}
125 
126 	*id_out = args.file_id;
127 
128 out:
129 	free(signature);
130 	return error;
131 }
132 
emit_file(int fd,const char * dir,const char * filename,incfs_uuid_t * id_out,size_t size,const char * attr)133 int emit_file(int fd, const char *dir, const char *filename,
134 	      incfs_uuid_t *id_out, size_t size, const char *attr)
135 {
136 	int mode = __S_IFREG | 0555;
137 	struct incfs_new_file_args args = { .size = size,
138 					    .mode = mode,
139 					    .file_name = ptr_to_u64(filename),
140 					    .directory_path = ptr_to_u64(dir),
141 					    .signature_info = ptr_to_u64(NULL),
142 					    .signature_size = 0,
143 					    .file_attr = ptr_to_u64(attr),
144 					    .file_attr_len =
145 						    attr ? strlen(attr) : 0 };
146 
147 	md5(filename, strlen(filename), (char *)args.file_id.bytes);
148 
149 	if (ioctl(fd, INCFS_IOC_CREATE_FILE, &args) != 0)
150 		return -errno;
151 
152 	*id_out = args.file_id;
153 	return 0;
154 }
155 
get_file_bmap(int cmd_fd,int ino,unsigned char * buf,int buf_size)156 int get_file_bmap(int cmd_fd, int ino, unsigned char *buf, int buf_size)
157 {
158 	return 0;
159 }
160 
get_file_signature(int fd,unsigned char * buf,int buf_size)161 int get_file_signature(int fd, unsigned char *buf, int buf_size)
162 {
163 	struct incfs_get_file_sig_args args = {
164 		.file_signature = ptr_to_u64(buf),
165 		.file_signature_buf_size = buf_size
166 	};
167 
168 	if (ioctl(fd, INCFS_IOC_READ_FILE_SIGNATURE, &args) == 0)
169 		return args.file_signature_len_out;
170 	return -errno;
171 }
172 
get_file_size(const char * name)173 loff_t get_file_size(const char *name)
174 {
175 	struct stat st;
176 
177 	if (stat(name, &st) == 0)
178 		return st.st_size;
179 	return -ENOENT;
180 }
181 
open_commands_file(const char * mount_dir)182 int open_commands_file(const char *mount_dir)
183 {
184 	char cmd_file[255];
185 	int cmd_fd;
186 
187 	snprintf(cmd_file, ARRAY_SIZE(cmd_file),
188 			"%s/%s", mount_dir, INCFS_PENDING_READS_FILENAME);
189 	cmd_fd = open(cmd_file, O_RDONLY | O_CLOEXEC);
190 
191 	if (cmd_fd < 0)
192 		perror("Can't open commands file");
193 	return cmd_fd;
194 }
195 
open_log_file(const char * mount_dir)196 int open_log_file(const char *mount_dir)
197 {
198 	char cmd_file[255];
199 	int cmd_fd;
200 
201 	snprintf(cmd_file, ARRAY_SIZE(cmd_file), "%s/.log", mount_dir);
202 	cmd_fd = open(cmd_file, O_RDWR | O_CLOEXEC);
203 	if (cmd_fd < 0)
204 		perror("Can't open log file");
205 	return cmd_fd;
206 }
207 
wait_for_pending_reads(int fd,int timeout_ms,struct incfs_pending_read_info * prs,int prs_count)208 int wait_for_pending_reads(int fd, int timeout_ms,
209 	struct incfs_pending_read_info *prs, int prs_count)
210 {
211 	ssize_t read_res = 0;
212 
213 	if (timeout_ms > 0) {
214 		int poll_res = 0;
215 		struct pollfd pollfd = {
216 			.fd = fd,
217 			.events = POLLIN
218 		};
219 
220 		poll_res = poll(&pollfd, 1, timeout_ms);
221 		if (poll_res < 0)
222 			return -errno;
223 		if (poll_res == 0)
224 			return 0;
225 		if (!(pollfd.revents | POLLIN))
226 			return 0;
227 	}
228 
229 	read_res = read(fd, prs, prs_count * sizeof(*prs));
230 	if (read_res < 0)
231 		return -errno;
232 
233 	return read_res / sizeof(*prs);
234 }
235 
concat_file_name(const char * dir,char * file)236 char *concat_file_name(const char *dir, char *file)
237 {
238 	char full_name[FILENAME_MAX] = "";
239 
240 	if (snprintf(full_name, ARRAY_SIZE(full_name), "%s/%s", dir, file) < 0)
241 		return NULL;
242 	return strdup(full_name);
243 }
244 
delete_dir_tree(const char * dir_path)245 int delete_dir_tree(const char *dir_path)
246 {
247 	DIR *dir = NULL;
248 	struct dirent *dp;
249 	int result = 0;
250 
251 	dir = opendir(dir_path);
252 	if (!dir) {
253 		result = -errno;
254 		goto out;
255 	}
256 
257 	while ((dp = readdir(dir))) {
258 		char *full_path;
259 
260 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
261 			continue;
262 
263 		full_path = concat_file_name(dir_path, dp->d_name);
264 		if (dp->d_type == DT_DIR)
265 			result = delete_dir_tree(full_path);
266 		else
267 			result = unlink(full_path);
268 		free(full_path);
269 		if (result)
270 			goto out;
271 	}
272 
273 out:
274 	if (dir)
275 		closedir(dir);
276 	if (!result)
277 		rmdir(dir_path);
278 	return result;
279 }
280 
sha256(const char * data,size_t dsize,char * hash)281 void sha256(const char *data, size_t dsize, char *hash)
282 {
283 	SHA256_CTX ctx;
284 
285 	SHA256_Init(&ctx);
286 	SHA256_Update(&ctx, data, dsize);
287 	SHA256_Final((unsigned char *)hash, &ctx);
288 }
289 
md5(const char * data,size_t dsize,char * hash)290 void md5(const char *data, size_t dsize, char *hash)
291 {
292 	MD5_CTX ctx;
293 
294 	MD5_Init(&ctx);
295 	MD5_Update(&ctx, data, dsize);
296 	MD5_Final((unsigned char *)hash, &ctx);
297 }
298