sys: use "Auto-Installed" field for packagelist
[project/rpcd.git] / file.c
1 /*
2 * rpcd - UBUS RPC server
3 *
4 * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
5 * Copyright (C) 2016 Luka Perkov <luka@openwrt.org>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #define _GNU_SOURCE
21
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <limits.h>
29 #include <dirent.h>
30 #include <sys/stat.h>
31 #include <sys/wait.h>
32 #include <libubus.h>
33 #include <libubox/blobmsg.h>
34 #include <libubox/md5.h>
35 #include <libubox/ustream.h>
36 #include <libubox/utils.h>
37
38 #include <rpcd/plugin.h>
39
40 /* limit of sys & proc files */
41 #define RPC_FILE_MIN_SIZE (4096)
42
43 /* limit of regular files and command output data */
44 #define RPC_FILE_MAX_SIZE (4096 * 64)
45
46 /* limit of command line length for exec acl checks */
47 #define RPC_CMDLINE_MAX_SIZE (1024)
48
49 #define ustream_for_each_read_buffer(stream, ptr, len) \
50 for (ptr = ustream_get_read_buf(stream, &len); \
51 ptr != NULL && len > 0; \
52 ustream_consume(stream, len), ptr = ustream_get_read_buf(stream, &len))
53
54 #define ustream_declare(us, fd, name) \
55 us.stream.string_data = true; \
56 us.stream.r.buffer_len = 4096; \
57 us.stream.r.max_buffers = RPC_FILE_MAX_SIZE / 4096; \
58 us.stream.notify_read = rpc_file_##name##_read_cb; \
59 us.stream.notify_state = rpc_file_##name##_state_cb; \
60 ustream_fd_init(&us, fd);
61
62 static const struct rpc_daemon_ops *ops;
63
64 struct rpc_file_exec_context {
65 struct ubus_context *context;
66 struct ubus_request_data request;
67 struct uloop_timeout timeout;
68 struct uloop_process process;
69 struct ustream_fd opipe;
70 struct ustream_fd epipe;
71 int stat;
72 };
73
74
75 static struct blob_buf buf;
76 static char *canonpath;
77 static char cmdstr[RPC_CMDLINE_MAX_SIZE];
78
79 enum {
80 RPC_F_R_PATH,
81 RPC_F_R_SESSION,
82 __RPC_F_R_MAX,
83 };
84
85 static const struct blobmsg_policy rpc_file_R_policy[__RPC_F_R_MAX] = {
86 [RPC_F_R_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
87 [RPC_F_R_SESSION] = { .name = "ubus_rpc_session",
88 .type = BLOBMSG_TYPE_STRING },
89 };
90
91 enum {
92 RPC_F_RB_PATH,
93 RPC_F_RB_BASE64,
94 RPC_F_RB_SESSION,
95 __RPC_F_RB_MAX,
96 };
97
98 static const struct blobmsg_policy rpc_file_RB_policy[__RPC_F_RB_MAX] = {
99 [RPC_F_RB_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
100 [RPC_F_RB_BASE64] = { .name = "base64", .type = BLOBMSG_TYPE_BOOL },
101 [RPC_F_RB_SESSION] = { .name = "ubus_rpc_session",
102 .type = BLOBMSG_TYPE_STRING },
103 };
104
105 enum {
106 RPC_F_RW_PATH,
107 RPC_F_RW_DATA,
108 RPC_F_RW_APPEND,
109 RPC_F_RW_MODE,
110 RPC_F_RW_BASE64,
111 RPC_F_RW_SESSION,
112 __RPC_F_RW_MAX,
113 };
114
115 static const struct blobmsg_policy rpc_file_RW_policy[__RPC_F_RW_MAX] = {
116 [RPC_F_RW_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
117 [RPC_F_RW_DATA] = { .name = "data", .type = BLOBMSG_TYPE_STRING },
118 [RPC_F_RW_APPEND] = { .name = "append", .type = BLOBMSG_TYPE_BOOL },
119 [RPC_F_RW_MODE] = { .name = "mode", .type = BLOBMSG_TYPE_INT32 },
120 [RPC_F_RW_BASE64] = { .name = "base64", .type = BLOBMSG_TYPE_BOOL },
121 [RPC_F_RW_SESSION] = { .name = "ubus_rpc_session",
122 .type = BLOBMSG_TYPE_STRING },
123 };
124
125 enum {
126 RPC_E_CMD,
127 RPC_E_PARM,
128 RPC_E_ENV,
129 RPC_E_SESSION,
130 __RPC_E_MAX,
131 };
132
133 static const struct blobmsg_policy rpc_exec_policy[__RPC_E_MAX] = {
134 [RPC_E_CMD] = { .name = "command", .type = BLOBMSG_TYPE_STRING },
135 [RPC_E_PARM] = { .name = "params", .type = BLOBMSG_TYPE_ARRAY },
136 [RPC_E_ENV] = { .name = "env", .type = BLOBMSG_TYPE_TABLE },
137 [RPC_E_SESSION] = { .name = "ubus_rpc_session",
138 .type = BLOBMSG_TYPE_STRING },
139 };
140
141 static const char *d_types[] = {
142 [DT_BLK] = "block",
143 [DT_CHR] = "char",
144 [DT_DIR] = "directory",
145 [DT_FIFO] = "fifo",
146 [DT_LNK] = "symlink",
147 [DT_REG] = "file",
148 [DT_SOCK] = "socket",
149 [DT_UNKNOWN] = "unknown",
150 };
151
152
153 static int
154 rpc_errno_status(void)
155 {
156 switch (errno)
157 {
158 case EACCES:
159 return UBUS_STATUS_PERMISSION_DENIED;
160
161 case ENOTDIR:
162 return UBUS_STATUS_INVALID_ARGUMENT;
163
164 case ENOENT:
165 return UBUS_STATUS_NOT_FOUND;
166
167 case EINVAL:
168 return UBUS_STATUS_INVALID_ARGUMENT;
169
170 default:
171 return UBUS_STATUS_UNKNOWN_ERROR;
172 }
173 }
174
175 static bool
176 rpc_file_access(const struct blob_attr *sid,
177 const char *path, const char *perm)
178 {
179 if (!sid)
180 return true;
181
182 return ops->session_access(blobmsg_data(sid), "file", path, perm);
183 }
184
185 static char *
186 rpc_canonicalize_path(const char *path)
187 {
188 char *cp;
189 const char *p;
190
191 if (path == NULL || *path == '\0')
192 return NULL;
193
194 if (canonpath != NULL)
195 free(canonpath);
196
197 canonpath = strdup(path);
198
199 if (canonpath == NULL)
200 return NULL;
201
202 /* normalize */
203 for (cp = canonpath, p = path; *p != '\0'; ) {
204 if (*p != '/')
205 goto next;
206
207 /* skip repeating / */
208 if (p[1] == '/') {
209 p++;
210 continue;
211 }
212
213 /* /./ or /../ */
214 if (p[1] == '.') {
215 /* skip /./ */
216 if ((p[2] == '\0') || (p[2] == '/')) {
217 p += 2;
218 continue;
219 }
220
221 /* collapse /x/../ */
222 if ((p[2] == '.') && ((p[3] == '\0') || (p[3] == '/'))) {
223 while ((cp > canonpath) && (*--cp != '/'))
224 ;
225
226 p += 3;
227 continue;
228 }
229 }
230
231 next:
232 *cp++ = *p++;
233 }
234
235 /* remove trailing slash if not root / */
236 if ((cp > canonpath + 1) && (cp[-1] == '/'))
237 cp--;
238 else if (cp == canonpath)
239 *cp++ = '/';
240
241 *cp = '\0';
242
243 return canonpath;
244 }
245
246 static struct blob_attr **
247 __rpc_check_path(const struct blobmsg_policy *policy, size_t policy_len,
248 int policy_path_idx, int policy_sid_idx, const char *perm,
249 struct blob_attr *msg, char **path, struct stat *s)
250 {
251 static struct blob_attr *tb[__RPC_F_RW_MAX]; /* largest _MAX constant */
252
253 blobmsg_parse(policy, policy_len, tb, blob_data(msg), blob_len(msg));
254
255 if (!tb[policy_path_idx])
256 {
257 errno = EINVAL;
258 return NULL;
259 }
260
261 *path = rpc_canonicalize_path(blobmsg_get_string(tb[policy_path_idx]));
262
263 if (*path == NULL)
264 {
265 errno = ENOMEM;
266 return NULL;
267 }
268
269 if (!rpc_file_access(tb[policy_sid_idx], *path, perm))
270 {
271 errno = EACCES;
272 return NULL;
273 }
274
275 if (s != NULL && stat(*path, s) != 0)
276 return NULL;
277
278 return tb;
279 }
280
281 #define rpc_check_path(msg, policy_selector, perm, path, s) \
282 __rpc_check_path(rpc_file_ ## policy_selector ## _policy, \
283 ARRAY_SIZE(rpc_file_ ## policy_selector ## _policy), \
284 RPC_F_ ## policy_selector ## _PATH, \
285 RPC_F_ ## policy_selector ## _SESSION, \
286 perm, msg, path, s)
287
288 static int
289 rpc_file_read(struct ubus_context *ctx, struct ubus_object *obj,
290 struct ubus_request_data *req, const char *method,
291 struct blob_attr *msg)
292 {
293 struct blob_attr **tb;
294 bool base64 = false;
295 int fd, rv;
296 ssize_t len;
297 char *path;
298 struct stat s;
299 char *wbuf;
300
301 tb = rpc_check_path(msg, RB, "read", &path, &s);
302
303 if (tb == NULL)
304 return rpc_errno_status();
305
306 if (s.st_size >= RPC_FILE_MAX_SIZE)
307 return UBUS_STATUS_NOT_SUPPORTED;
308
309 if ((fd = open(path, O_RDONLY)) < 0)
310 return rpc_errno_status();
311
312 /* some sysfs files do not report a length */
313 if (s.st_size == 0)
314 s.st_size = RPC_FILE_MIN_SIZE;
315
316 blob_buf_init(&buf, 0);
317
318 if (tb[RPC_F_RB_BASE64])
319 base64 = blobmsg_get_bool(tb[RPC_F_RB_BASE64]);
320
321 len = s.st_size + 1;
322 if (base64)
323 len = B64_ENCODE_LEN(s.st_size);
324 wbuf = blobmsg_alloc_string_buffer(&buf, "data", len);
325
326 if (!wbuf)
327 {
328 rv = UBUS_STATUS_UNKNOWN_ERROR;
329 goto out;
330 }
331
332 if ((len = read(fd, wbuf, s.st_size)) <= 0)
333 {
334 rv = UBUS_STATUS_NO_DATA;
335 goto out;
336 }
337
338 if (base64)
339 {
340 uint8_t *data = calloc(len, sizeof(uint8_t));
341 if (!data)
342 {
343 rv = UBUS_STATUS_UNKNOWN_ERROR;
344 goto out;
345 }
346 memcpy(data, wbuf, len);
347
348 len = b64_encode(data, len, wbuf, B64_ENCODE_LEN(len));
349 free(data);
350 if (len < 0)
351 {
352 rv = UBUS_STATUS_UNKNOWN_ERROR;
353 goto out;
354 }
355 }
356
357 *(wbuf + len) = '\0';
358 blobmsg_add_string_buffer(&buf);
359
360 ubus_send_reply(ctx, req, buf.head);
361 rv = UBUS_STATUS_OK;
362
363 out:
364 blob_buf_free(&buf);
365 close(fd);
366 return rv;
367 }
368
369 static int
370 rpc_file_write(struct ubus_context *ctx, struct ubus_object *obj,
371 struct ubus_request_data *req, const char *method,
372 struct blob_attr *msg)
373 {
374 struct blob_attr **tb;
375 int append = O_TRUNC;
376 mode_t prev_mode, mode = 0666;
377 int fd, rv = 0;
378 char *path = NULL;
379 void *data = NULL;
380 ssize_t data_len = 0;
381
382 tb = rpc_check_path(msg, RW, "write", &path, NULL);
383
384 if (tb == NULL)
385 return rpc_errno_status();
386
387 if (!tb[RPC_F_RW_DATA])
388 return UBUS_STATUS_INVALID_ARGUMENT;
389
390 data = blobmsg_data(tb[RPC_F_RW_DATA]);
391 data_len = blobmsg_data_len(tb[RPC_F_RW_DATA]) - 1;
392
393 if (tb[RPC_F_RW_APPEND] && blobmsg_get_bool(tb[RPC_F_RW_APPEND]))
394 append = O_APPEND;
395
396 if (tb[RPC_F_RW_MODE])
397 mode = blobmsg_get_u32(tb[RPC_F_RW_MODE]);
398
399 prev_mode = umask(0);
400 fd = open(path, O_CREAT | O_WRONLY | append, mode);
401 umask(prev_mode);
402 if (fd < 0)
403 return rpc_errno_status();
404
405 if (tb[RPC_F_RW_BASE64] && blobmsg_get_bool(tb[RPC_F_RW_BASE64]))
406 {
407 data_len = b64_decode(data, data, data_len);
408 if (data_len < 0)
409 {
410 rv = UBUS_STATUS_UNKNOWN_ERROR;
411 goto out;
412 }
413 }
414
415 if (write(fd, data, data_len) < 0)
416 rv = -1;
417
418 out:
419 if (fsync(fd) < 0)
420 rv = -1;
421
422 close(fd);
423 sync();
424
425 if (rv)
426 return rpc_errno_status();
427
428 return 0;
429 }
430
431 static int
432 rpc_file_md5(struct ubus_context *ctx, struct ubus_object *obj,
433 struct ubus_request_data *req, const char *method,
434 struct blob_attr *msg)
435 {
436 int rv, i;
437 char *path;
438 struct stat s;
439 uint8_t md5[16];
440 char *wbuf;
441
442 if (!rpc_check_path(msg, R, "read", &path, &s))
443 return rpc_errno_status();
444
445 if (!S_ISREG(s.st_mode))
446 return UBUS_STATUS_NOT_SUPPORTED;
447
448 if ((rv = md5sum(path, md5)) <= 0)
449 return rpc_errno_status();
450
451 blob_buf_init(&buf, 0);
452 wbuf = blobmsg_alloc_string_buffer(&buf, "md5", 33);
453
454 for (i = 0; i < 16; i++)
455 sprintf(wbuf + (i * 2), "%02x", (uint8_t) md5[i]);
456
457 blobmsg_add_string_buffer(&buf);
458 ubus_send_reply(ctx, req, buf.head);
459 blob_buf_free(&buf);
460
461 return UBUS_STATUS_OK;
462 }
463
464 static void
465 _rpc_file_add_stat(struct stat *s)
466 {
467 int type;
468
469 type = S_ISREG(s->st_mode) ? DT_REG :
470 S_ISDIR(s->st_mode) ? DT_DIR :
471 S_ISCHR(s->st_mode) ? DT_CHR :
472 S_ISBLK(s->st_mode) ? DT_BLK :
473 S_ISFIFO(s->st_mode) ? DT_FIFO :
474 S_ISLNK(s->st_mode) ? DT_LNK :
475 S_ISSOCK(s->st_mode) ? DT_SOCK :
476 DT_UNKNOWN;
477
478 blobmsg_add_string(&buf, "type", d_types[type]);
479 blobmsg_add_u32(&buf, "size", s->st_size);
480 blobmsg_add_u32(&buf, "mode", s->st_mode);
481 blobmsg_add_u32(&buf, "atime", s->st_atime);
482 blobmsg_add_u32(&buf, "mtime", s->st_mtime);
483 blobmsg_add_u32(&buf, "ctime", s->st_ctime);
484 blobmsg_add_u32(&buf, "inode", s->st_ino);
485 blobmsg_add_u32(&buf, "uid", s->st_uid);
486 blobmsg_add_u32(&buf, "gid", s->st_gid);
487 }
488
489 static int
490 rpc_file_list(struct ubus_context *ctx, struct ubus_object *obj,
491 struct ubus_request_data *req, const char *method,
492 struct blob_attr *msg)
493 {
494 DIR *fd;
495 void *c, *d;
496 struct stat s;
497 struct dirent *e;
498 char *path, *entrypath;
499
500 if (!rpc_check_path(msg, R, "list", &path, NULL))
501 return rpc_errno_status();
502
503 if ((fd = opendir(path)) == NULL)
504 return rpc_errno_status();
505
506 blob_buf_init(&buf, 0);
507 c = blobmsg_open_array(&buf, "entries");
508
509 while ((e = readdir(fd)) != NULL)
510 {
511 if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
512 continue;
513
514 if (asprintf(&entrypath, "%s/%s", path, e->d_name) < 0)
515 continue;
516
517 if (!stat(entrypath, &s))
518 {
519 d = blobmsg_open_table(&buf, NULL);
520 blobmsg_add_string(&buf, "name", e->d_name);
521 _rpc_file_add_stat(&s);
522 blobmsg_close_table(&buf, d);
523 }
524
525 free(entrypath);
526 }
527
528 closedir(fd);
529
530 blobmsg_close_array(&buf, c);
531 ubus_send_reply(ctx, req, buf.head);
532 blob_buf_free(&buf);
533
534 return 0;
535 }
536
537 static int
538 rpc_file_stat(struct ubus_context *ctx, struct ubus_object *obj,
539 struct ubus_request_data *req, const char *method,
540 struct blob_attr *msg)
541 {
542 char *path;
543 struct stat s;
544
545 if (!rpc_check_path(msg, R, "list", &path, &s))
546 return rpc_errno_status();
547
548 blob_buf_init(&buf, 0);
549
550 blobmsg_add_string(&buf, "path", path);
551 _rpc_file_add_stat(&s);
552
553 ubus_send_reply(ctx, req, buf.head);
554 blob_buf_free(&buf);
555
556 return 0;
557 }
558
559 static int
560 rpc_file_remove_recursive(const char *path);
561
562 static int
563 rpc_file_remove_recursive(const char *path)
564 {
565 DIR *fd;
566 int err = 0;
567 struct stat s;
568 struct dirent *e;
569 char *entrypath;
570
571 if ((fd = opendir(path)) == NULL)
572 return rpc_errno_status();
573
574 for (e = readdir(fd); e != NULL && err == 0; e = readdir(fd))
575 {
576 if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, ".."))
577 continue;
578
579 if (asprintf(&entrypath, "%s/%s", path, e->d_name) >= 0)
580 {
581 if (!lstat(entrypath, &s))
582 {
583 if (S_ISDIR(s.st_mode))
584 err = rpc_file_remove_recursive(entrypath);
585 else if (unlink(entrypath))
586 err = rpc_errno_status();
587 }
588
589 free(entrypath);
590 }
591 else
592 {
593 err = UBUS_STATUS_UNKNOWN_ERROR;
594 }
595 }
596
597 closedir(fd);
598
599 if (!err && rmdir(path))
600 return rpc_errno_status();
601
602 return err;
603 }
604
605 static int
606 rpc_file_remove(struct ubus_context *ctx, struct ubus_object *obj,
607 struct ubus_request_data *req, const char *method,
608 struct blob_attr *msg)
609 {
610 struct stat s;
611 char *path = NULL;
612
613 if (!rpc_check_path(msg, R, "write", &path, NULL))
614 return rpc_errno_status();
615
616 if (lstat(path, &s))
617 return rpc_errno_status();
618
619 if (S_ISDIR(s.st_mode))
620 return rpc_file_remove_recursive(path);
621
622 if (unlink(path))
623 return rpc_errno_status();
624
625 return 0;
626 }
627
628 static const char *
629 rpc_file_exec_lookup(const char *cmd)
630 {
631 struct stat s;
632 int plen = 0, clen = strlen(cmd) + 1;
633 char *search, *p;
634 static char path[PATH_MAX];
635
636 if (!stat(cmd, &s) && S_ISREG(s.st_mode))
637 return cmd;
638
639 search = getenv("PATH");
640
641 if (!search)
642 search = "/bin:/usr/bin:/sbin:/usr/sbin";
643
644 p = search;
645
646 do
647 {
648 if (*p != ':' && *p != '\0')
649 continue;
650
651 plen = p - search;
652
653 if ((plen + clen) >= sizeof(path))
654 continue;
655
656 strncpy(path, search, plen);
657 sprintf(path + plen, "/%s", cmd);
658
659 if (!stat(path, &s) && S_ISREG(s.st_mode))
660 return path;
661
662 search = p + 1;
663 }
664 while (*p++);
665
666 return NULL;
667 }
668
669
670 static void
671 rpc_ustream_to_blobmsg(struct ustream *s, const char *name)
672 {
673 int len;
674 char *rbuf, *wbuf;
675
676 if ((len = ustream_pending_data(s, false)) > 0)
677 {
678 wbuf = blobmsg_alloc_string_buffer(&buf, name, len + 1);
679
680 if (!wbuf)
681 return;
682
683 ustream_for_each_read_buffer(s, rbuf, len)
684 {
685 memcpy(wbuf, rbuf, len);
686 wbuf += len;
687 }
688
689 *wbuf = 0;
690 blobmsg_add_string_buffer(&buf);
691 }
692 }
693
694 static void
695 rpc_file_exec_reply(struct rpc_file_exec_context *c, int rv)
696 {
697 uloop_timeout_cancel(&c->timeout);
698 uloop_process_delete(&c->process);
699
700 if (rv == UBUS_STATUS_OK)
701 {
702 blob_buf_init(&buf, 0);
703
704 blobmsg_add_u32(&buf, "code", WEXITSTATUS(c->stat));
705
706 rpc_ustream_to_blobmsg(&c->opipe.stream, "stdout");
707 rpc_ustream_to_blobmsg(&c->epipe.stream, "stderr");
708
709 ubus_send_reply(c->context, &c->request, buf.head);
710 blob_buf_free(&buf);
711 }
712
713 ubus_complete_deferred_request(c->context, &c->request, rv);
714
715 ustream_free(&c->opipe.stream);
716 ustream_free(&c->epipe.stream);
717
718 close(c->opipe.fd.fd);
719 close(c->epipe.fd.fd);
720
721 free(c);
722 }
723
724 static void
725 rpc_file_exec_timeout_cb(struct uloop_timeout *t)
726 {
727 struct rpc_file_exec_context *c =
728 container_of(t, struct rpc_file_exec_context, timeout);
729
730 kill(c->process.pid, SIGKILL);
731 rpc_file_exec_reply(c, UBUS_STATUS_TIMEOUT);
732 }
733
734 static void
735 rpc_file_exec_process_cb(struct uloop_process *p, int stat)
736 {
737 struct rpc_file_exec_context *c =
738 container_of(p, struct rpc_file_exec_context, process);
739
740 c->stat = stat;
741
742 ustream_poll(&c->opipe.stream);
743 ustream_poll(&c->epipe.stream);
744 }
745
746 static void
747 rpc_file_exec_opipe_read_cb(struct ustream *s, int bytes)
748 {
749 struct rpc_file_exec_context *c =
750 container_of(s, struct rpc_file_exec_context, opipe.stream);
751
752 if (ustream_read_buf_full(s))
753 rpc_file_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED);
754 }
755
756 static void
757 rpc_file_exec_epipe_read_cb(struct ustream *s, int bytes)
758 {
759 struct rpc_file_exec_context *c =
760 container_of(s, struct rpc_file_exec_context, epipe.stream);
761
762 if (ustream_read_buf_full(s))
763 rpc_file_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED);
764 }
765
766 static void
767 rpc_file_exec_opipe_state_cb(struct ustream *s)
768 {
769 struct rpc_file_exec_context *c =
770 container_of(s, struct rpc_file_exec_context, opipe.stream);
771
772 if (c->opipe.stream.eof && c->epipe.stream.eof)
773 rpc_file_exec_reply(c, UBUS_STATUS_OK);
774 }
775
776 static void
777 rpc_file_exec_epipe_state_cb(struct ustream *s)
778 {
779 struct rpc_file_exec_context *c =
780 container_of(s, struct rpc_file_exec_context, epipe.stream);
781
782 if (c->opipe.stream.eof && c->epipe.stream.eof)
783 rpc_file_exec_reply(c, UBUS_STATUS_OK);
784 }
785
786 static void
787 rpc_fdclose(int fd)
788 {
789 if (fd > 2)
790 close(fd);
791 }
792
793 static int
794 rpc_file_exec_run(const char *cmd, const struct blob_attr *sid,
795 const struct blob_attr *arg, const struct blob_attr *env,
796 struct ubus_context *ctx, struct ubus_request_data *req)
797 {
798 pid_t pid;
799
800 int devnull;
801 int opipe[2];
802 int epipe[2];
803
804 int rem;
805 struct blob_attr *cur;
806
807 uint8_t arglen;
808 char *executable, **args, **tmp, *p;
809
810 struct rpc_file_exec_context *c;
811
812 if (sid && env)
813 return UBUS_STATUS_PERMISSION_DENIED;
814
815 cmd = rpc_file_exec_lookup(cmd);
816
817 if (!cmd)
818 return UBUS_STATUS_NOT_FOUND;
819
820 executable = rpc_canonicalize_path(cmd);
821
822 if (executable == NULL)
823 return UBUS_STATUS_UNKNOWN_ERROR;
824
825 if (!rpc_file_access(sid, executable, "exec"))
826 {
827 if (arg == NULL || strlen(executable) >= sizeof(cmdstr))
828 return UBUS_STATUS_PERMISSION_DENIED;
829
830 arglen = 2;
831 p = cmdstr + sprintf(cmdstr, "%s", executable);
832
833 blobmsg_for_each_attr(cur, arg, rem)
834 {
835 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
836 continue;
837
838 if (arglen == 255 ||
839 p + blobmsg_data_len(cur) >= cmdstr + sizeof(cmdstr))
840 return UBUS_STATUS_PERMISSION_DENIED;
841
842 p += sprintf(p, " %s", blobmsg_get_string(cur));
843 arglen++;
844 }
845
846 if (!rpc_file_access(sid, cmdstr, "exec"))
847 return UBUS_STATUS_PERMISSION_DENIED;
848 }
849
850 c = malloc(sizeof(*c));
851
852 if (!c)
853 return UBUS_STATUS_UNKNOWN_ERROR;
854
855 if (pipe(opipe))
856 goto fail_opipe;
857
858 if (pipe(epipe))
859 goto fail_epipe;
860
861 switch ((pid = fork()))
862 {
863 case -1:
864 goto fail_fork;
865
866 case 0:
867 uloop_done();
868
869 devnull = open("/dev/null", O_RDWR);
870
871 if (devnull == -1)
872 return UBUS_STATUS_UNKNOWN_ERROR;
873
874 dup2(devnull, 0);
875 dup2(opipe[1], 1);
876 dup2(epipe[1], 2);
877
878 rpc_fdclose(devnull);
879 rpc_fdclose(opipe[0]);
880 rpc_fdclose(opipe[1]);
881 rpc_fdclose(epipe[0]);
882 rpc_fdclose(epipe[1]);
883
884 arglen = 2;
885 args = malloc(sizeof(char *) * arglen);
886
887 if (!args)
888 return UBUS_STATUS_UNKNOWN_ERROR;
889
890 args[0] = (char *)executable;
891 args[1] = NULL;
892
893 if (arg)
894 {
895 blobmsg_for_each_attr(cur, arg, rem)
896 {
897 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
898 continue;
899
900 if (arglen == 255)
901 {
902 free(args);
903 return UBUS_STATUS_INVALID_ARGUMENT;
904 }
905
906 arglen++;
907 tmp = realloc(args, sizeof(char *) * arglen);
908
909 if (!tmp)
910 {
911 free(args);
912 return UBUS_STATUS_UNKNOWN_ERROR;
913 }
914
915 args = tmp;
916 args[arglen-2] = blobmsg_data(cur);
917 args[arglen-1] = NULL;
918 }
919 }
920
921 if (env)
922 {
923 blobmsg_for_each_attr(cur, env, rem)
924 {
925 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
926 continue;
927
928 setenv(blobmsg_name(cur), blobmsg_data(cur), 1);
929 }
930 }
931
932 if (execv(executable, args))
933 return rpc_errno_status();
934
935 default:
936 memset(c, 0, sizeof(*c));
937
938 ustream_declare(c->opipe, opipe[0], exec_opipe);
939 ustream_declare(c->epipe, epipe[0], exec_epipe);
940
941 c->process.pid = pid;
942 c->process.cb = rpc_file_exec_process_cb;
943 uloop_process_add(&c->process);
944
945 c->timeout.cb = rpc_file_exec_timeout_cb;
946 uloop_timeout_set(&c->timeout, *ops->exec_timeout);
947
948 close(opipe[1]);
949 close(epipe[1]);
950
951 c->context = ctx;
952 ubus_defer_request(ctx, req, &c->request);
953 }
954
955 return UBUS_STATUS_OK;
956
957 fail_fork:
958 close(epipe[0]);
959 close(epipe[1]);
960
961 fail_epipe:
962 close(opipe[0]);
963 close(opipe[1]);
964
965 fail_opipe:
966 free(c);
967 return rpc_errno_status();
968 }
969
970 static int
971 rpc_file_exec(struct ubus_context *ctx, struct ubus_object *obj,
972 struct ubus_request_data *req, const char *method,
973 struct blob_attr *msg)
974 {
975 struct blob_attr *tb[__RPC_E_MAX];
976
977 blobmsg_parse(rpc_exec_policy, __RPC_E_MAX, tb,
978 blob_data(msg), blob_len(msg));
979
980 if (!tb[RPC_E_CMD])
981 return UBUS_STATUS_INVALID_ARGUMENT;
982
983 return rpc_file_exec_run(blobmsg_data(tb[RPC_E_CMD]), tb[RPC_E_SESSION],
984 tb[RPC_E_PARM], tb[RPC_E_ENV], ctx, req);
985 }
986
987
988 static int
989 rpc_file_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx)
990 {
991 static const struct ubus_method file_methods[] = {
992 UBUS_METHOD("read", rpc_file_read, rpc_file_RB_policy),
993 UBUS_METHOD("write", rpc_file_write, rpc_file_RW_policy),
994 UBUS_METHOD("list", rpc_file_list, rpc_file_R_policy),
995 UBUS_METHOD("stat", rpc_file_stat, rpc_file_R_policy),
996 UBUS_METHOD("md5", rpc_file_md5, rpc_file_R_policy),
997 UBUS_METHOD("remove", rpc_file_remove, rpc_file_R_policy),
998 UBUS_METHOD("exec", rpc_file_exec, rpc_exec_policy),
999 };
1000
1001 static struct ubus_object_type file_type =
1002 UBUS_OBJECT_TYPE("rpcd-plugin-file", file_methods);
1003
1004 static struct ubus_object obj = {
1005 .name = "file",
1006 .type = &file_type,
1007 .methods = file_methods,
1008 .n_methods = ARRAY_SIZE(file_methods),
1009 };
1010
1011 ops = o;
1012
1013 return ubus_add_object(ctx, &obj);
1014 }
1015
1016 struct rpc_plugin rpc_plugin = {
1017 .init = rpc_file_api_init
1018 };