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