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 return rc;
262 }
263
264 *session_p = (storage_session_t)rc;
265 return NO_ERROR;
266 }
267
storage_close_session(storage_session_t session)268 void storage_close_session(storage_session_t session) {
269 close(session);
270 }
271
storage_open_file(storage_session_t session,file_handle_t * handle_p,const char * name,uint32_t flags,uint32_t opflags)272 int storage_open_file(storage_session_t session,
273 file_handle_t* handle_p,
274 const char* name,
275 uint32_t flags,
276 uint32_t opflags) {
277 struct storage_msg msg = {.cmd = STORAGE_FILE_OPEN,
278 .flags = _to_msg_flags(opflags)};
279 struct storage_file_open_req req = {.flags = flags};
280 struct iovec tx[3] = {{&msg, sizeof(msg)},
281 {&req, sizeof(req)},
282 {(void*)name, strlen(name)}};
283 struct storage_file_open_resp rsp = {0};
284 struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
285
286 ssize_t rc = send_reqv(session, tx, 3, rx, 2);
287 rc = check_response(&msg, rc);
288 if (rc < 0)
289 return rc;
290
291 if ((size_t)rc != sizeof(rsp)) {
292 TLOGE("%s: invalid response length (%zd != %zd)\n", __func__,
293 (size_t)rc, sizeof(rsp));
294 return ERR_IO;
295 }
296 *handle_p = make_file_handle(session, rsp.handle);
297 return NO_ERROR;
298 }
299
storage_close_file(file_handle_t fh)300 void storage_close_file(file_handle_t fh) {
301 struct storage_msg msg = {.cmd = STORAGE_FILE_CLOSE};
302 struct storage_file_close_req req = {.handle = _to_handle(fh)};
303 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
304 struct iovec rx[1] = {{&msg, sizeof(msg)}};
305
306 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
307 rc = check_response(&msg, rc);
308 if (rc < 0) {
309 TLOGE("close file failed (%d)\n", (int)rc);
310 }
311 }
312
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)313 int storage_move_file(storage_session_t session,
314 file_handle_t handle,
315 const char* old_name,
316 const char* new_name,
317 uint32_t flags,
318 uint32_t opflags) {
319 size_t old_name_len = strlen(old_name);
320 size_t new_name_len = strlen(new_name);
321 struct storage_msg msg = {
322 .cmd = STORAGE_FILE_MOVE,
323 .flags = _to_msg_flags(opflags),
324 };
325 struct storage_file_move_req req = {
326 .flags = flags,
327 .handle = _to_handle(handle),
328 .old_name_len = old_name_len,
329 };
330 struct iovec tx[4] = {
331 {&msg, sizeof(msg)},
332 {&req, sizeof(req)},
333 {(void*)old_name, old_name_len},
334 {(void*)new_name, new_name_len},
335 };
336 struct iovec rx[1] = {{&msg, sizeof(msg)}};
337
338 ssize_t rc = send_reqv(session, tx, 4, rx, 1);
339 return (int)check_response(&msg, rc);
340 }
341
storage_delete_file(storage_session_t session,const char * name,uint32_t opflags)342 int storage_delete_file(storage_session_t session,
343 const char* name,
344 uint32_t opflags) {
345 struct storage_msg msg = {.cmd = STORAGE_FILE_DELETE,
346 .flags = _to_msg_flags(opflags)};
347 struct storage_file_delete_req req = {
348 .flags = 0,
349 };
350 struct iovec tx[3] = {{&msg, sizeof(msg)},
351 {&req, sizeof(req)},
352 {(void*)name, strlen(name)}};
353 struct iovec rx[1] = {{&msg, sizeof(msg)}};
354
355 ssize_t rc = send_reqv(session, tx, 3, rx, 1);
356 return (int)check_response(&msg, rc);
357 }
358
359 struct storage_open_dir_state {
360 uint8_t buf[MAX_CHUNK_SIZE];
361 size_t buf_size;
362 size_t buf_last_read;
363 size_t buf_read;
364 };
365
storage_open_dir(storage_session_t session,const char * path,struct storage_open_dir_state ** state)366 int storage_open_dir(storage_session_t session,
367 const char* path,
368 struct storage_open_dir_state** state) {
369 struct storage_file_list_resp* resp;
370
371 if (path && strlen(path)) {
372 return ERR_NOT_FOUND; /* current server does not support directories */
373 }
374 *state = malloc(sizeof(**state));
375 if (*state == NULL) {
376 return ERR_NO_MEMORY;
377 }
378 resp = (void*)(*state)->buf;
379 resp->flags = STORAGE_FILE_LIST_START;
380 (*state)->buf_size = sizeof(*resp);
381 (*state)->buf_last_read = 0;
382 (*state)->buf_read = (*state)->buf_size;
383
384 return 0;
385 }
386
storage_close_dir(storage_session_t session,struct storage_open_dir_state * state)387 void storage_close_dir(storage_session_t session,
388 struct storage_open_dir_state* state) {
389 free(state);
390 }
391
storage_read_dir_send_message(storage_session_t session,struct storage_open_dir_state * state)392 static int storage_read_dir_send_message(storage_session_t session,
393 struct storage_open_dir_state* state) {
394 struct storage_file_list_resp* last_item =
395 (void*)(state->buf + state->buf_last_read);
396 struct storage_msg msg = {.cmd = STORAGE_FILE_LIST};
397 struct storage_file_list_req req = {.flags = last_item->flags};
398 struct iovec tx[3] = {
399 {&msg, sizeof(msg)},
400 {&req, sizeof(req)},
401 };
402 uint32_t tx_count = 2;
403 struct iovec rx[2] = {{&msg, sizeof(msg)},
404 {state->buf, sizeof(state->buf)}};
405 ssize_t rc;
406
407 if (last_item->flags != STORAGE_FILE_LIST_START) {
408 tx[2].iov_base = last_item->name;
409 tx[2].iov_len = strlen(last_item->name);
410 tx_count = 3;
411 }
412
413 rc = send_reqv(session, tx, tx_count, rx, 2);
414 rc = check_response(&msg, rc);
415
416 state->buf_size = (rc > 0) ? rc : 0;
417 state->buf_last_read = 0;
418 state->buf_read = 0;
419
420 if (rc < 0)
421 return rc;
422
423 return 0;
424 }
425
storage_read_dir(storage_session_t session,struct storage_open_dir_state * state,uint8_t * flags,char * name,size_t name_out_size)426 int storage_read_dir(storage_session_t session,
427 struct storage_open_dir_state* state,
428 uint8_t* flags,
429 char* name,
430 size_t name_out_size) {
431 int ret;
432 size_t rem;
433 size_t name_size;
434 struct storage_file_list_resp* item;
435
436 if (state->buf_size == 0) {
437 return ERR_IO;
438 }
439
440 if (state->buf_read >= state->buf_size) {
441 ret = storage_read_dir_send_message(session, state);
442 if (ret) {
443 return ret;
444 }
445 }
446 rem = state->buf_size - state->buf_read;
447 if (rem < sizeof(*item)) {
448 TLOGE("got short response\n");
449 return ERR_IO;
450 }
451 item = (void*)(state->buf + state->buf_read);
452 rem -= sizeof(*item);
453
454 *flags = item->flags;
455 if ((item->flags & STORAGE_FILE_LIST_STATE_MASK) == STORAGE_FILE_LIST_END) {
456 state->buf_size = 0;
457 name_size = 0;
458 } else {
459 name_size = strnlen(item->name, rem) + 1;
460 if (name_size > rem) {
461 TLOGE("got invalid filename size %zd >= %zd\n", name_size, rem);
462 return ERR_IO;
463 }
464 if (name_size >= name_out_size) {
465 return ERR_NOT_ENOUGH_BUFFER;
466 }
467 strcpy(name, item->name);
468 }
469
470 state->buf_last_read = state->buf_read;
471 state->buf_read += sizeof(*item) + name_size;
472
473 return name_size;
474 }
475
_read_chunk(file_handle_t fh,storage_off_t off,void * buf,size_t size)476 static ssize_t _read_chunk(file_handle_t fh,
477 storage_off_t off,
478 void* buf,
479 size_t size) {
480 struct storage_msg msg = {.cmd = STORAGE_FILE_READ};
481 struct storage_file_read_req req = {
482 .handle = _to_handle(fh),
483 .size = size,
484 .offset = off,
485 };
486 struct iovec tx[2] = {
487 {&msg, sizeof(msg)},
488 {&req, sizeof(req)},
489 };
490 struct iovec rx[2] = {
491 {&msg, sizeof(msg)},
492 {buf, size},
493 };
494
495 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
496 return check_response(&msg, rc);
497 }
498
storage_read(file_handle_t fh,storage_off_t off,void * buf,size_t size)499 ssize_t storage_read(file_handle_t fh,
500 storage_off_t off,
501 void* buf,
502 size_t size) {
503 ssize_t rc;
504 size_t bytes_read = 0;
505 size_t chunk = MAX_CHUNK_SIZE;
506 uint8_t* ptr = buf;
507
508 while (size) {
509 if (chunk > size)
510 chunk = size;
511 rc = _read_chunk(fh, off, ptr, chunk);
512 if (rc < 0)
513 return rc;
514 if (rc == 0)
515 break;
516 off += rc;
517 ptr += rc;
518 bytes_read += rc;
519 size -= rc;
520 }
521 return bytes_read;
522 }
523
_write_req(file_handle_t fh,storage_off_t off,const void * buf,size_t size,uint32_t msg_flags)524 static ssize_t _write_req(file_handle_t fh,
525 storage_off_t off,
526 const void* buf,
527 size_t size,
528 uint32_t msg_flags) {
529 struct storage_msg msg = {
530 .cmd = STORAGE_FILE_WRITE,
531 .flags = msg_flags,
532 };
533 struct storage_file_write_req req = {
534 .handle = _to_handle(fh),
535 .offset = off,
536 };
537 struct iovec tx[3] = {
538 {&msg, sizeof(msg)}, {&req, sizeof(req)}, {(void*)buf, size}};
539 struct iovec rx[1] = {{&msg, sizeof(msg)}};
540
541 ssize_t rc = send_reqv(_to_session(fh), tx, 3, rx, 1);
542 rc = check_response(&msg, rc);
543 return rc < 0 ? rc : (ssize_t)size;
544 }
545
storage_write(file_handle_t fh,storage_off_t off,const void * buf,size_t size,uint32_t opflags)546 ssize_t storage_write(file_handle_t fh,
547 storage_off_t off,
548 const void* buf,
549 size_t size,
550 uint32_t opflags) {
551 ssize_t rc;
552 size_t bytes_written = 0;
553 size_t chunk = MAX_CHUNK_SIZE;
554 const uint8_t* ptr = buf;
555 uint32_t msg_flags = _to_msg_flags(opflags & ~STORAGE_OP_COMPLETE);
556
557 while (size) {
558 if (chunk >= size) {
559 /* last chunk in sequence */
560 chunk = size;
561 msg_flags = _to_msg_flags(opflags);
562 }
563 rc = _write_req(fh, off, ptr, chunk, msg_flags);
564 if (rc < 0)
565 return rc;
566 if ((size_t)rc != chunk) {
567 TLOGE("got partial write (%d)\n", (int)rc);
568 return ERR_IO;
569 }
570 off += chunk;
571 ptr += chunk;
572 bytes_written += chunk;
573 size -= chunk;
574 }
575 return bytes_written;
576 }
577
storage_set_file_size(file_handle_t fh,storage_off_t file_size,uint32_t opflags)578 int storage_set_file_size(file_handle_t fh,
579 storage_off_t file_size,
580 uint32_t opflags) {
581 struct storage_msg msg = {.cmd = STORAGE_FILE_SET_SIZE,
582 .flags = _to_msg_flags(opflags)};
583 struct storage_file_set_size_req req = {
584 .handle = _to_handle(fh),
585 .size = file_size,
586 };
587 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
588 struct iovec rx[1] = {{&msg, sizeof(msg)}};
589
590 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 1);
591 return (int)check_response(&msg, rc);
592 }
593
storage_get_file_size(file_handle_t fh,storage_off_t * size_p)594 int storage_get_file_size(file_handle_t fh, storage_off_t* size_p) {
595 struct storage_msg msg = {.cmd = STORAGE_FILE_GET_SIZE};
596 struct storage_file_get_size_req req = {
597 .handle = _to_handle(fh),
598 };
599 struct iovec tx[2] = {{&msg, sizeof(msg)}, {&req, sizeof(req)}};
600 struct storage_file_get_size_resp rsp;
601 struct iovec rx[2] = {{&msg, sizeof(msg)}, {&rsp, sizeof(rsp)}};
602
603 ssize_t rc = send_reqv(_to_session(fh), tx, 2, rx, 2);
604 rc = check_response(&msg, rc);
605 if (rc < 0)
606 return rc;
607
608 if ((size_t)rc != sizeof(rsp)) {
609 TLOGE("%s: invalid response length (%zd != %zd)\n", __func__,
610 (size_t)rc, sizeof(rsp));
611 return ERR_IO;
612 }
613
614 *size_p = rsp.size;
615 return NO_ERROR;
616 }
617
storage_end_transaction(storage_session_t session,bool complete)618 int storage_end_transaction(storage_session_t session, bool complete) {
619 struct storage_msg msg = {
620 .cmd = STORAGE_END_TRANSACTION,
621 .flags = complete ? STORAGE_MSG_FLAG_TRANSACT_COMPLETE : 0,
622 };
623 struct iovec iov = {&msg, sizeof(msg)};
624
625 ssize_t rc = send_reqv(session, &iov, 1, &iov, 1);
626 return (int)check_response(&msg, rc);
627 }
628
storage_commit_checkpoint(storage_session_t session)629 int storage_commit_checkpoint(storage_session_t session) {
630 struct storage_msg msg = {
631 .cmd = STORAGE_END_TRANSACTION,
632 .flags = STORAGE_MSG_FLAG_TRANSACT_COMPLETE |
633 STORAGE_MSG_FLAG_TRANSACT_CHECKPOINT,
634 };
635 struct iovec iov = {&msg, sizeof(msg)};
636
637 ssize_t rc = send_reqv(session, &iov, 1, &iov, 1);
638 return (int)check_response(&msg, rc);
639 }
640