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