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