1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <assert.h>
17 #include <cutils/properties.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <libgen.h>
22 #include <linux/fs.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/syscall.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30
31 #include "checkpoint_handling.h"
32 #include "ipc.h"
33 #include "log.h"
34 #include "storage.h"
35 #include "watchdog.h"
36
37 #define FD_TBL_SIZE 64
38 #define MAX_READ_SIZE 4096
39
40 #define ALTERNATE_DATA_DIR "alternate/"
41
42 /* Maximum file size for filesystem backed storage (i.e. not block dev backed storage) */
43 static uint64_t max_file_size = 0x10000000000;
44
45 enum sync_state {
46 SS_UNUSED = -1,
47 SS_CLEAN = 0,
48 SS_DIRTY = 1,
49 SS_CLEAN_NEED_SYMLINK = 2,
50 };
51
52 static const char *ssdir_name;
53
54 /* List head for storage mapping, elements added at init, and never removed */
55 static struct storage_mapping_node* storage_mapping_head;
56
57 /*
58 * Property set to 1 after we have opened a file under ssdir_name. The backing
59 * files for both TD and TDP are currently located under /data/vendor/ss and can
60 * only be opened once userdata is mounted. This storageproxyd service is
61 * restarted when userdata is available, which causes the Trusty storage service
62 * to reconnect and attempt to open the backing files for TD and TDP. Once we
63 * set this property, other users can expect that the Trusty storage service
64 * ports will be available (although they may block if still being initialized),
65 * and connections will not be reset after this point (assuming the
66 * storageproxyd service stays running).
67 */
68 #define FS_READY_PROPERTY "ro.vendor.trusty.storage.fs_ready"
69
70 /* has FS_READY_PROPERTY been set? */
71 static bool fs_ready_initialized = false;
72
73 static enum sync_state fs_state;
74 static enum sync_state fd_state[FD_TBL_SIZE];
75
76 static bool alternate_mode;
77
78 static struct {
79 struct storage_file_read_resp hdr;
80 uint8_t data[MAX_READ_SIZE];
81 } read_rsp;
82
insert_fd(int open_flags,int fd,struct storage_mapping_node * node)83 static uint32_t insert_fd(int open_flags, int fd, struct storage_mapping_node* node) {
84 uint32_t handle = fd;
85
86 if (handle < FD_TBL_SIZE) {
87 fd_state[fd] = SS_CLEAN; /* fd clean */
88 if (open_flags & O_TRUNC) {
89 assert(node == NULL);
90 fd_state[fd] = SS_DIRTY; /* set fd dirty */
91 }
92
93 if (node != NULL) {
94 fd_state[fd] = SS_CLEAN_NEED_SYMLINK;
95 }
96 } else {
97 ALOGW("%s: untracked fd %u\n", __func__, fd);
98 if (open_flags & (O_TRUNC | O_CREAT)) {
99 fs_state = SS_DIRTY;
100 }
101 }
102
103 if (node != NULL) {
104 node->fd = fd;
105 }
106
107 return handle;
108 }
109
clear_fd_symlink_status(uint32_t handle,struct storage_mapping_node * entry)110 static void clear_fd_symlink_status(uint32_t handle, struct storage_mapping_node* entry) {
111 /* Always clear FD, in case fd is not in FD_TBL */
112 entry->fd = -1;
113
114 if (handle >= FD_TBL_SIZE) {
115 ALOGE("%s: untracked fd=%u\n", __func__, handle);
116 return;
117 }
118
119 if (fd_state[handle] == SS_CLEAN_NEED_SYMLINK) {
120 fd_state[handle] = SS_CLEAN;
121 }
122 }
123
get_pending_symlink_mapping(uint32_t handle)124 static struct storage_mapping_node* get_pending_symlink_mapping(uint32_t handle) {
125 /* Fast lookup failure, is it in FD TBL */
126 if (handle < FD_TBL_SIZE && fd_state[handle] != SS_CLEAN_NEED_SYMLINK) {
127 return NULL;
128 }
129
130 /* Go find our mapping */
131 struct storage_mapping_node* curr = storage_mapping_head;
132 for (; curr != NULL; curr = curr->next) {
133 if (curr->fd == handle) {
134 return curr;
135 }
136 }
137
138 /* Safety check: state inconsistent if we get here with handle inside table range */
139 assert(handle >= FD_TBL_SIZE);
140
141 return NULL;
142 };
143
possibly_symlink_and_clear_mapping(uint32_t handle)144 static int possibly_symlink_and_clear_mapping(uint32_t handle) {
145 struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
146 if (entry == NULL) {
147 /* No mappings pending */
148 return 0;
149 }
150
151 /* Create full path */
152 char* path = NULL;
153 int rc = asprintf(&path, "%s/%s", ssdir_name, entry->file_name);
154 if (rc < 0) {
155 ALOGE("%s: asprintf failed\n", __func__);
156 return -1;
157 }
158
159 /* Try and setup the symlinking */
160 ALOGI("Creating symlink %s->%s\n", path, entry->backing_storage);
161 rc = symlink(entry->backing_storage, path);
162 if (rc < 0) {
163 ALOGE("%s: error symlinking %s->%s (%s)\n", __func__, path, entry->backing_storage,
164 strerror(errno));
165 free(path);
166 return rc;
167 }
168 free(path);
169
170 clear_fd_symlink_status(handle, entry);
171
172 return rc;
173 }
174
is_pending_symlink(uint32_t handle)175 static bool is_pending_symlink(uint32_t handle) {
176 struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
177 return entry != NULL;
178 }
179
lookup_fd(uint32_t handle,bool dirty)180 static int lookup_fd(uint32_t handle, bool dirty)
181 {
182 if (dirty) {
183 if (handle < FD_TBL_SIZE) {
184 fd_state[handle] = SS_DIRTY;
185 } else {
186 fs_state = SS_DIRTY;
187 }
188 }
189 return handle;
190 }
191
remove_fd(uint32_t handle)192 static int remove_fd(uint32_t handle)
193 {
194 /* Cleanup fd in symlink mapping if it exists */
195 struct storage_mapping_node* entry = get_pending_symlink_mapping(handle);
196 if (entry != NULL) {
197 entry->fd = -1;
198 }
199
200 if (handle < FD_TBL_SIZE) {
201 fd_state[handle] = SS_UNUSED; /* set to uninstalled */
202 }
203 return handle;
204 }
205
translate_errno(int error)206 static enum storage_err translate_errno(int error)
207 {
208 enum storage_err result;
209 switch (error) {
210 case 0:
211 result = STORAGE_NO_ERROR;
212 break;
213 case EBADF:
214 case EINVAL:
215 case ENOTDIR:
216 case EISDIR:
217 case ENAMETOOLONG:
218 result = STORAGE_ERR_NOT_VALID;
219 break;
220 case ENOENT:
221 result = STORAGE_ERR_NOT_FOUND;
222 break;
223 case EEXIST:
224 result = STORAGE_ERR_EXIST;
225 break;
226 case EPERM:
227 case EACCES:
228 result = STORAGE_ERR_ACCESS;
229 break;
230 default:
231 result = STORAGE_ERR_GENERIC;
232 break;
233 }
234
235 return result;
236 }
237
write_with_retry(int fd,const void * buf_,size_t size,off_t offset)238 static ssize_t write_with_retry(int fd, const void *buf_, size_t size, off_t offset)
239 {
240 ssize_t rc;
241 const uint8_t *buf = buf_;
242
243 while (size > 0) {
244 rc = TEMP_FAILURE_RETRY(pwrite(fd, buf, size, offset));
245 if (rc < 0)
246 return rc;
247 size -= rc;
248 buf += rc;
249 offset += rc;
250 }
251 return 0;
252 }
253
read_with_retry(int fd,void * buf_,size_t size,off_t offset)254 static ssize_t read_with_retry(int fd, void *buf_, size_t size, off_t offset)
255 {
256 ssize_t rc;
257 size_t rcnt = 0;
258 uint8_t *buf = buf_;
259
260 while (size > 0) {
261 rc = TEMP_FAILURE_RETRY(pread(fd, buf, size, offset));
262 if (rc < 0)
263 return rc;
264 if (rc == 0)
265 break;
266 size -= rc;
267 buf += rc;
268 offset += rc;
269 rcnt += rc;
270 }
271 return rcnt;
272 }
273
storage_file_delete(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)274 int storage_file_delete(struct storage_msg* msg, const void* r, size_t req_len,
275 struct watcher* watcher) {
276 char *path = NULL;
277 const struct storage_file_delete_req *req = r;
278
279 if (req_len < sizeof(*req)) {
280 ALOGE("%s: invalid request length (%zd < %zd)\n",
281 __func__, req_len, sizeof(*req));
282 msg->result = STORAGE_ERR_NOT_VALID;
283 goto err_response;
284 }
285
286 size_t fname_len = strlen(req->name);
287 if (fname_len != req_len - sizeof(*req)) {
288 ALOGE("%s: invalid filename length (%zd != %zd)\n",
289 __func__, fname_len, req_len - sizeof(*req));
290 msg->result = STORAGE_ERR_NOT_VALID;
291 goto err_response;
292 }
293
294 int rc = asprintf(&path, "%s/%s", ssdir_name, req->name);
295 if (rc < 0) {
296 ALOGE("%s: asprintf failed\n", __func__);
297 msg->result = STORAGE_ERR_GENERIC;
298 goto err_response;
299 }
300
301 watch_progress(watcher, "unlinking file");
302 rc = unlink(path);
303 if (rc < 0) {
304 rc = errno;
305 if (errno == ENOENT) {
306 ALOGV("%s: error (%d) unlinking file '%s'\n",
307 __func__, rc, path);
308 } else {
309 ALOGE("%s: error (%d) unlinking file '%s'\n",
310 __func__, rc, path);
311 }
312 msg->result = translate_errno(rc);
313 goto err_response;
314 }
315
316 ALOGV("%s: \"%s\"\n", __func__, path);
317 msg->result = STORAGE_NO_ERROR;
318
319 err_response:
320 if (path)
321 free(path);
322 return ipc_respond(msg, NULL, 0);
323 }
324
sync_parent(const char * path,struct watcher * watcher)325 static void sync_parent(const char* path, struct watcher* watcher) {
326 int parent_fd;
327 watch_progress(watcher, "syncing parent");
328 char* parent_path = dirname(path);
329 parent_fd = TEMP_FAILURE_RETRY(open(parent_path, O_RDONLY));
330 if (parent_fd >= 0) {
331 fsync(parent_fd);
332 close(parent_fd);
333 } else {
334 ALOGE("%s: failed to open parent directory \"%s\" for sync: %s\n", __func__, parent_path,
335 strerror(errno));
336 }
337 watch_progress(watcher, "done syncing parent");
338 }
339
get_storage_mapping_entry(const char * source)340 static struct storage_mapping_node* get_storage_mapping_entry(const char* source) {
341 struct storage_mapping_node* curr = storage_mapping_head;
342 for (; curr != NULL; curr = curr->next) {
343 if (!strcmp(source, curr->file_name)) {
344 ALOGI("Found backing file %s for %s\n", curr->backing_storage, source);
345 return curr;
346 }
347 }
348 return NULL;
349 }
350
is_backing_storage_mapped(const char * source)351 static bool is_backing_storage_mapped(const char* source) {
352 const struct storage_mapping_node* curr = storage_mapping_head;
353 for (; curr != NULL; curr = curr->next) {
354 if (!strcmp(source, curr->backing_storage)) {
355 ALOGI("Backed storage mapping exists for %s\n", curr->backing_storage);
356 return true;
357 }
358 }
359 return false;
360 }
361
362 /* Attempts to open a backed file, if mapped, without creating the symlink. Symlink will be created
363 * later on the first write. This allows us to continue reporting zero read sizes until the first
364 * write. */
open_possibly_mapped_file(const char * short_path,const char * full_path,int open_flags,struct storage_mapping_node ** entry)365 static int open_possibly_mapped_file(const char* short_path, const char* full_path, int open_flags,
366 struct storage_mapping_node** entry) {
367 /* See if mapping exists, report upstream if there is no mapping. */
368 struct storage_mapping_node* mapping_entry = get_storage_mapping_entry(short_path);
369 if (mapping_entry == NULL) {
370 return TEMP_FAILURE_RETRY(open(full_path, open_flags, S_IRUSR | S_IWUSR));
371 }
372
373 /* Check for existence of root path, we don't allow mappings during early boot */
374 struct stat buf = {0};
375 if (stat(ssdir_name, &buf) != 0) {
376 ALOGW("Root path not accessible yet, refuse to open mappings for now.\n");
377 return -1;
378 }
379
380 /* We don't support exclusive opening of mapped files */
381 if (open_flags & O_EXCL) {
382 ALOGE("Requesting exclusive open on backed storage isn't supported: %s\n", full_path);
383 return -1;
384 }
385
386 /* Try and open mapping file */
387 open_flags &= ~(O_CREAT | O_EXCL);
388 ALOGI("%s Attempting to open mapped file: %s\n", __func__, mapping_entry->backing_storage);
389 int fd =
390 TEMP_FAILURE_RETRY(open(mapping_entry->backing_storage, open_flags, S_IRUSR | S_IWUSR));
391 if (fd < 0) {
392 ALOGE("%s Failed to open mapping file: %s\n", __func__, mapping_entry->backing_storage);
393 return -1;
394 }
395
396 /* Let caller know which entry we used for opening */
397 *entry = mapping_entry;
398 return fd;
399 }
400
storage_file_open(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)401 int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len,
402 struct watcher* watcher) {
403 char* path = NULL;
404 const struct storage_file_open_req *req = r;
405 struct storage_file_open_resp resp = {0};
406 struct storage_mapping_node* mapping_entry = NULL;
407
408 if (req_len < sizeof(*req)) {
409 ALOGE("%s: invalid request length (%zd < %zd)\n",
410 __func__, req_len, sizeof(*req));
411 msg->result = STORAGE_ERR_NOT_VALID;
412 goto err_response;
413 }
414
415 size_t fname_len = strlen(req->name);
416 if (fname_len != req_len - sizeof(*req)) {
417 ALOGE("%s: invalid filename length (%zd != %zd)\n",
418 __func__, fname_len, req_len - sizeof(*req));
419 msg->result = STORAGE_ERR_NOT_VALID;
420 goto err_response;
421 }
422
423 /*
424 * TODO(b/210501710): Expose GSI image running state to vendor
425 * storageproxyd. We want to control data file paths in vendor_init, but we
426 * don't have access to the necessary property there yet. When we have
427 * access to that property we can set the root data path read-only and only
428 * allow creation of files in alternate/. Checking paths here temporarily
429 * until that is fixed.
430 *
431 * We are just checking for "/" instead of "alternate/" because we still
432 * want to still allow access to "persist/" in alternate mode (for now, this
433 * may change in the future).
434 */
435 if (alternate_mode && !strchr(req->name, '/')) {
436 ALOGE("%s: Cannot open root data file \"%s\" in alternate mode\n", __func__, req->name);
437 msg->result = STORAGE_ERR_ACCESS;
438 goto err_response;
439 }
440
441 int rc = asprintf(&path, "%s/%s", ssdir_name, req->name);
442 if (rc < 0) {
443 ALOGE("%s: asprintf failed\n", __func__);
444 msg->result = STORAGE_ERR_GENERIC;
445 goto err_response;
446 }
447
448 int open_flags = O_RDWR;
449
450 if (req->flags & STORAGE_FILE_OPEN_TRUNCATE)
451 open_flags |= O_TRUNC;
452
453 if (req->flags & STORAGE_FILE_OPEN_CREATE) {
454 /*
455 * Create the alternate parent dir if needed & allowed.
456 *
457 * TODO(b/210501710): Expose GSI image running state to vendor
458 * storageproxyd. This directory should be created by vendor_init, once
459 * it has access to the necessary bit of information.
460 */
461 if (strstr(req->name, ALTERNATE_DATA_DIR) == req->name) {
462 char* parent_path = dirname(path);
463 rc = mkdir(parent_path, S_IRWXU);
464 if (rc == 0) {
465 sync_parent(parent_path, watcher);
466 } else if (errno != EEXIST) {
467 ALOGE("%s: Could not create parent directory \"%s\": %s\n", __func__, parent_path,
468 strerror(errno));
469 }
470 }
471
472 /* open or create */
473 if (req->flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE) {
474 /* create exclusive */
475 open_flags |= O_CREAT | O_EXCL;
476
477 /* Look for and attempt opening a mapping, else just do normal open. */
478 rc = open_possibly_mapped_file(req->name, path, open_flags, &mapping_entry);
479 } else {
480 /* try open first */
481 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
482 if (rc == -1 && errno == ENOENT) {
483 /* then try open with O_CREATE */
484 open_flags |= O_CREAT;
485
486 /* Look for and attempt opening a mapping, else just do normal open. */
487 rc = open_possibly_mapped_file(req->name, path, open_flags, &mapping_entry);
488 }
489
490 }
491 } else {
492 /* open an existing file */
493 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
494 }
495
496 if (rc < 0) {
497 rc = errno;
498 if (errno == EEXIST || errno == ENOENT) {
499 ALOGV("%s: failed to open file \"%s\": %s\n",
500 __func__, path, strerror(errno));
501 } else {
502 ALOGE("%s: failed to open file \"%s\": %s\n",
503 __func__, path, strerror(errno));
504 }
505 msg->result = translate_errno(rc);
506 goto err_response;
507 }
508
509 if (open_flags & O_CREAT) {
510 sync_parent(path, watcher);
511 }
512
513 /* at this point rc contains storage file fd */
514 msg->result = STORAGE_NO_ERROR;
515 resp.handle = insert_fd(open_flags, rc, mapping_entry);
516 ALOGV("%s: \"%s\": fd = %u: handle = %d\n",
517 __func__, path, rc, resp.handle);
518
519 free(path);
520 path = NULL;
521
522 /* a backing file has been opened, notify any waiting init steps */
523 if (!fs_ready_initialized) {
524 rc = property_set(FS_READY_PROPERTY, "1");
525 if (rc == 0) {
526 fs_ready_initialized = true;
527 } else {
528 ALOGE("Could not set property %s, rc: %d\n", FS_READY_PROPERTY, rc);
529 }
530 }
531
532 return ipc_respond(msg, &resp, sizeof(resp));
533
534 err_response:
535 if (path)
536 free(path);
537 return ipc_respond(msg, NULL, 0);
538 }
539
storage_file_close(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)540 int storage_file_close(struct storage_msg* msg, const void* r, size_t req_len,
541 struct watcher* watcher) {
542 const struct storage_file_close_req *req = r;
543
544 if (req_len != sizeof(*req)) {
545 ALOGE("%s: invalid request length (%zd != %zd)\n",
546 __func__, req_len, sizeof(*req));
547 msg->result = STORAGE_ERR_NOT_VALID;
548 goto err_response;
549 }
550
551 int fd = remove_fd(req->handle);
552 ALOGV("%s: handle = %u: fd = %u\n", __func__, req->handle, fd);
553
554 watch_progress(watcher, "fsyncing before file close");
555 int rc = fsync(fd);
556 watch_progress(watcher, "done fsyncing before file close");
557 if (rc < 0) {
558 rc = errno;
559 ALOGE("%s: fsync failed for fd=%u: %s\n",
560 __func__, fd, strerror(errno));
561 msg->result = translate_errno(rc);
562 goto err_response;
563 }
564
565 rc = close(fd);
566 if (rc < 0) {
567 rc = errno;
568 ALOGE("%s: close failed for fd=%u: %s\n",
569 __func__, fd, strerror(errno));
570 msg->result = translate_errno(rc);
571 goto err_response;
572 }
573
574 msg->result = STORAGE_NO_ERROR;
575
576 err_response:
577 return ipc_respond(msg, NULL, 0);
578 }
579
storage_file_write(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)580 int storage_file_write(struct storage_msg* msg, const void* r, size_t req_len,
581 struct watcher* watcher) {
582 int rc;
583 const struct storage_file_write_req *req = r;
584
585 if (req_len < sizeof(*req)) {
586 ALOGE("%s: invalid request length (%zd < %zd)\n",
587 __func__, req_len, sizeof(*req));
588 msg->result = STORAGE_ERR_NOT_VALID;
589 goto err_response;
590 }
591
592 /* Handle any delayed symlinking for this handle if any */
593 rc = possibly_symlink_and_clear_mapping(req->handle);
594 if (rc < 0) {
595 ALOGE("Failed to symlink storage\n");
596 msg->result = STORAGE_ERR_GENERIC;
597 goto err_response;
598 }
599
600 int fd = lookup_fd(req->handle, true);
601 watch_progress(watcher, "writing");
602 if (write_with_retry(fd, &req->data[0], req_len - sizeof(*req),
603 req->offset) < 0) {
604 watch_progress(watcher, "writing done w/ error");
605 rc = errno;
606 ALOGW("%s: error writing file (fd=%d): %s\n",
607 __func__, fd, strerror(errno));
608 msg->result = translate_errno(rc);
609 goto err_response;
610 }
611 watch_progress(watcher, "writing done");
612
613 if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) {
614 rc = storage_sync_checkpoint(watcher);
615 if (rc < 0) {
616 msg->result = STORAGE_ERR_SYNC_FAILURE;
617 goto err_response;
618 }
619 }
620
621 msg->result = STORAGE_NO_ERROR;
622
623 err_response:
624 return ipc_respond(msg, NULL, 0);
625 }
626
storage_file_read(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)627 int storage_file_read(struct storage_msg* msg, const void* r, size_t req_len,
628 struct watcher* watcher) {
629 int rc;
630 const struct storage_file_read_req *req = r;
631
632 if (req_len != sizeof(*req)) {
633 ALOGE("%s: invalid request length (%zd != %zd)\n",
634 __func__, req_len, sizeof(*req));
635 msg->result = STORAGE_ERR_NOT_VALID;
636 goto err_response;
637 }
638
639 if (req->size > MAX_READ_SIZE) {
640 ALOGW("%s: request is too large (%u > %d) - refusing\n",
641 __func__, req->size, MAX_READ_SIZE);
642 msg->result = STORAGE_ERR_NOT_VALID;
643 goto err_response;
644 }
645
646 /* If this handle has a delayed symlink we should report 0 size reads until first write occurs
647 */
648 if (is_pending_symlink(req->handle)) {
649 ALOGI("Pending symlink: Forcing read result 0.\n");
650 msg->result = STORAGE_NO_ERROR;
651 return ipc_respond(msg, &read_rsp, sizeof(read_rsp.hdr));
652 }
653
654 int fd = lookup_fd(req->handle, false);
655 watch_progress(watcher, "reading");
656 ssize_t read_res = read_with_retry(fd, read_rsp.hdr.data, req->size,
657 (off_t)req->offset);
658 watch_progress(watcher, "reading done");
659 if (read_res < 0) {
660 rc = errno;
661 ALOGW("%s: error reading file (fd=%d): %s\n",
662 __func__, fd, strerror(errno));
663 msg->result = translate_errno(rc);
664 goto err_response;
665 }
666
667 msg->result = STORAGE_NO_ERROR;
668 return ipc_respond(msg, &read_rsp, read_res + sizeof(read_rsp.hdr));
669
670 err_response:
671 return ipc_respond(msg, NULL, 0);
672 }
673
storage_file_get_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)674 int storage_file_get_size(struct storage_msg* msg, const void* r, size_t req_len,
675 struct watcher* watcher) {
676 const struct storage_file_get_size_req *req = r;
677 struct storage_file_get_size_resp resp = {0};
678
679 if (req_len != sizeof(*req)) {
680 ALOGE("%s: invalid request length (%zd != %zd)\n",
681 __func__, req_len, sizeof(*req));
682 msg->result = STORAGE_ERR_NOT_VALID;
683 goto err_response;
684 }
685
686 struct stat stat;
687 int fd = lookup_fd(req->handle, false);
688 watch_progress(watcher, "fstat");
689 int rc = fstat(fd, &stat);
690 watch_progress(watcher, "fstat done");
691 if (rc < 0) {
692 rc = errno;
693 ALOGE("%s: error stat'ing file (fd=%d): %s\n",
694 __func__, fd, strerror(errno));
695 msg->result = translate_errno(rc);
696 goto err_response;
697 }
698
699 resp.size = stat.st_size;
700 msg->result = STORAGE_NO_ERROR;
701 return ipc_respond(msg, &resp, sizeof(resp));
702
703 err_response:
704 return ipc_respond(msg, NULL, 0);
705 }
706
storage_file_set_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)707 int storage_file_set_size(struct storage_msg* msg, const void* r, size_t req_len,
708 struct watcher* watcher) {
709 const struct storage_file_set_size_req *req = r;
710
711 if (req_len != sizeof(*req)) {
712 ALOGE("%s: invalid request length (%zd != %zd)\n",
713 __func__, req_len, sizeof(*req));
714 msg->result = STORAGE_ERR_NOT_VALID;
715 goto err_response;
716 }
717
718 int fd = lookup_fd(req->handle, true);
719 watch_progress(watcher, "ftruncate");
720 int rc = TEMP_FAILURE_RETRY(ftruncate(fd, req->size));
721 watch_progress(watcher, "ftruncate done");
722 if (rc < 0) {
723 rc = errno;
724 ALOGE("%s: error truncating file (fd=%d): %s\n",
725 __func__, fd, strerror(errno));
726 msg->result = translate_errno(rc);
727 goto err_response;
728 }
729
730 msg->result = STORAGE_NO_ERROR;
731
732 err_response:
733 return ipc_respond(msg, NULL, 0);
734 }
735
storage_file_get_max_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)736 int storage_file_get_max_size(struct storage_msg* msg, const void* r, size_t req_len,
737 struct watcher* watcher) {
738 const struct storage_file_get_max_size_req* req = r;
739 struct storage_file_get_max_size_resp resp = {0};
740 uint64_t max_size = 0;
741
742 if (req_len != sizeof(*req)) {
743 ALOGE("%s: invalid request length (%zd != %zd)\n", __func__, req_len, sizeof(*req));
744 msg->result = STORAGE_ERR_NOT_VALID;
745 goto err_response;
746 }
747
748 struct stat stat;
749 int fd = lookup_fd(req->handle, false);
750 watch_progress(watcher, "fstat to get max size");
751 int rc = fstat(fd, &stat);
752 watch_progress(watcher, "fstat to get max size done");
753 if (rc < 0) {
754 ALOGE("%s: error stat'ing file (fd=%d): %s\n", __func__, fd, strerror(errno));
755 goto err_response;
756 }
757
758 if ((stat.st_mode & S_IFMT) == S_IFBLK) {
759 rc = ioctl(fd, BLKGETSIZE64, &max_size);
760 if (rc < 0) {
761 rc = errno;
762 ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
763 msg->result = translate_errno(rc);
764 goto err_response;
765 }
766 } else {
767 max_size = max_file_size;
768 }
769
770 resp.max_size = max_size;
771 msg->result = STORAGE_NO_ERROR;
772 return ipc_respond(msg, &resp, sizeof(resp));
773
774 err_response:
775 return ipc_respond(msg, NULL, 0);
776 }
777
determine_max_file_size(const char * max_file_size_from)778 int determine_max_file_size(const char* max_file_size_from) {
779 /* Use default if none passed in */
780 if (max_file_size_from == NULL) {
781 ALOGI("No max file source given, continuing to use default: 0x%" PRIx64 "\n",
782 max_file_size);
783 return 0;
784 }
785
786 /* Check that max_file_size_from is part of our mapping list. */
787 if (!is_backing_storage_mapped(max_file_size_from)) {
788 ALOGE("%s: file doesn't match mapped storages (filename=%s)\n", __func__,
789 max_file_size_from);
790 return -1;
791 }
792
793 ALOGI("Using %s to determine max file size.\n", max_file_size_from);
794
795 /* Error if max file size source not found, possible misconfig. */
796 struct stat buf = {0};
797 int rc = stat(max_file_size_from, &buf);
798 if (rc < 0) {
799 ALOGE("%s: error stat'ing file (filename=%s): %s\n", __func__, max_file_size_from,
800 strerror(errno));
801 return -1;
802 }
803
804 /* Currently only support block device as max file size source */
805 if ((buf.st_mode & S_IFMT) != S_IFBLK) {
806 ALOGE("Unsupported max file size source type: %d\n", buf.st_mode);
807 return -1;
808 }
809
810 ALOGI("%s is a block device, determining block device size\n", max_file_size_from);
811 uint64_t max_size = 0;
812 int fd = TEMP_FAILURE_RETRY(open(max_file_size_from, O_RDONLY | O_NONBLOCK));
813 if (fd < 0) {
814 ALOGE("%s: failed to open backing file %s for ioctl: %s\n", __func__, max_file_size_from,
815 strerror(errno));
816 return -1;
817 }
818 rc = ioctl(fd, BLKGETSIZE64, &max_size);
819 if (rc < 0) {
820 ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
821 close(fd);
822 return -1;
823 }
824 close(fd);
825 max_file_size = max_size;
826
827 ALOGI("Using 0x%" PRIx64 " as max file size\n", max_file_size);
828 return 0;
829 }
830
storage_init(const char * dirname,struct storage_mapping_node * mappings,const char * max_file_size_from)831 int storage_init(const char* dirname, struct storage_mapping_node* mappings,
832 const char* max_file_size_from) {
833 /* If there is an active DSU image, use the alternate fs mode. */
834 alternate_mode = is_gsi_running();
835
836 fs_state = SS_CLEAN;
837 for (uint i = 0; i < FD_TBL_SIZE; i++) {
838 fd_state[i] = SS_UNUSED; /* uninstalled */
839 }
840
841 ssdir_name = dirname;
842
843 storage_mapping_head = mappings;
844
845 /* Set the max file size based on incoming configuration */
846 int rc = determine_max_file_size(max_file_size_from);
847 if (rc < 0) {
848 return rc;
849 }
850
851 return 0;
852 }
853
storage_sync_checkpoint(struct watcher * watcher)854 int storage_sync_checkpoint(struct watcher* watcher) {
855 int rc;
856
857 watch_progress(watcher, "sync fd table");
858 /* sync fd table and reset it to clean state first */
859 for (uint fd = 0; fd < FD_TBL_SIZE; fd++) {
860 if (fd_state[fd] == SS_DIRTY) {
861 if (fs_state == SS_CLEAN) {
862 /* need to sync individual fd */
863 rc = fsync(fd);
864 if (rc < 0) {
865 ALOGE("fsync for fd=%d failed: %s\n", fd, strerror(errno));
866 return rc;
867 }
868 }
869 fd_state[fd] = SS_CLEAN; /* set to clean */
870 }
871 }
872
873 /* check if we need to sync all filesystems */
874 if (fs_state == SS_DIRTY) {
875 /*
876 * We sync all filesystems here because we don't know what filesystem
877 * needs syncing if there happen to be other filesystems symlinked under
878 * the root data directory. This should not happen in the normal case
879 * because our fd table is large enough to handle the few open files we
880 * use.
881 */
882 watch_progress(watcher, "all fs sync");
883 sync();
884 fs_state = SS_CLEAN;
885 }
886
887 watch_progress(watcher, "done syncing");
888
889 return 0;
890 }
891