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, bool use_lstat) 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 && (use_lstat ? lstat(*path, s) : stat(*path, s)) != 0) 276 return NULL; 277 278 return tb; 279 } 280 281 // use_lstat defaults to false 282 #define rpc_check_path(msg, policy_selector, perm, path, s) \ 283 __rpc_check_path(rpc_file_ ## policy_selector ## _policy, \ 284 ARRAY_SIZE(rpc_file_ ## policy_selector ## _policy), \ 285 RPC_F_ ## policy_selector ## _PATH, \ 286 RPC_F_ ## policy_selector ## _SESSION, \ 287 perm, msg, path, s, false) 288 289 // use_lstat control 290 #define rpc_check_path_with_lstat(msg, policy_selector, perm, path, s, use_lstat) \ 291 __rpc_check_path(rpc_file_ ## policy_selector ## _policy, \ 292 ARRAY_SIZE(rpc_file_ ## policy_selector ## _policy), \ 293 RPC_F_ ## policy_selector ## _PATH, \ 294 RPC_F_ ## policy_selector ## _SESSION, \ 295 perm, msg, path, s, use_lstat) 296 297 static int 298 rpc_file_read(struct ubus_context *ctx, struct ubus_object *obj, 299 struct ubus_request_data *req, const char *method, 300 struct blob_attr *msg) 301 { 302 struct blob_attr **tb; 303 bool base64 = false; 304 int fd, rv; 305 ssize_t len; 306 char *path; 307 struct stat s; 308 char *wbuf; 309 310 tb = rpc_check_path(msg, RB, "read", &path, &s); 311 312 if (tb == NULL) 313 return rpc_errno_status(); 314 315 if (s.st_size >= RPC_FILE_MAX_SIZE) 316 return UBUS_STATUS_NOT_SUPPORTED; 317 318 if ((fd = open(path, O_RDONLY)) < 0) 319 return rpc_errno_status(); 320 321 /* some sysfs files do not report a length */ 322 if (s.st_size == 0) 323 s.st_size = RPC_FILE_MIN_SIZE; 324 325 blob_buf_init(&buf, 0); 326 327 if (tb[RPC_F_RB_BASE64]) 328 base64 = blobmsg_get_bool(tb[RPC_F_RB_BASE64]); 329 330 len = s.st_size + 1; 331 if (base64) 332 len = B64_ENCODE_LEN(s.st_size); 333 wbuf = blobmsg_alloc_string_buffer(&buf, "data", len); 334 335 if (!wbuf) 336 { 337 rv = UBUS_STATUS_UNKNOWN_ERROR; 338 goto out; 339 } 340 341 if ((len = read(fd, wbuf, s.st_size)) <= 0) 342 { 343 rv = UBUS_STATUS_NO_DATA; 344 goto out; 345 } 346 347 if (base64) 348 { 349 uint8_t *data = calloc(len, sizeof(uint8_t)); 350 if (!data) 351 { 352 rv = UBUS_STATUS_UNKNOWN_ERROR; 353 goto out; 354 } 355 memcpy(data, wbuf, len); 356 357 len = b64_encode(data, len, wbuf, B64_ENCODE_LEN(len)); 358 free(data); 359 if (len < 0) 360 { 361 rv = UBUS_STATUS_UNKNOWN_ERROR; 362 goto out; 363 } 364 } 365 366 *(wbuf + len) = '\0'; 367 blobmsg_add_string_buffer(&buf); 368 369 ubus_send_reply(ctx, req, buf.head); 370 rv = UBUS_STATUS_OK; 371 372 out: 373 blob_buf_free(&buf); 374 close(fd); 375 return rv; 376 } 377 378 static int 379 rpc_file_write(struct ubus_context *ctx, struct ubus_object *obj, 380 struct ubus_request_data *req, const char *method, 381 struct blob_attr *msg) 382 { 383 struct blob_attr **tb; 384 int append = O_TRUNC; 385 mode_t prev_mode, mode = 0666; 386 int fd, rv = 0; 387 char *path = NULL; 388 void *data = NULL; 389 ssize_t data_len = 0; 390 391 tb = rpc_check_path(msg, RW, "write", &path, NULL); 392 393 if (tb == NULL) 394 return rpc_errno_status(); 395 396 if (!tb[RPC_F_RW_DATA]) 397 return UBUS_STATUS_INVALID_ARGUMENT; 398 399 data = blobmsg_data(tb[RPC_F_RW_DATA]); 400 data_len = blobmsg_data_len(tb[RPC_F_RW_DATA]) - 1; 401 402 if (tb[RPC_F_RW_APPEND] && blobmsg_get_bool(tb[RPC_F_RW_APPEND])) 403 append = O_APPEND; 404 405 if (tb[RPC_F_RW_MODE]) 406 mode = blobmsg_get_u32(tb[RPC_F_RW_MODE]); 407 408 prev_mode = umask(0); 409 fd = open(path, O_CREAT | O_WRONLY | append, mode); 410 umask(prev_mode); 411 if (fd < 0) 412 return rpc_errno_status(); 413 414 if (tb[RPC_F_RW_BASE64] && blobmsg_get_bool(tb[RPC_F_RW_BASE64])) 415 { 416 data_len = b64_decode(data, data, data_len); 417 if (data_len < 0) 418 { 419 rv = UBUS_STATUS_UNKNOWN_ERROR; 420 goto out; 421 } 422 } 423 424 if (write(fd, data, data_len) < 0) 425 rv = -1; 426 427 out: 428 if (fsync(fd) < 0) 429 rv = -1; 430 431 close(fd); 432 sync(); 433 434 if (rv) 435 return rpc_errno_status(); 436 437 return 0; 438 } 439 440 static int 441 rpc_file_md5(struct ubus_context *ctx, struct ubus_object *obj, 442 struct ubus_request_data *req, const char *method, 443 struct blob_attr *msg) 444 { 445 int rv, i; 446 char *path; 447 struct stat s; 448 uint8_t md5[16]; 449 char *wbuf; 450 451 if (!rpc_check_path(msg, R, "read", &path, &s)) 452 return rpc_errno_status(); 453 454 if (!S_ISREG(s.st_mode)) 455 return UBUS_STATUS_NOT_SUPPORTED; 456 457 if ((rv = md5sum(path, md5)) <= 0) 458 return rpc_errno_status(); 459 460 blob_buf_init(&buf, 0); 461 wbuf = blobmsg_alloc_string_buffer(&buf, "md5", 33); 462 463 for (i = 0; i < 16; i++) 464 sprintf(wbuf + (i * 2), "%02x", (uint8_t) md5[i]); 465 466 blobmsg_add_string_buffer(&buf); 467 ubus_send_reply(ctx, req, buf.head); 468 blob_buf_free(&buf); 469 470 return UBUS_STATUS_OK; 471 } 472 473 static void 474 _rpc_file_add_stat(struct stat *s) 475 { 476 int type; 477 478 type = S_ISREG(s->st_mode) ? DT_REG : 479 S_ISDIR(s->st_mode) ? DT_DIR : 480 S_ISCHR(s->st_mode) ? DT_CHR : 481 S_ISBLK(s->st_mode) ? DT_BLK : 482 S_ISFIFO(s->st_mode) ? DT_FIFO : 483 S_ISLNK(s->st_mode) ? DT_LNK : 484 S_ISSOCK(s->st_mode) ? DT_SOCK : 485 DT_UNKNOWN; 486 487 blobmsg_add_string(&buf, "type", d_types[type]); 488 blobmsg_add_u32(&buf, "size", s->st_size); 489 blobmsg_add_u32(&buf, "mode", s->st_mode); 490 blobmsg_add_u32(&buf, "atime", s->st_atime); 491 blobmsg_add_u32(&buf, "mtime", s->st_mtime); 492 blobmsg_add_u32(&buf, "ctime", s->st_ctime); 493 blobmsg_add_u32(&buf, "inode", s->st_ino); 494 blobmsg_add_u32(&buf, "uid", s->st_uid); 495 blobmsg_add_u32(&buf, "gid", s->st_gid); 496 } 497 498 static int 499 rpc_file_list(struct ubus_context *ctx, struct ubus_object *obj, 500 struct ubus_request_data *req, const char *method, 501 struct blob_attr *msg) 502 { 503 DIR *fd; 504 void *c, *d; 505 struct stat s; 506 struct dirent *e; 507 char *path, *entrypath; 508 509 if (!rpc_check_path(msg, R, "list", &path, NULL)) 510 return rpc_errno_status(); 511 512 if ((fd = opendir(path)) == NULL) 513 return rpc_errno_status(); 514 515 blob_buf_init(&buf, 0); 516 c = blobmsg_open_array(&buf, "entries"); 517 518 while ((e = readdir(fd)) != NULL) 519 { 520 if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) 521 continue; 522 523 if (asprintf(&entrypath, "%s/%s", path, e->d_name) < 0) 524 continue; 525 526 if (!stat(entrypath, &s)) 527 { 528 d = blobmsg_open_table(&buf, NULL); 529 blobmsg_add_string(&buf, "name", e->d_name); 530 _rpc_file_add_stat(&s); 531 blobmsg_close_table(&buf, d); 532 } 533 534 free(entrypath); 535 } 536 537 closedir(fd); 538 539 blobmsg_close_array(&buf, c); 540 ubus_send_reply(ctx, req, buf.head); 541 blob_buf_free(&buf); 542 543 return 0; 544 } 545 546 static int 547 rpc_file_stat(struct ubus_context *ctx, struct ubus_object *obj, 548 struct ubus_request_data *req, const char *method, 549 struct blob_attr *msg) 550 { 551 char *path; 552 struct stat s; 553 554 if (!rpc_check_path(msg, R, "list", &path, &s)) 555 return rpc_errno_status(); 556 557 blob_buf_init(&buf, 0); 558 559 blobmsg_add_string(&buf, "path", path); 560 _rpc_file_add_stat(&s); 561 562 ubus_send_reply(ctx, req, buf.head); 563 blob_buf_free(&buf); 564 565 return 0; 566 } 567 568 static int 569 rpc_file_lstat(struct ubus_context *ctx, struct ubus_object *obj, 570 struct ubus_request_data *req, const char *method, 571 struct blob_attr *msg) 572 { 573 char *path; 574 struct stat s; 575 576 if (!rpc_check_path_with_lstat(msg, R, "list", &path, &s, true)) 577 return rpc_errno_status(); 578 579 blob_buf_init(&buf, 0); 580 581 blobmsg_add_string(&buf, "path", path); 582 _rpc_file_add_stat(&s); 583 584 ubus_send_reply(ctx, req, buf.head); 585 blob_buf_free(&buf); 586 587 return 0; 588 } 589 590 static int 591 rpc_file_remove_recursive(const char *path); 592 593 static int 594 rpc_file_remove_recursive(const char *path) 595 { 596 DIR *fd; 597 int err = 0; 598 struct stat s; 599 struct dirent *e; 600 char *entrypath; 601 602 if ((fd = opendir(path)) == NULL) 603 return rpc_errno_status(); 604 605 for (e = readdir(fd); e != NULL && err == 0; e = readdir(fd)) 606 { 607 if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) 608 continue; 609 610 if (asprintf(&entrypath, "%s/%s", path, e->d_name) >= 0) 611 { 612 if (!lstat(entrypath, &s)) 613 { 614 if (S_ISDIR(s.st_mode)) 615 err = rpc_file_remove_recursive(entrypath); 616 else if (unlink(entrypath)) 617 err = rpc_errno_status(); 618 } 619 620 free(entrypath); 621 } 622 else 623 { 624 err = UBUS_STATUS_UNKNOWN_ERROR; 625 } 626 } 627 628 closedir(fd); 629 630 if (!err && rmdir(path)) 631 return rpc_errno_status(); 632 633 return err; 634 } 635 636 static int 637 rpc_file_remove(struct ubus_context *ctx, struct ubus_object *obj, 638 struct ubus_request_data *req, const char *method, 639 struct blob_attr *msg) 640 { 641 struct stat s; 642 char *path = NULL; 643 644 if (!rpc_check_path(msg, R, "write", &path, NULL)) 645 return rpc_errno_status(); 646 647 if (lstat(path, &s)) 648 return rpc_errno_status(); 649 650 if (S_ISDIR(s.st_mode)) 651 return rpc_file_remove_recursive(path); 652 653 if (unlink(path)) 654 return rpc_errno_status(); 655 656 return 0; 657 } 658 659 static const char * 660 rpc_file_exec_lookup(const char *cmd) 661 { 662 struct stat s; 663 int plen = 0, clen = strlen(cmd) + 1; 664 char *search, *p; 665 static char path[PATH_MAX]; 666 667 if (!stat(cmd, &s) && S_ISREG(s.st_mode)) 668 return cmd; 669 670 search = getenv("PATH"); 671 672 if (!search) 673 search = "/bin:/usr/bin:/sbin:/usr/sbin"; 674 675 p = search; 676 677 do 678 { 679 if (*p != ':' && *p != '\0') 680 continue; 681 682 plen = p - search; 683 684 if ((plen + clen) >= sizeof(path)) 685 continue; 686 687 strncpy(path, search, plen); 688 sprintf(path + plen, "/%s", cmd); 689 690 if (!stat(path, &s) && S_ISREG(s.st_mode)) 691 return path; 692 693 search = p + 1; 694 } 695 while (*p++); 696 697 return NULL; 698 } 699 700 701 static void 702 rpc_ustream_to_blobmsg(struct ustream *s, const char *name) 703 { 704 int len; 705 char *rbuf, *wbuf; 706 707 if ((len = ustream_pending_data(s, false)) > 0) 708 { 709 wbuf = blobmsg_alloc_string_buffer(&buf, name, len + 1); 710 711 if (!wbuf) 712 return; 713 714 ustream_for_each_read_buffer(s, rbuf, len) 715 { 716 memcpy(wbuf, rbuf, len); 717 wbuf += len; 718 } 719 720 *wbuf = 0; 721 blobmsg_add_string_buffer(&buf); 722 } 723 } 724 725 static void 726 rpc_file_exec_reply(struct rpc_file_exec_context *c, int rv) 727 { 728 uloop_timeout_cancel(&c->timeout); 729 uloop_process_delete(&c->process); 730 731 if (rv == UBUS_STATUS_OK) 732 { 733 blob_buf_init(&buf, 0); 734 735 blobmsg_add_u32(&buf, "code", WEXITSTATUS(c->stat)); 736 737 rpc_ustream_to_blobmsg(&c->opipe.stream, "stdout"); 738 rpc_ustream_to_blobmsg(&c->epipe.stream, "stderr"); 739 740 ubus_send_reply(c->context, &c->request, buf.head); 741 blob_buf_free(&buf); 742 } 743 744 ubus_complete_deferred_request(c->context, &c->request, rv); 745 746 ustream_free(&c->opipe.stream); 747 ustream_free(&c->epipe.stream); 748 749 close(c->opipe.fd.fd); 750 close(c->epipe.fd.fd); 751 752 free(c); 753 } 754 755 static void 756 rpc_file_exec_timeout_cb(struct uloop_timeout *t) 757 { 758 struct rpc_file_exec_context *c = 759 container_of(t, struct rpc_file_exec_context, timeout); 760 761 kill(c->process.pid, SIGKILL); 762 rpc_file_exec_reply(c, UBUS_STATUS_TIMEOUT); 763 } 764 765 static void 766 rpc_file_exec_process_cb(struct uloop_process *p, int stat) 767 { 768 struct rpc_file_exec_context *c = 769 container_of(p, struct rpc_file_exec_context, process); 770 771 c->stat = stat; 772 773 ustream_poll(&c->opipe.stream); 774 ustream_poll(&c->epipe.stream); 775 } 776 777 static void 778 rpc_file_exec_opipe_read_cb(struct ustream *s, int bytes) 779 { 780 struct rpc_file_exec_context *c = 781 container_of(s, struct rpc_file_exec_context, opipe.stream); 782 783 if (ustream_read_buf_full(s)) 784 rpc_file_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED); 785 } 786 787 static void 788 rpc_file_exec_epipe_read_cb(struct ustream *s, int bytes) 789 { 790 struct rpc_file_exec_context *c = 791 container_of(s, struct rpc_file_exec_context, epipe.stream); 792 793 if (ustream_read_buf_full(s)) 794 rpc_file_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED); 795 } 796 797 static void 798 rpc_file_exec_opipe_state_cb(struct ustream *s) 799 { 800 struct rpc_file_exec_context *c = 801 container_of(s, struct rpc_file_exec_context, opipe.stream); 802 803 if (c->opipe.stream.eof && c->epipe.stream.eof) 804 rpc_file_exec_reply(c, UBUS_STATUS_OK); 805 } 806 807 static void 808 rpc_file_exec_epipe_state_cb(struct ustream *s) 809 { 810 struct rpc_file_exec_context *c = 811 container_of(s, struct rpc_file_exec_context, epipe.stream); 812 813 if (c->opipe.stream.eof && c->epipe.stream.eof) 814 rpc_file_exec_reply(c, UBUS_STATUS_OK); 815 } 816 817 static void 818 rpc_fdclose(int fd) 819 { 820 if (fd > 2) 821 close(fd); 822 } 823 824 static int 825 rpc_file_exec_run(const char *cmd, const struct blob_attr *sid, 826 const struct blob_attr *arg, const struct blob_attr *env, 827 struct ubus_context *ctx, struct ubus_request_data *req) 828 { 829 pid_t pid; 830 831 int devnull; 832 int opipe[2]; 833 int epipe[2]; 834 835 int rem; 836 struct blob_attr *cur; 837 838 uint8_t arglen; 839 char *executable, **args, **tmp, *p; 840 841 struct rpc_file_exec_context *c; 842 843 if (sid && env) 844 return UBUS_STATUS_PERMISSION_DENIED; 845 846 cmd = rpc_file_exec_lookup(cmd); 847 848 if (!cmd) 849 return UBUS_STATUS_NOT_FOUND; 850 851 executable = rpc_canonicalize_path(cmd); 852 853 if (executable == NULL) 854 return UBUS_STATUS_UNKNOWN_ERROR; 855 856 if (!rpc_file_access(sid, executable, "exec")) 857 { 858 if (arg == NULL || strlen(executable) >= sizeof(cmdstr)) 859 return UBUS_STATUS_PERMISSION_DENIED; 860 861 arglen = 2; 862 p = cmdstr + sprintf(cmdstr, "%s", executable); 863 864 blobmsg_for_each_attr(cur, arg, rem) 865 { 866 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 867 continue; 868 869 if (arglen == 255 || 870 p + blobmsg_data_len(cur) >= cmdstr + sizeof(cmdstr)) 871 return UBUS_STATUS_PERMISSION_DENIED; 872 873 p += sprintf(p, " %s", blobmsg_get_string(cur)); 874 arglen++; 875 } 876 877 if (!rpc_file_access(sid, cmdstr, "exec")) 878 return UBUS_STATUS_PERMISSION_DENIED; 879 } 880 881 c = malloc(sizeof(*c)); 882 883 if (!c) 884 return UBUS_STATUS_UNKNOWN_ERROR; 885 886 if (pipe(opipe)) 887 goto fail_opipe; 888 889 if (pipe(epipe)) 890 goto fail_epipe; 891 892 switch ((pid = fork())) 893 { 894 case -1: 895 goto fail_fork; 896 897 case 0: 898 uloop_done(); 899 900 devnull = open("/dev/null", O_RDWR); 901 902 if (devnull == -1) 903 return UBUS_STATUS_UNKNOWN_ERROR; 904 905 dup2(devnull, 0); 906 dup2(opipe[1], 1); 907 dup2(epipe[1], 2); 908 909 rpc_fdclose(devnull); 910 rpc_fdclose(opipe[0]); 911 rpc_fdclose(opipe[1]); 912 rpc_fdclose(epipe[0]); 913 rpc_fdclose(epipe[1]); 914 915 arglen = 2; 916 args = malloc(sizeof(char *) * arglen); 917 918 if (!args) 919 return UBUS_STATUS_UNKNOWN_ERROR; 920 921 args[0] = (char *)executable; 922 args[1] = NULL; 923 924 if (arg) 925 { 926 blobmsg_for_each_attr(cur, arg, rem) 927 { 928 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 929 continue; 930 931 if (arglen == 255) 932 { 933 free(args); 934 return UBUS_STATUS_INVALID_ARGUMENT; 935 } 936 937 arglen++; 938 tmp = realloc(args, sizeof(char *) * arglen); 939 940 if (!tmp) 941 { 942 free(args); 943 return UBUS_STATUS_UNKNOWN_ERROR; 944 } 945 946 args = tmp; 947 args[arglen-2] = blobmsg_data(cur); 948 args[arglen-1] = NULL; 949 } 950 } 951 952 if (env) 953 { 954 blobmsg_for_each_attr(cur, env, rem) 955 { 956 if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) 957 continue; 958 959 setenv(blobmsg_name(cur), blobmsg_data(cur), 1); 960 } 961 } 962 963 if (execv(executable, args)) 964 return rpc_errno_status(); 965 966 default: 967 memset(c, 0, sizeof(*c)); 968 969 ustream_declare(c->opipe, opipe[0], exec_opipe); 970 ustream_declare(c->epipe, epipe[0], exec_epipe); 971 972 c->process.pid = pid; 973 c->process.cb = rpc_file_exec_process_cb; 974 uloop_process_add(&c->process); 975 976 c->timeout.cb = rpc_file_exec_timeout_cb; 977 uloop_timeout_set(&c->timeout, *ops->exec_timeout); 978 979 close(opipe[1]); 980 close(epipe[1]); 981 982 c->context = ctx; 983 ubus_defer_request(ctx, req, &c->request); 984 } 985 986 return UBUS_STATUS_OK; 987 988 fail_fork: 989 close(epipe[0]); 990 close(epipe[1]); 991 992 fail_epipe: 993 close(opipe[0]); 994 close(opipe[1]); 995 996 fail_opipe: 997 free(c); 998 return rpc_errno_status(); 999 } 1000 1001 static int 1002 rpc_file_exec(struct ubus_context *ctx, struct ubus_object *obj, 1003 struct ubus_request_data *req, const char *method, 1004 struct blob_attr *msg) 1005 { 1006 struct blob_attr *tb[__RPC_E_MAX]; 1007 1008 blobmsg_parse(rpc_exec_policy, __RPC_E_MAX, tb, 1009 blob_data(msg), blob_len(msg)); 1010 1011 if (!tb[RPC_E_CMD]) 1012 return UBUS_STATUS_INVALID_ARGUMENT; 1013 1014 return rpc_file_exec_run(blobmsg_data(tb[RPC_E_CMD]), tb[RPC_E_SESSION], 1015 tb[RPC_E_PARM], tb[RPC_E_ENV], ctx, req); 1016 } 1017 1018 1019 static int 1020 rpc_file_api_init(const struct rpc_daemon_ops *o, struct ubus_context *ctx) 1021 { 1022 static const struct ubus_method file_methods[] = { 1023 UBUS_METHOD("read", rpc_file_read, rpc_file_RB_policy), 1024 UBUS_METHOD("write", rpc_file_write, rpc_file_RW_policy), 1025 UBUS_METHOD("list", rpc_file_list, rpc_file_R_policy), 1026 UBUS_METHOD("lstat", rpc_file_lstat, rpc_file_R_policy), 1027 UBUS_METHOD("stat", rpc_file_stat, rpc_file_R_policy), 1028 UBUS_METHOD("md5", rpc_file_md5, rpc_file_R_policy), 1029 UBUS_METHOD("remove", rpc_file_remove, rpc_file_R_policy), 1030 UBUS_METHOD("exec", rpc_file_exec, rpc_exec_policy), 1031 }; 1032 1033 static struct ubus_object_type file_type = 1034 UBUS_OBJECT_TYPE("rpcd-plugin-file", file_methods); 1035 1036 static struct ubus_object obj = { 1037 .name = "file", 1038 .type = &file_type, 1039 .methods = file_methods, 1040 .n_methods = ARRAY_SIZE(file_methods), 1041 }; 1042 1043 ops = o; 1044 1045 return ubus_add_object(ctx, &obj); 1046 } 1047 1048 struct rpc_plugin rpc_plugin = { 1049 .init = rpc_file_api_init 1050 }; 1051
This page was automatically generated by LXR 0.3.1. • OpenWrt