utils.c 7.8 KB

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