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 <cutils/properties.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <libgen.h>
21 #include <linux/fs.h>
22 #include <stdbool.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 #include "checkpoint_handling.h"
31 #include "ipc.h"
32 #include "log.h"
33 #include "storage.h"
34 #include "watchdog.h"
35
36 #define FD_TBL_SIZE 64
37 #define MAX_READ_SIZE 4096
38
39 #define ALTERNATE_DATA_DIR "alternate/"
40
41 /* Maximum file size for filesystem backed storage (i.e. not block dev backed storage) */
42 #define MAX_FILE_SIZE (0x10000000000)
43
44 enum sync_state {
45 SS_UNUSED = -1,
46 SS_CLEAN = 0,
47 SS_DIRTY = 1,
48 };
49
50 static const char *ssdir_name;
51
52 /*
53 * Property set to 1 after we have opened a file under ssdir_name. The backing
54 * files for both TD and TDP are currently located under /data/vendor/ss and can
55 * only be opened once userdata is mounted. This storageproxyd service is
56 * restarted when userdata is available, which causes the Trusty storage service
57 * to reconnect and attempt to open the backing files for TD and TDP. Once we
58 * set this property, other users can expect that the Trusty storage service
59 * ports will be available (although they may block if still being initialized),
60 * and connections will not be reset after this point (assuming the
61 * storageproxyd service stays running).
62 */
63 #define FS_READY_PROPERTY "ro.vendor.trusty.storage.fs_ready"
64
65 /* has FS_READY_PROPERTY been set? */
66 static bool fs_ready_initialized = false;
67
68 static enum sync_state fs_state;
69 static enum sync_state fd_state[FD_TBL_SIZE];
70
71 static bool alternate_mode;
72
73 static struct {
74 struct storage_file_read_resp hdr;
75 uint8_t data[MAX_READ_SIZE];
76 } read_rsp;
77
insert_fd(int open_flags,int fd)78 static uint32_t insert_fd(int open_flags, int fd)
79 {
80 uint32_t handle = fd;
81
82 if (handle < FD_TBL_SIZE) {
83 fd_state[fd] = SS_CLEAN; /* fd clean */
84 if (open_flags & O_TRUNC) {
85 fd_state[fd] = SS_DIRTY; /* set fd dirty */
86 }
87 } else {
88 ALOGW("%s: untracked fd %u\n", __func__, fd);
89 if (open_flags & (O_TRUNC | O_CREAT)) {
90 fs_state = SS_DIRTY;
91 }
92 }
93 return handle;
94 }
95
lookup_fd(uint32_t handle,bool dirty)96 static int lookup_fd(uint32_t handle, bool dirty)
97 {
98 if (dirty) {
99 if (handle < FD_TBL_SIZE) {
100 fd_state[handle] = SS_DIRTY;
101 } else {
102 fs_state = SS_DIRTY;
103 }
104 }
105 return handle;
106 }
107
remove_fd(uint32_t handle)108 static int remove_fd(uint32_t handle)
109 {
110 if (handle < FD_TBL_SIZE) {
111 fd_state[handle] = SS_UNUSED; /* set to uninstalled */
112 }
113 return handle;
114 }
115
translate_errno(int error)116 static enum storage_err translate_errno(int error)
117 {
118 enum storage_err result;
119 switch (error) {
120 case 0:
121 result = STORAGE_NO_ERROR;
122 break;
123 case EBADF:
124 case EINVAL:
125 case ENOTDIR:
126 case EISDIR:
127 case ENAMETOOLONG:
128 result = STORAGE_ERR_NOT_VALID;
129 break;
130 case ENOENT:
131 result = STORAGE_ERR_NOT_FOUND;
132 break;
133 case EEXIST:
134 result = STORAGE_ERR_EXIST;
135 break;
136 case EPERM:
137 case EACCES:
138 result = STORAGE_ERR_ACCESS;
139 break;
140 default:
141 result = STORAGE_ERR_GENERIC;
142 break;
143 }
144
145 return result;
146 }
147
write_with_retry(int fd,const void * buf_,size_t size,off_t offset)148 static ssize_t write_with_retry(int fd, const void *buf_, size_t size, off_t offset)
149 {
150 ssize_t rc;
151 const uint8_t *buf = buf_;
152
153 while (size > 0) {
154 rc = TEMP_FAILURE_RETRY(pwrite(fd, buf, size, offset));
155 if (rc < 0)
156 return rc;
157 size -= rc;
158 buf += rc;
159 offset += rc;
160 }
161 return 0;
162 }
163
read_with_retry(int fd,void * buf_,size_t size,off_t offset)164 static ssize_t read_with_retry(int fd, void *buf_, size_t size, off_t offset)
165 {
166 ssize_t rc;
167 size_t rcnt = 0;
168 uint8_t *buf = buf_;
169
170 while (size > 0) {
171 rc = TEMP_FAILURE_RETRY(pread(fd, buf, size, offset));
172 if (rc < 0)
173 return rc;
174 if (rc == 0)
175 break;
176 size -= rc;
177 buf += rc;
178 offset += rc;
179 rcnt += rc;
180 }
181 return rcnt;
182 }
183
storage_file_delete(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)184 int storage_file_delete(struct storage_msg* msg, const void* r, size_t req_len,
185 struct watcher* watcher) {
186 char *path = NULL;
187 const struct storage_file_delete_req *req = r;
188
189 if (req_len < sizeof(*req)) {
190 ALOGE("%s: invalid request length (%zd < %zd)\n",
191 __func__, req_len, sizeof(*req));
192 msg->result = STORAGE_ERR_NOT_VALID;
193 goto err_response;
194 }
195
196 size_t fname_len = strlen(req->name);
197 if (fname_len != req_len - sizeof(*req)) {
198 ALOGE("%s: invalid filename length (%zd != %zd)\n",
199 __func__, fname_len, req_len - sizeof(*req));
200 msg->result = STORAGE_ERR_NOT_VALID;
201 goto err_response;
202 }
203
204 int rc = asprintf(&path, "%s/%s", ssdir_name, req->name);
205 if (rc < 0) {
206 ALOGE("%s: asprintf failed\n", __func__);
207 msg->result = STORAGE_ERR_GENERIC;
208 goto err_response;
209 }
210
211 watch_progress(watcher, "unlinking file");
212 rc = unlink(path);
213 if (rc < 0) {
214 rc = errno;
215 if (errno == ENOENT) {
216 ALOGV("%s: error (%d) unlinking file '%s'\n",
217 __func__, rc, path);
218 } else {
219 ALOGE("%s: error (%d) unlinking file '%s'\n",
220 __func__, rc, path);
221 }
222 msg->result = translate_errno(rc);
223 goto err_response;
224 }
225
226 ALOGV("%s: \"%s\"\n", __func__, path);
227 msg->result = STORAGE_NO_ERROR;
228
229 err_response:
230 if (path)
231 free(path);
232 return ipc_respond(msg, NULL, 0);
233 }
234
sync_parent(const char * path,struct watcher * watcher)235 static void sync_parent(const char* path, struct watcher* watcher) {
236 int parent_fd;
237 watch_progress(watcher, "syncing parent");
238 char* parent_path = dirname(path);
239 parent_fd = TEMP_FAILURE_RETRY(open(parent_path, O_RDONLY));
240 if (parent_fd >= 0) {
241 fsync(parent_fd);
242 close(parent_fd);
243 } else {
244 ALOGE("%s: failed to open parent directory \"%s\" for sync: %s\n", __func__, parent_path,
245 strerror(errno));
246 }
247 watch_progress(watcher, "done syncing parent");
248 }
249
storage_file_open(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)250 int storage_file_open(struct storage_msg* msg, const void* r, size_t req_len,
251 struct watcher* watcher) {
252 char* path = NULL;
253 const struct storage_file_open_req *req = r;
254 struct storage_file_open_resp resp = {0};
255
256 if (req_len < sizeof(*req)) {
257 ALOGE("%s: invalid request length (%zd < %zd)\n",
258 __func__, req_len, sizeof(*req));
259 msg->result = STORAGE_ERR_NOT_VALID;
260 goto err_response;
261 }
262
263 size_t fname_len = strlen(req->name);
264 if (fname_len != req_len - sizeof(*req)) {
265 ALOGE("%s: invalid filename length (%zd != %zd)\n",
266 __func__, fname_len, req_len - sizeof(*req));
267 msg->result = STORAGE_ERR_NOT_VALID;
268 goto err_response;
269 }
270
271 /*
272 * TODO(b/210501710): Expose GSI image running state to vendor
273 * storageproxyd. We want to control data file paths in vendor_init, but we
274 * don't have access to the necessary property there yet. When we have
275 * access to that property we can set the root data path read-only and only
276 * allow creation of files in alternate/. Checking paths here temporarily
277 * until that is fixed.
278 *
279 * We are just checking for "/" instead of "alternate/" because we still
280 * want to still allow access to "persist/" in alternate mode (for now, this
281 * may change in the future).
282 */
283 if (alternate_mode && !strchr(req->name, '/')) {
284 ALOGE("%s: Cannot open root data file \"%s\" in alternate mode\n", __func__, req->name);
285 msg->result = STORAGE_ERR_ACCESS;
286 goto err_response;
287 }
288
289 int rc = asprintf(&path, "%s/%s", ssdir_name, req->name);
290 if (rc < 0) {
291 ALOGE("%s: asprintf failed\n", __func__);
292 msg->result = STORAGE_ERR_GENERIC;
293 goto err_response;
294 }
295
296 int open_flags = O_RDWR;
297
298 if (req->flags & STORAGE_FILE_OPEN_TRUNCATE)
299 open_flags |= O_TRUNC;
300
301 if (req->flags & STORAGE_FILE_OPEN_CREATE) {
302 /*
303 * Create the alternate parent dir if needed & allowed.
304 *
305 * TODO(b/210501710): Expose GSI image running state to vendor
306 * storageproxyd. This directory should be created by vendor_init, once
307 * it has access to the necessary bit of information.
308 */
309 if (strstr(req->name, ALTERNATE_DATA_DIR) == req->name) {
310 char* parent_path = dirname(path);
311 rc = mkdir(parent_path, S_IRWXU);
312 if (rc == 0) {
313 sync_parent(parent_path, watcher);
314 } else if (errno != EEXIST) {
315 ALOGE("%s: Could not create parent directory \"%s\": %s\n", __func__, parent_path,
316 strerror(errno));
317 }
318 }
319
320 /* open or create */
321 if (req->flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE) {
322 /* create exclusive */
323 open_flags |= O_CREAT | O_EXCL;
324 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
325 } else {
326 /* try open first */
327 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
328 if (rc == -1 && errno == ENOENT) {
329 /* then try open with O_CREATE */
330 open_flags |= O_CREAT;
331 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
332 }
333
334 }
335 } else {
336 /* open an existing file */
337 rc = TEMP_FAILURE_RETRY(open(path, open_flags, S_IRUSR | S_IWUSR));
338 }
339
340 if (rc < 0) {
341 rc = errno;
342 if (errno == EEXIST || errno == ENOENT) {
343 ALOGV("%s: failed to open file \"%s\": %s\n",
344 __func__, path, strerror(errno));
345 } else {
346 ALOGE("%s: failed to open file \"%s\": %s\n",
347 __func__, path, strerror(errno));
348 }
349 msg->result = translate_errno(rc);
350 goto err_response;
351 }
352
353 if (open_flags & O_CREAT) {
354 sync_parent(path, watcher);
355 }
356 free(path);
357
358 /* at this point rc contains storage file fd */
359 msg->result = STORAGE_NO_ERROR;
360 resp.handle = insert_fd(open_flags, rc);
361 ALOGV("%s: \"%s\": fd = %u: handle = %d\n",
362 __func__, path, rc, resp.handle);
363
364 /* a backing file has been opened, notify any waiting init steps */
365 if (!fs_ready_initialized) {
366 rc = property_set(FS_READY_PROPERTY, "1");
367 if (rc == 0) {
368 fs_ready_initialized = true;
369 } else {
370 ALOGE("Could not set property %s, rc: %d\n", FS_READY_PROPERTY, rc);
371 }
372 }
373
374 return ipc_respond(msg, &resp, sizeof(resp));
375
376 err_response:
377 if (path)
378 free(path);
379 return ipc_respond(msg, NULL, 0);
380 }
381
storage_file_close(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)382 int storage_file_close(struct storage_msg* msg, const void* r, size_t req_len,
383 struct watcher* watcher) {
384 const struct storage_file_close_req *req = r;
385
386 if (req_len != sizeof(*req)) {
387 ALOGE("%s: invalid request length (%zd != %zd)\n",
388 __func__, req_len, sizeof(*req));
389 msg->result = STORAGE_ERR_NOT_VALID;
390 goto err_response;
391 }
392
393 int fd = remove_fd(req->handle);
394 ALOGV("%s: handle = %u: fd = %u\n", __func__, req->handle, fd);
395
396 watch_progress(watcher, "fsyncing before file close");
397 int rc = fsync(fd);
398 watch_progress(watcher, "done fsyncing before file close");
399 if (rc < 0) {
400 rc = errno;
401 ALOGE("%s: fsync failed for fd=%u: %s\n",
402 __func__, fd, strerror(errno));
403 msg->result = translate_errno(rc);
404 goto err_response;
405 }
406
407 rc = close(fd);
408 if (rc < 0) {
409 rc = errno;
410 ALOGE("%s: close failed for fd=%u: %s\n",
411 __func__, fd, strerror(errno));
412 msg->result = translate_errno(rc);
413 goto err_response;
414 }
415
416 msg->result = STORAGE_NO_ERROR;
417
418 err_response:
419 return ipc_respond(msg, NULL, 0);
420 }
421
storage_file_write(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)422 int storage_file_write(struct storage_msg* msg, const void* r, size_t req_len,
423 struct watcher* watcher) {
424 int rc;
425 const struct storage_file_write_req *req = r;
426
427 if (req_len < sizeof(*req)) {
428 ALOGE("%s: invalid request length (%zd < %zd)\n",
429 __func__, req_len, sizeof(*req));
430 msg->result = STORAGE_ERR_NOT_VALID;
431 goto err_response;
432 }
433
434 int fd = lookup_fd(req->handle, true);
435 watch_progress(watcher, "writing");
436 if (write_with_retry(fd, &req->data[0], req_len - sizeof(*req),
437 req->offset) < 0) {
438 watch_progress(watcher, "writing done w/ error");
439 rc = errno;
440 ALOGW("%s: error writing file (fd=%d): %s\n",
441 __func__, fd, strerror(errno));
442 msg->result = translate_errno(rc);
443 goto err_response;
444 }
445 watch_progress(watcher, "writing done");
446
447 if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) {
448 rc = storage_sync_checkpoint(watcher);
449 if (rc < 0) {
450 msg->result = STORAGE_ERR_SYNC_FAILURE;
451 goto err_response;
452 }
453 }
454
455 msg->result = STORAGE_NO_ERROR;
456
457 err_response:
458 return ipc_respond(msg, NULL, 0);
459 }
460
storage_file_read(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)461 int storage_file_read(struct storage_msg* msg, const void* r, size_t req_len,
462 struct watcher* watcher) {
463 int rc;
464 const struct storage_file_read_req *req = r;
465
466 if (req_len != sizeof(*req)) {
467 ALOGE("%s: invalid request length (%zd != %zd)\n",
468 __func__, req_len, sizeof(*req));
469 msg->result = STORAGE_ERR_NOT_VALID;
470 goto err_response;
471 }
472
473 if (req->size > MAX_READ_SIZE) {
474 ALOGW("%s: request is too large (%u > %d) - refusing\n",
475 __func__, req->size, MAX_READ_SIZE);
476 msg->result = STORAGE_ERR_NOT_VALID;
477 goto err_response;
478 }
479
480 int fd = lookup_fd(req->handle, false);
481 watch_progress(watcher, "reading");
482 ssize_t read_res = read_with_retry(fd, read_rsp.hdr.data, req->size,
483 (off_t)req->offset);
484 watch_progress(watcher, "reading done");
485 if (read_res < 0) {
486 rc = errno;
487 ALOGW("%s: error reading file (fd=%d): %s\n",
488 __func__, fd, strerror(errno));
489 msg->result = translate_errno(rc);
490 goto err_response;
491 }
492
493 msg->result = STORAGE_NO_ERROR;
494 return ipc_respond(msg, &read_rsp, read_res + sizeof(read_rsp.hdr));
495
496 err_response:
497 return ipc_respond(msg, NULL, 0);
498 }
499
storage_file_get_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)500 int storage_file_get_size(struct storage_msg* msg, const void* r, size_t req_len,
501 struct watcher* watcher) {
502 const struct storage_file_get_size_req *req = r;
503 struct storage_file_get_size_resp resp = {0};
504
505 if (req_len != sizeof(*req)) {
506 ALOGE("%s: invalid request length (%zd != %zd)\n",
507 __func__, req_len, sizeof(*req));
508 msg->result = STORAGE_ERR_NOT_VALID;
509 goto err_response;
510 }
511
512 struct stat stat;
513 int fd = lookup_fd(req->handle, false);
514 watch_progress(watcher, "fstat");
515 int rc = fstat(fd, &stat);
516 watch_progress(watcher, "fstat done");
517 if (rc < 0) {
518 rc = errno;
519 ALOGE("%s: error stat'ing file (fd=%d): %s\n",
520 __func__, fd, strerror(errno));
521 msg->result = translate_errno(rc);
522 goto err_response;
523 }
524
525 resp.size = stat.st_size;
526 msg->result = STORAGE_NO_ERROR;
527 return ipc_respond(msg, &resp, sizeof(resp));
528
529 err_response:
530 return ipc_respond(msg, NULL, 0);
531 }
532
storage_file_set_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)533 int storage_file_set_size(struct storage_msg* msg, const void* r, size_t req_len,
534 struct watcher* watcher) {
535 const struct storage_file_set_size_req *req = r;
536
537 if (req_len != sizeof(*req)) {
538 ALOGE("%s: invalid request length (%zd != %zd)\n",
539 __func__, req_len, sizeof(*req));
540 msg->result = STORAGE_ERR_NOT_VALID;
541 goto err_response;
542 }
543
544 int fd = lookup_fd(req->handle, true);
545 watch_progress(watcher, "ftruncate");
546 int rc = TEMP_FAILURE_RETRY(ftruncate(fd, req->size));
547 watch_progress(watcher, "ftruncate done");
548 if (rc < 0) {
549 rc = errno;
550 ALOGE("%s: error truncating file (fd=%d): %s\n",
551 __func__, fd, strerror(errno));
552 msg->result = translate_errno(rc);
553 goto err_response;
554 }
555
556 msg->result = STORAGE_NO_ERROR;
557
558 err_response:
559 return ipc_respond(msg, NULL, 0);
560 }
561
storage_file_get_max_size(struct storage_msg * msg,const void * r,size_t req_len,struct watcher * watcher)562 int storage_file_get_max_size(struct storage_msg* msg, const void* r, size_t req_len,
563 struct watcher* watcher) {
564 const struct storage_file_get_max_size_req* req = r;
565 struct storage_file_get_max_size_resp resp = {0};
566 uint64_t max_size = 0;
567
568 if (req_len != sizeof(*req)) {
569 ALOGE("%s: invalid request length (%zd != %zd)\n", __func__, req_len, sizeof(*req));
570 msg->result = STORAGE_ERR_NOT_VALID;
571 goto err_response;
572 }
573
574 struct stat stat;
575 int fd = lookup_fd(req->handle, false);
576 watch_progress(watcher, "fstat to get max size");
577 int rc = fstat(fd, &stat);
578 watch_progress(watcher, "fstat to get max size done");
579 if (rc < 0) {
580 ALOGE("%s: error stat'ing file (fd=%d): %s\n", __func__, fd, strerror(errno));
581 goto err_response;
582 }
583
584 if ((stat.st_mode & S_IFMT) == S_IFBLK) {
585 rc = ioctl(fd, BLKGETSIZE64, &max_size);
586 if (rc < 0) {
587 rc = errno;
588 ALOGE("%s: error calling ioctl on file (fd=%d): %s\n", __func__, fd, strerror(errno));
589 msg->result = translate_errno(rc);
590 goto err_response;
591 }
592 } else {
593 max_size = MAX_FILE_SIZE;
594 }
595
596 resp.max_size = max_size;
597 msg->result = STORAGE_NO_ERROR;
598 return ipc_respond(msg, &resp, sizeof(resp));
599
600 err_response:
601 return ipc_respond(msg, NULL, 0);
602 }
603
storage_init(const char * dirname)604 int storage_init(const char *dirname)
605 {
606 /* If there is an active DSU image, use the alternate fs mode. */
607 alternate_mode = is_gsi_running();
608
609 fs_state = SS_CLEAN;
610 for (uint i = 0; i < FD_TBL_SIZE; i++) {
611 fd_state[i] = SS_UNUSED; /* uninstalled */
612 }
613
614 ssdir_name = dirname;
615 return 0;
616 }
617
storage_sync_checkpoint(struct watcher * watcher)618 int storage_sync_checkpoint(struct watcher* watcher) {
619 int rc;
620
621 watch_progress(watcher, "sync fd table");
622 /* sync fd table and reset it to clean state first */
623 for (uint fd = 0; fd < FD_TBL_SIZE; fd++) {
624 if (fd_state[fd] == SS_DIRTY) {
625 if (fs_state == SS_CLEAN) {
626 /* need to sync individual fd */
627 rc = fsync(fd);
628 if (rc < 0) {
629 ALOGE("fsync for fd=%d failed: %s\n", fd, strerror(errno));
630 return rc;
631 }
632 }
633 fd_state[fd] = SS_CLEAN; /* set to clean */
634 }
635 }
636
637 /* check if we need to sync all filesystems */
638 if (fs_state == SS_DIRTY) {
639 /*
640 * We sync all filesystems here because we don't know what filesystem
641 * needs syncing if there happen to be other filesystems symlinked under
642 * the root data directory. This should not happen in the normal case
643 * because our fd table is large enough to handle the few open files we
644 * use.
645 */
646 watch_progress(watcher, "all fs sync");
647 sync();
648 fs_state = SS_CLEAN;
649 }
650
651 watch_progress(watcher, "done syncing");
652
653 return 0;
654 }
655