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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt