• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/rpcd/file.c

  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