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