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 }; 1019
This page was automatically generated by LXR 0.3.1. • OpenWrt