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