1 /*
2 * Copyright (C) 2015-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
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <trusty_ipc.h>
21
22 #define TLOG_TAG "storage_client"
23 #include <trusty_log.h>
24
25 #include <uapi/err.h>
26
27 #include <lib/storage/storage.h>
28
29 #define TLOGE_APP_NAME(fmt, ...) TLOGE("%s: " fmt, __progname, ##__VA_ARGS__)
30
31 #define MAX_CHUNK_SIZE 4040
32
33 /* At what delay threshold should wait_infinite_logged() start logging? */
34 #define WAIT_INFINITE_LOG_THRESHOLD_MSEC 1000
35
36 /* Maximum timeout value to use for wait_infinite_logged */
37 #define WAIT_INFINITE_LOG_MAX_TIMEOUT_MSEC 60000
38
39 /* Initialized by __init_libc in ./trusty/musl/src/env/__libc_start_main.c */
40 extern char* __progname;
41
make_file_handle(storage_session_t s,uint32_t fid)42 static inline file_handle_t make_file_handle(storage_session_t s,
43 uint32_t fid) {
44 return ((uint64_t)s << 32) | fid;
45 }
46
_to_session(file_handle_t fh)47 static inline storage_session_t _to_session(file_handle_t fh) {
48 return (storage_session_t)(fh >> 32);
49 }
50
_to_handle(file_handle_t fh)51 static inline uint32_t _to_handle(file_handle_t fh) {
52 return (uint32_t)fh;
53 }
54
_to_msg_flags(uint32_t opflags)55 static inline uint32_t _to_msg_flags(uint32_t opflags) {
56 uint32_t msg_flags = 0;
57
58 if (opflags & STORAGE_OP_COMPLETE)
59 msg_flags |= STORAGE_MSG_FLAG_TRANSACT_COMPLETE;
60
61 if (opflags & STORAGE_OP_CHECKPOINT) {
62 if ((msg_flags & STORAGE_MSG_FLAG_TRANSACT_COMPLETE) == 0) {
63 TLOGE("STORAGE_OP_CHECKPOINT only valid when committing a checkpoint\n");
64 }
65 msg_flags |= STORAGE_MSG_FLAG_TRANSACT_CHECKPOINT;
66 }
67
68 if (opflags & STORAGE_OP_FS_REPAIRED_ACK) {
69 msg_flags |= STORAGE_MSG_FLAG_FS_REPAIRED_ACK;
70 }
71
72 return msg_flags;
73 }
74
check_response(struct storage_msg * msg,ssize_t res)75 static ssize_t check_response(struct storage_msg* msg, ssize_t res) {
76 if (res < 0)
77 return res;
78
79 if ((size_t)res < sizeof(*msg)) {
80 TLOGE("invalid msg length (%zd < %zd)\n", (size_t)res, sizeof(*msg));
81 return ERR_IO;
82 }
83
84 /* TLOGI("cmd 0x%x: server returned %u\n", msg->cmd, msg->result); */
85
86 switch (msg->result) {
87 case STORAGE_NO_ERROR:
88 return res - sizeof(*msg);
89
90 case STORAGE_ERR_NOT_FOUND:
91 return ERR_NOT_FOUND;
92
93 case STORAGE_ERR_EXIST:
94 return ERR_ALREADY_EXISTS;
95
96 case STORAGE_ERR_NOT_VALID:
97 return ERR_NOT_VALID;
98
99 case STORAGE_ERR_NOT_ALLOWED:
100 return ERR_NOT_ALLOWED;
101
102 case STORAGE_ERR_TRANSACT:
103 return ERR_BUSY;
104
105 case STORAGE_ERR_ACCESS:
106 return ERR_ACCESS_DENIED;
107
108 case STORAGE_ERR_FS_REPAIRED:
109 return ERR_BAD_STATE;
110
111 case STORAGE_ERR_UNIMPLEMENTED:
112 TLOGE("cmd 0x%x: is unhandles command\n", msg->cmd);
113 return ERR_NOT_IMPLEMENTED;
114
115 case STORAGE_ERR_GENERIC:
116 TLOGE("cmd 0x%x: internal server error\n", msg->cmd);
117 return ERR_GENERIC;
118
119 default:
120 TLOGE("cmd 0x%x: unhandled server response %u\n", msg->cmd,
121 msg->result);
122 }
123
124 return ERR_IO;
125 }
126
wait_infinite_logged(storage_session_t session,uevent_t * ev,const char * caller)127 int wait_infinite_logged(storage_session_t session,
128 uevent_t* ev,
129 const char* caller) {
130 unsigned long wait_time = WAIT_INFINITE_LOG_THRESHOLD_MSEC;
131
132 /* wait for reply */
133 int rc;
134 do {
135 rc = wait(session, ev, wait_time);
136 if (rc == ERR_TIMED_OUT) {
137 TLOGE_APP_NAME(
138 "Timed out after %ldx milliseconds, retrying; "
139 "called by %s\n",
140 wait_time, caller);
141 wait_time = wait_time * 2;
142 if (wait_time > WAIT_INFINITE_LOG_MAX_TIMEOUT_MSEC) {
143 wait_time = WAIT_INFINITE_LOG_MAX_TIMEOUT_MSEC;
144 }
145 }
146 } while (rc == ERR_TIMED_OUT);
147
148 if (wait_time != WAIT_INFINITE_LOG_THRESHOLD_MSEC) {
149 TLOGE_APP_NAME(
150 "Finally succeeded (last wait: < %ldx milliseconds); "
151 "called by %s\n",
152 wait_time, caller);
153 }
154
155 return rc;
156 }
157
get_response(storage_session_t session,struct iovec * rx_iovs,uint32_t rx_iovcnt)158 static ssize_t get_response(storage_session_t session,
159 struct iovec* rx_iovs,
160 uint32_t rx_iovcnt)
161
162 {
163 uevent_t ev;
164 struct ipc_msg_info mi;
165 struct ipc_msg rx_msg = {
166 .iov = rx_iovs,
167 .num_iov = rx_iovcnt,
168 };
169
170 if (!rx_iovcnt)
171 return 0;
172
173 /* wait for reply */
174 int rc = wait_infinite_logged(session, &ev, __func__);
175 if (rc != NO_ERROR) {
176 TLOGE("%s: interrupted waiting for response", __func__);
177 return rc;
178 }
179
180 rc = get_msg(session, &mi);
181 if (rc != NO_ERROR) {
182 TLOGE("%s: failed to get_msg (%d)\n", __func__, rc);
183 return rc;
184 }
185
186 rc = read_msg(session, mi.id, 0, &rx_msg);
187 put_msg(session, mi.id);
188 if (rc < 0) {
189 TLOGE("%s: failed to read msg (%d)\n", __func__, rc);
190 return rc;
191 }
192
193 if ((size_t)rc != mi.len) {
194 TLOGE("%s: partial message read (%zd vs. %zd)\n", __func__, (size_t)rc,
195 mi.len);
196 return ERR_IO;
197 }
198
199 return rc;
200 }
201
wait_to_send(handle_t session,struct ipc_msg * msg)202 static int wait_to_send(handle_t session, struct ipc_msg* msg) {
203 int rc;
204 struct uevent ev;
205
206 rc = wait_infinite_logged(session, &ev, __func__);
207 if (rc < 0) {
208 TLOGE("failed to wait for outgoing queue to free up\n");
209 return rc;
210 }
211
212 if (ev.event & IPC_HANDLE_POLL_SEND_UNBLOCKED) {
213 return send_msg(session, msg);
214 }
215
216 if (ev.event & IPC_HANDLE_POLL_MSG) {
217 return ERR_BUSY;
218 }
219
220 if (ev.event & IPC_HANDLE_POLL_HUP) {
221 return ERR_CHANNEL_CLOSED;
222 }
223
224 return rc;
225 }
226
send_reqv(storage_session_t session,struct iovec * tx_iovs,uint32_t tx_iovcnt,struct iovec * rx_iovs,uint32_t rx_iovcnt)227 ssize_t send_reqv(storage_session_t session,
228 struct iovec* tx_iovs,
229 uint32_t tx_iovcnt,
230 struct iovec* rx_iovs,
231 uint32_t rx_iovcnt) {
232 ssize_t rc;
233
234 struct ipc_msg tx_msg = {
235 .iov = tx_iovs,
236 .num_iov = tx_iovcnt,
237 };
238
239 rc = send_msg(session, &tx_msg);
240 if (rc == ERR_NOT_ENOUGH_BUFFER) {
241 rc = wait_to_send(session, &tx_msg);
242 }
243
244 if (rc < 0) {
245 TLOGE("%s: failed (%d) to send_msg\n", __func__, (int)rc);
246 return rc;
247 }
248
249 rc = get_response(session, rx_iovs, rx_iovcnt);
250 if (rc < 0) {
251 TLOGI("%s: failed (%d) to get response\n", __func__, (int)rc);
252 return rc;
253 }
254
255 return rc;
256 }
257
storage_open_session(storage_session_t * session_p,const char * type)258 int storage_open_session(storage_session_t* session_p, const char* type) {
259 long rc = connect(type, IPC_CONNECT_WAIT_FOR_PORT);
260 if (rc < 0) {
261 *session_p = STORAGE_INVALID_SESSION;
262 return rc;
263 }
264
265 *session_p = (storage_session_t)rc;
266 return NO_ERROR;
267 }
268
storage_close_session(storage_session_t session)269 void storage_close_session(storage_session_t session) {
270 close(session);
271 }
272
storage_open_file(storage_session_t session,file_handle_t * handle_p,const char * name,uint32_t flags,uint32_t opflags)273 int storage_open_file(storage_session_t session,
274 file_handle_t* handle_p,
275 const char* name,
276 uint32_t flags,
277 uint32_t opflags) {
278 struct storage_msg msg = {.cmd = STORAGE_FILE_OPEN,
279 .flags = _to_msg_flags(opflags)};
280 struct storage_file_open_req req = {.flags = flags};
281 struct iovec tx[3] = {{&msg, sizeof(msg)},
282 {&req, sizeof(req)},
283 {(void*)name, strlen(name)}};
284 struct storage_file_open_resp rsp = {0};
285 struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
286
287 *handle_p = make_file_handle(STORAGE_INVALID_SESSION, 0);
288
289 ssize_t rc = send_reqv(session, tx, 3, rx, 2);
290 rc = check_response(&msg, rc);
291 if (rc < 0)
292 return rc;
293
294 if ((size_t)rc != sizeof(rsp)) {
295 TLOGE("%s: invalid response length (%zd != %zd)\n", __func__,
296 (size_t)rc, sizeof(rsp));
297 return ERR_IO;
298 }
299 *handle_p = make_file_handle(session, rsp.handle);
300 return NO_ERROR;
301 }
302
storage_close_file(file_handle_t fh)303 void storage_close_file(file_handle_t fh) {
304 struct storage_msg msg = {.cmd = STORAGE_FILE_CLOSE};
305 struct storage_file_close_req req = {.handle = _to_handle(fh)};
306 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
307 struct iovec rx[1] = {{&msg, sizeof(msg)}};
308
309 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
310 rc = check_response(&msg, rc);
311 if (rc < 0) {
312 TLOGE("close file failed (%d)\n", (int)rc);
313 }
314 }
315
storage_move_file(storage_session_t session,file_handle_t handle,const char * old_name,const char * new_name,uint32_t flags,uint32_t opflags)316 int storage_move_file(storage_session_t session,
317 file_handle_t handle,
318 const char* old_name,
319 const char* new_name,
320 uint32_t flags,
321 uint32_t opflags) {
322 size_t old_name_len = strlen(old_name);
323 size_t new_name_len = strlen(new_name);
324 struct storage_msg msg = {
325 .cmd = STORAGE_FILE_MOVE,
326 .flags = _to_msg_flags(opflags),
327 };
328 struct storage_file_move_req req = {
329 .flags = flags,
330 .handle = _to_handle(handle),
331 .old_name_len = old_name_len,
332 };
333 struct iovec tx[4] = {
334 {&msg, sizeof(msg)},
335 {&req, sizeof(req)},
336 {(void*)old_name, old_name_len},
337 {(void*)new_name, new_name_len},
338 };
339 struct iovec rx[1] = {{&msg, sizeof(msg)}};
340
341 ssize_t rc = send_reqv(session, tx, 4, rx, 1);
342 return (int)check_response(&msg, rc);
343 }
344
storage_delete_file(storage_session_t session,const char * name,uint32_t opflags)345 int storage_delete_file(storage_session_t session,
346 const char* name,
347 uint32_t opflags) {
348 struct storage_msg msg = {.cmd = STORAGE_FILE_DELETE,
349 .flags = _to_msg_flags(opflags)};
350 struct storage_file_delete_req req = {
351 .flags = 0,
352 };
353 struct iovec tx[3] = {{&msg, sizeof(msg)},
354 {&req, sizeof(req)},
355 {(void*)name, strlen(name)}};
356 struct iovec rx[1] = {{&msg, sizeof(msg)}};
357
358 ssize_t rc = send_reqv(session, tx, 3, rx, 1);
359 return (int)check_response(&msg, rc);
360 }
361
362 struct storage_open_dir_state {
363 uint8_t buf[MAX_CHUNK_SIZE];
364 size_t buf_size;
365 size_t buf_last_read;
366 size_t buf_read;
367 };
368
storage_open_dir(storage_session_t session,const char * path,struct storage_open_dir_state ** state)369 int storage_open_dir(storage_session_t session,
370 const char* path,
371 struct storage_open_dir_state** state) {
372 struct storage_file_list_resp* resp;
373
374 if (path && strlen(path)) {
375 *state = NULL;
376 return ERR_NOT_FOUND; /* current server does not support directories */
377 }
378 *state = malloc(sizeof(**state));
379 if (*state == NULL) {
380 return ERR_NO_MEMORY;
381 }
382 resp = (void*)(*state)->buf;
383 resp->flags = STORAGE_FILE_LIST_START;
384 (*state)->buf_size = sizeof(*resp);
385 (*state)->buf_last_read = 0;
386 (*state)->buf_read = (*state)->buf_size;
387
388 return 0;
389 }
390
storage_close_dir(storage_session_t session,struct storage_open_dir_state * state)391 void storage_close_dir(storage_session_t session,
392 struct storage_open_dir_state* state) {
393 free(state);
394 }
395
storage_read_dir_send_message(storage_session_t session,struct storage_open_dir_state * state)396 static int storage_read_dir_send_message(storage_session_t session,
397 struct storage_open_dir_state* state) {
398 struct storage_file_list_resp* last_item =
399 (void*)(state->buf + state->buf_last_read);
400 struct storage_msg msg = {.cmd = STORAGE_FILE_LIST};
401 struct storage_file_list_req req = {.flags = last_item->flags};
402 struct iovec tx[3] = {
403 {&msg, sizeof(msg)},
404 {&req, sizeof(req)},
405 };
406 uint32_t tx_count = 2;
407 struct iovec rx[2] = {{&msg, sizeof(msg)},
408 {state->buf, sizeof(state->buf)}};
409 ssize_t rc;
410
411 if (last_item->flags != STORAGE_FILE_LIST_START) {
412 tx[2].iov_base = last_item->name;
413 tx[2].iov_len = strlen(last_item->name);
414 tx_count = 3;
415 }
416
417 rc = send_reqv(session, tx, tx_count, rx, 2);
418 rc = check_response(&msg, rc);
419
420 state->buf_size = (rc > 0) ? rc : 0;
421 state->buf_last_read = 0;
422 state->buf_read = 0;
423
424 if (rc < 0)
425 return rc;
426
427 return 0;
428 }
429
storage_read_dir(storage_session_t session,struct storage_open_dir_state * state,uint8_t * flags,char * name,size_t name_out_size)430 int storage_read_dir(storage_session_t session,
431 struct storage_open_dir_state* state,
432 uint8_t* flags,
433 char* name,
434 size_t name_out_size) {
435 int ret;
436 size_t rem;
437 size_t name_size;
438 struct storage_file_list_resp* item;
439
440 if (state->buf_size == 0) {
441 return ERR_IO;
442 }
443
444 if (state->buf_read >= state->buf_size) {
445 ret = storage_read_dir_send_message(session, state);
446 if (ret) {
447 return ret;
448 }
449 }
450 rem = state->buf_size - state->buf_read;
451 if (rem < sizeof(*item)) {
452 TLOGE("got short response\n");
453 return ERR_IO;
454 }
455 item = (void*)(state->buf + state->buf_read);
456 rem -= sizeof(*item);
457
458 *flags = item->flags;
459 if ((item->flags & STORAGE_FILE_LIST_STATE_MASK) == STORAGE_FILE_LIST_END) {
460 state->buf_size = 0;
461 name_size = 0;
462 } else {
463 name_size = strnlen(item->name, rem) + 1;
464 if (name_size > rem) {
465 TLOGE("got invalid filename size %zd >= %zd\n", name_size, rem);
466 return ERR_IO;
467 }
468 if (name_size >= name_out_size) {
469 return ERR_NOT_ENOUGH_BUFFER;
470 }
471 strcpy(name, item->name);
472 }
473
474 state->buf_last_read = state->buf_read;
475 state->buf_read += sizeof(*item) + name_size;
476
477 return name_size;
478 }
479
_read_chunk(file_handle_t fh,storage_off_t off,void * buf,size_t size)480 static ssize_t _read_chunk(file_handle_t fh,
481 storage_off_t off,
482 void* buf,
483 size_t size) {
484 struct storage_msg msg = {.cmd = STORAGE_FILE_READ};
485 struct storage_file_read_req req = {
486 .handle = _to_handle(fh),
487 .size = size,
488 .offset = off,
489 };
490 struct iovec tx[2] = {
491 {&msg, sizeof(msg)},
492 {&req, sizeof(req)},
493 };
494 struct iovec rx[2] = {
495 {&msg, sizeof(msg)},
496 {buf, size},
497 };
498
499 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
500 return check_response(&msg, rc);
501 }
502
storage_read(file_handle_t fh,storage_off_t off,void * buf,size_t size)503 ssize_t storage_read(file_handle_t fh,
504 storage_off_t off,
505 void* buf,
506 size_t size) {
507 ssize_t rc;
508 size_t bytes_read = 0;
509 size_t chunk = MAX_CHUNK_SIZE;
510 uint8_t* ptr = buf;
511
512 while (size) {
513 if (chunk > size)
514 chunk = size;
515 rc = _read_chunk(fh, off, ptr, chunk);
516 if (rc < 0)
517 return rc;
518 if (rc == 0)
519 break;
520 off += rc;
521 ptr += rc;
522 bytes_read += rc;
523 size -= rc;
524 }
525 return bytes_read;
526 }
527
_write_req(file_handle_t fh,storage_off_t off,const void * buf,size_t size,uint32_t msg_flags)528 static ssize_t _write_req(file_handle_t fh,
529 storage_off_t off,
530 const void* buf,
531 size_t size,
532 uint32_t msg_flags) {
533 struct storage_msg msg = {
534 .cmd = STORAGE_FILE_WRITE,
535 .flags = msg_flags,
536 };
537 struct storage_file_write_req req = {
538 .handle = _to_handle(fh),
539 .offset = off,
540 };
541 struct iovec tx[3] = {
542 {&msg, sizeof(msg)}, {&req, sizeof(req)}, {(void*)buf, size}};
543 struct iovec rx[1] = {{&msg, sizeof(msg)}};
544
545 ssize_t rc = send_reqv(_to_session(fh), tx, 3, rx, 1);
546 rc = check_response(&msg, rc);
547 return rc < 0 ? rc : (ssize_t)size;
548 }
549
storage_write(file_handle_t fh,storage_off_t off,const void * buf,size_t size,uint32_t opflags)550 ssize_t storage_write(file_handle_t fh,
551 storage_off_t off,
552 const void* buf,
553 size_t size,
554 uint32_t opflags) {
555 ssize_t rc;
556 size_t bytes_written = 0;
557 size_t chunk = MAX_CHUNK_SIZE;
558 const uint8_t* ptr = buf;
559 uint32_t msg_flags = _to_msg_flags(opflags & ~STORAGE_OP_COMPLETE);
560
561 while (size) {
562 if (chunk >= size) {
563 /* last chunk in sequence */
564 chunk = size;
565 msg_flags = _to_msg_flags(opflags);
566 }
567 rc = _write_req(fh, off, ptr, chunk, msg_flags);
568 if (rc < 0)
569 return rc;
570 if ((size_t)rc != chunk) {
571 TLOGE("got partial write (%d)\n", (int)rc);
572 return ERR_IO;
573 }
574 off += chunk;
575 ptr += chunk;
576 bytes_written += chunk;
577 size -= chunk;
578 }
579 return bytes_written;
580 }
581
storage_set_file_size(file_handle_t fh,storage_off_t file_size,uint32_t opflags)582 int storage_set_file_size(file_handle_t fh,
583 storage_off_t file_size,
584 uint32_t opflags) {
585 struct storage_msg msg = {.cmd = STORAGE_FILE_SET_SIZE,
586 .flags = _to_msg_flags(opflags)};
587 struct storage_file_set_size_req req = {
588 .handle = _to_handle(fh),
589 .size = file_size,
590 };
591 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
592 struct iovec rx[1] = {{&msg, sizeof(msg)}};
593
594 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
595 return (int)check_response(&msg, rc);
596 }
597
storage_get_file_size(file_handle_t fh,storage_off_t * size_p)598 int storage_get_file_size(file_handle_t fh, storage_off_t* size_p) {
599 struct storage_msg msg = {.cmd = STORAGE_FILE_GET_SIZE};
600 struct storage_file_get_size_req req = {
601 .handle = _to_handle(fh),
602 };
603 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
604 struct storage_file_get_size_resp rsp;
605 struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
606
607 *size_p = 0;
608
609 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
610 rc = check_response(&msg, rc);
611 if (rc < 0)
612 return rc;
613
614 if ((size_t)rc != sizeof(rsp)) {
615 TLOGE("%s: invalid response length (%zd != %zd)\n", __func__,
616 (size_t)rc, sizeof(rsp));
617 return ERR_IO;
618 }
619
620 *size_p = rsp.size;
621 return NO_ERROR;
622 }
623
storage_end_transaction(storage_session_t session,bool complete)624 int storage_end_transaction(storage_session_t session, bool complete) {
625 struct storage_msg msg = {
626 .cmd = STORAGE_END_TRANSACTION,
627 .flags = complete ? STORAGE_MSG_FLAG_TRANSACT_COMPLETE : 0,
628 };
629 struct iovec iov = {&msg, sizeof(msg)};
630
631 ssize_t rc = send_reqv(session, &iov, 1, &iov, 1);
632 return (int)check_response(&msg, rc);
633 }
634
storage_commit_checkpoint(storage_session_t session)635 int storage_commit_checkpoint(storage_session_t session) {
636 struct storage_msg msg = {
637 .cmd = STORAGE_END_TRANSACTION,
638 .flags = STORAGE_MSG_FLAG_TRANSACT_COMPLETE |
639 STORAGE_MSG_FLAG_TRANSACT_CHECKPOINT,
640 };
641 struct iovec iov = {&msg, sizeof(msg)};
642
643 ssize_t rc = send_reqv(session, &iov, 1, &iov, 1);
644 return (int)check_response(&msg, rc);
645 }
646