instance.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. /*
  2. * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
  3. * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License version 2.1
  7. * as published by the Free Software Foundation
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #define _GNU_SOURCE
  15. #include <sys/resource.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <sys/stat.h>
  19. #include <net/if.h>
  20. #include <unistd.h>
  21. #include <stdint.h>
  22. #include <stdio.h>
  23. #include <fcntl.h>
  24. #include <pwd.h>
  25. #include <libgen.h>
  26. #include <unistd.h>
  27. #include <libubox/md5.h>
  28. #include "../procd.h"
  29. #include "service.h"
  30. #include "instance.h"
  31. enum {
  32. INSTANCE_ATTR_COMMAND,
  33. INSTANCE_ATTR_ENV,
  34. INSTANCE_ATTR_DATA,
  35. INSTANCE_ATTR_NETDEV,
  36. INSTANCE_ATTR_FILE,
  37. INSTANCE_ATTR_TRIGGER,
  38. INSTANCE_ATTR_RESPAWN,
  39. INSTANCE_ATTR_NICE,
  40. INSTANCE_ATTR_LIMITS,
  41. INSTANCE_ATTR_WATCH,
  42. INSTANCE_ATTR_ERROR,
  43. INSTANCE_ATTR_USER,
  44. INSTANCE_ATTR_STDOUT,
  45. INSTANCE_ATTR_STDERR,
  46. INSTANCE_ATTR_NO_NEW_PRIVS,
  47. INSTANCE_ATTR_JAIL,
  48. INSTANCE_ATTR_TRACE,
  49. INSTANCE_ATTR_SECCOMP,
  50. INSTANCE_ATTR_PIDFILE,
  51. INSTANCE_ATTR_RELOADSIG,
  52. INSTANCE_ATTR_TERMTIMEOUT,
  53. __INSTANCE_ATTR_MAX
  54. };
  55. static const struct blobmsg_policy instance_attr[__INSTANCE_ATTR_MAX] = {
  56. [INSTANCE_ATTR_COMMAND] = { "command", BLOBMSG_TYPE_ARRAY },
  57. [INSTANCE_ATTR_ENV] = { "env", BLOBMSG_TYPE_TABLE },
  58. [INSTANCE_ATTR_DATA] = { "data", BLOBMSG_TYPE_TABLE },
  59. [INSTANCE_ATTR_NETDEV] = { "netdev", BLOBMSG_TYPE_ARRAY },
  60. [INSTANCE_ATTR_FILE] = { "file", BLOBMSG_TYPE_ARRAY },
  61. [INSTANCE_ATTR_TRIGGER] = { "triggers", BLOBMSG_TYPE_ARRAY },
  62. [INSTANCE_ATTR_RESPAWN] = { "respawn", BLOBMSG_TYPE_ARRAY },
  63. [INSTANCE_ATTR_NICE] = { "nice", BLOBMSG_TYPE_INT32 },
  64. [INSTANCE_ATTR_LIMITS] = { "limits", BLOBMSG_TYPE_TABLE },
  65. [INSTANCE_ATTR_WATCH] = { "watch", BLOBMSG_TYPE_ARRAY },
  66. [INSTANCE_ATTR_ERROR] = { "error", BLOBMSG_TYPE_ARRAY },
  67. [INSTANCE_ATTR_USER] = { "user", BLOBMSG_TYPE_STRING },
  68. [INSTANCE_ATTR_STDOUT] = { "stdout", BLOBMSG_TYPE_BOOL },
  69. [INSTANCE_ATTR_STDERR] = { "stderr", BLOBMSG_TYPE_BOOL },
  70. [INSTANCE_ATTR_NO_NEW_PRIVS] = { "no_new_privs", BLOBMSG_TYPE_BOOL },
  71. [INSTANCE_ATTR_JAIL] = { "jail", BLOBMSG_TYPE_TABLE },
  72. [INSTANCE_ATTR_TRACE] = { "trace", BLOBMSG_TYPE_BOOL },
  73. [INSTANCE_ATTR_SECCOMP] = { "seccomp", BLOBMSG_TYPE_STRING },
  74. [INSTANCE_ATTR_PIDFILE] = { "pidfile", BLOBMSG_TYPE_STRING },
  75. [INSTANCE_ATTR_RELOADSIG] = { "reload_signal", BLOBMSG_TYPE_INT32 },
  76. [INSTANCE_ATTR_TERMTIMEOUT] = { "term_timeout", BLOBMSG_TYPE_INT32 },
  77. };
  78. enum {
  79. JAIL_ATTR_NAME,
  80. JAIL_ATTR_HOSTNAME,
  81. JAIL_ATTR_PROCFS,
  82. JAIL_ATTR_SYSFS,
  83. JAIL_ATTR_UBUS,
  84. JAIL_ATTR_LOG,
  85. JAIL_ATTR_RONLY,
  86. JAIL_ATTR_MOUNT,
  87. __JAIL_ATTR_MAX,
  88. };
  89. static const struct blobmsg_policy jail_attr[__JAIL_ATTR_MAX] = {
  90. [JAIL_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
  91. [JAIL_ATTR_HOSTNAME] = { "hostname", BLOBMSG_TYPE_STRING },
  92. [JAIL_ATTR_PROCFS] = { "procfs", BLOBMSG_TYPE_BOOL },
  93. [JAIL_ATTR_SYSFS] = { "sysfs", BLOBMSG_TYPE_BOOL },
  94. [JAIL_ATTR_UBUS] = { "ubus", BLOBMSG_TYPE_BOOL },
  95. [JAIL_ATTR_LOG] = { "log", BLOBMSG_TYPE_BOOL },
  96. [JAIL_ATTR_RONLY] = { "ronly", BLOBMSG_TYPE_BOOL },
  97. [JAIL_ATTR_MOUNT] = { "mount", BLOBMSG_TYPE_TABLE },
  98. };
  99. struct instance_netdev {
  100. struct blobmsg_list_node node;
  101. int ifindex;
  102. };
  103. struct instance_file {
  104. struct blobmsg_list_node node;
  105. uint32_t md5[4];
  106. };
  107. struct rlimit_name {
  108. const char *name;
  109. int resource;
  110. };
  111. static const struct rlimit_name rlimit_names[] = {
  112. { "as", RLIMIT_AS },
  113. { "core", RLIMIT_CORE },
  114. { "cpu", RLIMIT_CPU },
  115. { "data", RLIMIT_DATA },
  116. { "fsize", RLIMIT_FSIZE },
  117. { "memlock", RLIMIT_MEMLOCK },
  118. { "nofile", RLIMIT_NOFILE },
  119. { "nproc", RLIMIT_NPROC },
  120. { "rss", RLIMIT_RSS },
  121. { "stack", RLIMIT_STACK },
  122. #ifdef linux
  123. { "nice", RLIMIT_NICE },
  124. { "rtprio", RLIMIT_RTPRIO },
  125. { "msgqueue", RLIMIT_MSGQUEUE },
  126. { "sigpending", RLIMIT_SIGPENDING },
  127. #endif
  128. { NULL, 0 }
  129. };
  130. static char trace[] = "/sbin/utrace";
  131. static void closefd(int fd)
  132. {
  133. if (fd > STDERR_FILENO)
  134. close(fd);
  135. }
  136. static void
  137. instance_limits(const char *limit, const char *value)
  138. {
  139. int i;
  140. struct rlimit rlim;
  141. unsigned long cur, max;
  142. for (i = 0; rlimit_names[i].name != NULL; i++) {
  143. if (strcmp(rlimit_names[i].name, limit))
  144. continue;
  145. if (!strcmp(value, "unlimited")) {
  146. rlim.rlim_cur = RLIM_INFINITY;
  147. rlim.rlim_max = RLIM_INFINITY;
  148. } else {
  149. if (getrlimit(rlimit_names[i].resource, &rlim))
  150. return;
  151. cur = rlim.rlim_cur;
  152. max = rlim.rlim_max;
  153. if (sscanf(value, "%lu %lu", &cur, &max) < 1)
  154. return;
  155. rlim.rlim_cur = cur;
  156. rlim.rlim_max = max;
  157. }
  158. setrlimit(rlimit_names[i].resource, &rlim);
  159. return;
  160. }
  161. }
  162. static inline int
  163. jail_run(struct service_instance *in, char **argv)
  164. {
  165. struct blobmsg_list_node *var;
  166. struct jail *jail = &in->jail;
  167. int argc = 0;
  168. argv[argc++] = "/sbin/ujail";
  169. if (jail->name) {
  170. argv[argc++] = "-n";
  171. argv[argc++] = jail->name;
  172. }
  173. if (jail->hostname) {
  174. argv[argc++] = "-h";
  175. argv[argc++] = jail->hostname;
  176. }
  177. if (in->seccomp) {
  178. argv[argc++] = "-S";
  179. argv[argc++] = in->seccomp;
  180. }
  181. if (in->no_new_privs)
  182. argv[argc++] = "-c";
  183. if (jail->procfs)
  184. argv[argc++] = "-p";
  185. if (jail->sysfs)
  186. argv[argc++] = "-s";
  187. if (jail->ubus)
  188. argv[argc++] = "-u";
  189. if (jail->log)
  190. argv[argc++] = "-l";
  191. if (jail->ronly)
  192. argv[argc++] = "-o";
  193. blobmsg_list_for_each(&jail->mount, var) {
  194. const char *type = blobmsg_data(var->data);
  195. if (*type == '1')
  196. argv[argc++] = "-w";
  197. else
  198. argv[argc++] = "-r";
  199. argv[argc++] = (char *) blobmsg_name(var->data);
  200. }
  201. argv[argc++] = "--";
  202. return argc;
  203. }
  204. static int
  205. instance_removepid(struct service_instance *in) {
  206. if (!in->pidfile)
  207. return 0;
  208. if (unlink(in->pidfile)) {
  209. ERROR("Failed to removed pidfile: %s: %d - %s\n",
  210. in->pidfile, errno, strerror(errno));
  211. return 1;
  212. }
  213. return 0;
  214. }
  215. static int
  216. instance_writepid(struct service_instance *in)
  217. {
  218. FILE *_pidfile;
  219. if (!in->pidfile) {
  220. return 0;
  221. }
  222. _pidfile = fopen(in->pidfile, "w");
  223. if (_pidfile == NULL) {
  224. ERROR("failed to open pidfile for writing: %s: %d (%s)",
  225. in->pidfile, errno, strerror(errno));
  226. return 1;
  227. }
  228. if (fprintf(_pidfile, "%d\n", in->proc.pid) < 0) {
  229. ERROR("failed to write pidfile: %s: %d (%s)",
  230. in->pidfile, errno, strerror(errno));
  231. fclose(_pidfile);
  232. return 2;
  233. }
  234. if (fclose(_pidfile)) {
  235. ERROR("failed to close pidfile: %s: %d (%s)",
  236. in->pidfile, errno, strerror(errno));
  237. return 3;
  238. }
  239. return 0;
  240. }
  241. static void
  242. instance_run(struct service_instance *in, int _stdout, int _stderr)
  243. {
  244. struct blobmsg_list_node *var;
  245. struct blob_attr *cur;
  246. char **argv;
  247. char *ld_preload;
  248. int argc = 1; /* NULL terminated */
  249. int rem, _stdin;
  250. bool seccomp = !in->trace && !in->has_jail && in->seccomp;
  251. bool setlbf = _stdout >= 0;
  252. if (in->nice)
  253. setpriority(PRIO_PROCESS, 0, in->nice);
  254. blobmsg_for_each_attr(cur, in->command, rem)
  255. argc++;
  256. blobmsg_list_for_each(&in->env, var)
  257. setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1);
  258. if (seccomp)
  259. setenv("SECCOMP_FILE", in->seccomp, 1);
  260. if ((seccomp || setlbf) && asprintf(&ld_preload, "LD_PRELOAD=%s%s%s",
  261. seccomp ? "/lib/libpreload-seccomp.so" : "",
  262. seccomp && setlbf ? ":" : "",
  263. setlbf ? "/lib/libsetlbf.so" : "") > 0)
  264. putenv(ld_preload);
  265. blobmsg_list_for_each(&in->limits, var)
  266. instance_limits(blobmsg_name(var->data), blobmsg_data(var->data));
  267. if (in->trace)
  268. argc += 1;
  269. argv = alloca(sizeof(char *) * (argc + in->jail.argc));
  270. argc = 0;
  271. if (in->trace)
  272. argv[argc++] = trace;
  273. if (in->has_jail)
  274. argc = jail_run(in, argv);
  275. blobmsg_for_each_attr(cur, in->command, rem)
  276. argv[argc++] = blobmsg_data(cur);
  277. argv[argc] = NULL;
  278. _stdin = open("/dev/null", O_RDONLY);
  279. if (_stdout == -1)
  280. _stdout = open("/dev/null", O_WRONLY);
  281. if (_stderr == -1)
  282. _stderr = open("/dev/null", O_WRONLY);
  283. if (_stdin > -1) {
  284. dup2(_stdin, STDIN_FILENO);
  285. closefd(_stdin);
  286. }
  287. if (_stdout > -1) {
  288. dup2(_stdout, STDOUT_FILENO);
  289. closefd(_stdout);
  290. }
  291. if (_stderr > -1) {
  292. dup2(_stderr, STDERR_FILENO);
  293. closefd(_stderr);
  294. }
  295. if (in->gid && setgid(in->gid)) {
  296. ERROR("failed to set group id %d: %d (%s)\n", in->gid, errno, strerror(errno));
  297. exit(127);
  298. }
  299. if (in->uid && setuid(in->uid)) {
  300. ERROR("failed to set user id %d: %d (%s)\n", in->uid, errno, strerror(errno));
  301. exit(127);
  302. }
  303. execvp(argv[0], argv);
  304. exit(127);
  305. }
  306. static void
  307. instance_free_stdio(struct service_instance *in)
  308. {
  309. if (in->_stdout.fd.fd > -1) {
  310. ustream_free(&in->_stdout.stream);
  311. close(in->_stdout.fd.fd);
  312. in->_stdout.fd.fd = -1;
  313. }
  314. if (in->_stderr.fd.fd > -1) {
  315. ustream_free(&in->_stderr.stream);
  316. close(in->_stderr.fd.fd);
  317. in->_stderr.fd.fd = -1;
  318. }
  319. }
  320. void
  321. instance_start(struct service_instance *in)
  322. {
  323. int pid;
  324. int opipe[2] = { -1, -1 };
  325. int epipe[2] = { -1, -1 };
  326. if (!avl_is_empty(&in->errors.avl)) {
  327. LOG("Not starting instance %s::%s, an error was indicated\n", in->srv->name, in->name);
  328. return;
  329. }
  330. if (!in->command) {
  331. LOG("Not starting instance %s::%s, command not set\n", in->srv->name, in->name);
  332. return;
  333. }
  334. if (in->proc.pending) {
  335. if (in->halt)
  336. in->restart = true;
  337. return;
  338. }
  339. instance_free_stdio(in);
  340. if (in->_stdout.fd.fd > -2) {
  341. if (pipe(opipe)) {
  342. ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
  343. opipe[0] = opipe[1] = -1;
  344. }
  345. }
  346. if (in->_stderr.fd.fd > -2) {
  347. if (pipe(epipe)) {
  348. ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
  349. epipe[0] = epipe[1] = -1;
  350. }
  351. }
  352. in->restart = false;
  353. in->halt = false;
  354. if (!in->valid)
  355. return;
  356. pid = fork();
  357. if (pid < 0)
  358. return;
  359. if (!pid) {
  360. uloop_done();
  361. closefd(opipe[0]);
  362. closefd(epipe[0]);
  363. instance_run(in, opipe[1], epipe[1]);
  364. return;
  365. }
  366. DEBUG(2, "Started instance %s::%s[%d]\n", in->srv->name, in->name, pid);
  367. in->proc.pid = pid;
  368. instance_writepid(in);
  369. clock_gettime(CLOCK_MONOTONIC, &in->start);
  370. uloop_process_add(&in->proc);
  371. if (opipe[0] > -1) {
  372. ustream_fd_init(&in->_stdout, opipe[0]);
  373. closefd(opipe[1]);
  374. }
  375. if (epipe[0] > -1) {
  376. ustream_fd_init(&in->_stderr, epipe[0]);
  377. closefd(epipe[1]);
  378. }
  379. service_event("instance.start", in->srv->name, in->name);
  380. }
  381. static void
  382. instance_stdio(struct ustream *s, int prio, struct service_instance *in)
  383. {
  384. char *newline, *str, *arg0, ident[32];
  385. int len;
  386. arg0 = basename(blobmsg_data(blobmsg_data(in->command)));
  387. snprintf(ident, sizeof(ident), "%s[%d]", arg0, in->proc.pid);
  388. ulog_open(ULOG_SYSLOG, LOG_DAEMON, ident);
  389. do {
  390. str = ustream_get_read_buf(s, NULL);
  391. if (!str)
  392. break;
  393. newline = strchr(str, '\n');
  394. if (!newline)
  395. break;
  396. *newline = 0;
  397. ulog(prio, "%s\n", str);
  398. len = newline + 1 - str;
  399. ustream_consume(s, len);
  400. } while (1);
  401. ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
  402. }
  403. static void
  404. instance_stdout(struct ustream *s, int bytes)
  405. {
  406. instance_stdio(s, LOG_INFO,
  407. container_of(s, struct service_instance, _stdout.stream));
  408. }
  409. static void
  410. instance_stderr(struct ustream *s, int bytes)
  411. {
  412. instance_stdio(s, LOG_ERR,
  413. container_of(s, struct service_instance, _stderr.stream));
  414. }
  415. static void
  416. instance_timeout(struct uloop_timeout *t)
  417. {
  418. struct service_instance *in;
  419. in = container_of(t, struct service_instance, timeout);
  420. if (in->halt) {
  421. LOG("Instance %s::%s pid %d not stopped on SIGTERM, sending SIGKILL instead\n",
  422. in->srv->name, in->name, in->proc.pid);
  423. kill(in->proc.pid, SIGKILL);
  424. } else if (in->restart || in->respawn)
  425. instance_start(in);
  426. }
  427. static void
  428. instance_exit(struct uloop_process *p, int ret)
  429. {
  430. struct service_instance *in;
  431. struct timespec tp;
  432. long runtime;
  433. in = container_of(p, struct service_instance, proc);
  434. clock_gettime(CLOCK_MONOTONIC, &tp);
  435. runtime = tp.tv_sec - in->start.tv_sec;
  436. DEBUG(2, "Instance %s::%s exit with error code %d after %ld seconds\n", in->srv->name, in->name, ret, runtime);
  437. if (upgrade_running)
  438. return;
  439. uloop_timeout_cancel(&in->timeout);
  440. service_event("instance.stop", in->srv->name, in->name);
  441. if (in->halt) {
  442. instance_removepid(in);
  443. if (in->restart)
  444. instance_start(in);
  445. else {
  446. struct service *s = in->srv;
  447. avl_delete(&s->instances.avl, &in->node.avl);
  448. instance_free(in);
  449. service_stopped(s);
  450. }
  451. } else if (in->restart) {
  452. instance_start(in);
  453. } else if (in->respawn) {
  454. if (runtime < in->respawn_threshold)
  455. in->respawn_count++;
  456. else
  457. in->respawn_count = 0;
  458. if (in->respawn_count > in->respawn_retry && in->respawn_retry > 0 ) {
  459. LOG("Instance %s::%s s in a crash loop %d crashes, %ld seconds since last crash\n",
  460. in->srv->name, in->name, in->respawn_count, runtime);
  461. in->restart = in->respawn = 0;
  462. in->halt = 1;
  463. service_event("instance.fail", in->srv->name, in->name);
  464. } else {
  465. service_event("instance.respawn", in->srv->name, in->name);
  466. uloop_timeout_set(&in->timeout, in->respawn_timeout * 1000);
  467. }
  468. }
  469. }
  470. void
  471. instance_stop(struct service_instance *in)
  472. {
  473. if (!in->proc.pending)
  474. return;
  475. in->halt = true;
  476. in->restart = in->respawn = false;
  477. kill(in->proc.pid, SIGTERM);
  478. uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
  479. }
  480. static void
  481. instance_restart(struct service_instance *in)
  482. {
  483. if (!in->proc.pending)
  484. return;
  485. if (in->reload_signal) {
  486. kill(in->proc.pid, in->reload_signal);
  487. return;
  488. }
  489. in->halt = true;
  490. in->restart = true;
  491. kill(in->proc.pid, SIGTERM);
  492. uloop_timeout_set(&in->timeout, in->term_timeout * 1000);
  493. }
  494. static bool
  495. instance_config_changed(struct service_instance *in, struct service_instance *in_new)
  496. {
  497. if (!in->valid)
  498. return true;
  499. if (!blob_attr_equal(in->command, in_new->command))
  500. return true;
  501. if (!blobmsg_list_equal(&in->env, &in_new->env))
  502. return true;
  503. if (!blobmsg_list_equal(&in->netdev, &in_new->netdev))
  504. return true;
  505. if (!blobmsg_list_equal(&in->file, &in_new->file))
  506. return true;
  507. if (in->nice != in_new->nice)
  508. return true;
  509. if (in->uid != in_new->uid)
  510. return true;
  511. if (in->gid != in_new->gid)
  512. return true;
  513. if (in->pidfile && in_new->pidfile)
  514. if (strcmp(in->pidfile, in_new->pidfile))
  515. return true;
  516. if (in->pidfile && !in_new->pidfile)
  517. return true;
  518. if (!in->pidfile && in_new->pidfile)
  519. return true;
  520. if (!blobmsg_list_equal(&in->limits, &in_new->limits))
  521. return true;
  522. if (!blobmsg_list_equal(&in->jail.mount, &in_new->jail.mount))
  523. return true;
  524. if (!blobmsg_list_equal(&in->errors, &in_new->errors))
  525. return true;
  526. return false;
  527. }
  528. static bool
  529. instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
  530. {
  531. struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node);
  532. struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node);
  533. return n1->ifindex == n2->ifindex;
  534. }
  535. static void
  536. instance_netdev_update(struct blobmsg_list_node *l)
  537. {
  538. struct instance_netdev *n = container_of(l, struct instance_netdev, node);
  539. n->ifindex = if_nametoindex(n->node.avl.key);
  540. }
  541. static bool
  542. instance_file_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
  543. {
  544. struct instance_file *f1 = container_of(l1, struct instance_file, node);
  545. struct instance_file *f2 = container_of(l2, struct instance_file, node);
  546. return !memcmp(f1->md5, f2->md5, sizeof(f1->md5));
  547. }
  548. static void
  549. instance_file_update(struct blobmsg_list_node *l)
  550. {
  551. struct instance_file *f = container_of(l, struct instance_file, node);
  552. md5_ctx_t md5;
  553. char buf[256];
  554. int len, fd;
  555. memset(f->md5, 0, sizeof(f->md5));
  556. fd = open(l->avl.key, O_RDONLY);
  557. if (fd < 0)
  558. return;
  559. md5_begin(&md5);
  560. do {
  561. len = read(fd, buf, sizeof(buf));
  562. if (len < 0) {
  563. if (errno == EINTR)
  564. continue;
  565. break;
  566. }
  567. if (!len)
  568. break;
  569. md5_hash(buf, len, &md5);
  570. } while(1);
  571. md5_end(f->md5, &md5);
  572. close(fd);
  573. }
  574. static void
  575. instance_fill_any(struct blobmsg_list *l, struct blob_attr *cur)
  576. {
  577. if (!cur)
  578. return;
  579. blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), false);
  580. }
  581. static bool
  582. instance_fill_array(struct blobmsg_list *l, struct blob_attr *cur, blobmsg_update_cb cb, bool array)
  583. {
  584. struct blobmsg_list_node *node;
  585. if (!cur)
  586. return true;
  587. if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
  588. return false;
  589. blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), array);
  590. if (cb) {
  591. blobmsg_list_for_each(l, node)
  592. cb(node);
  593. }
  594. return true;
  595. }
  596. static int
  597. instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
  598. {
  599. struct blob_attr *tb[__JAIL_ATTR_MAX];
  600. struct jail *jail = &in->jail;
  601. struct stat s;
  602. if (stat("/sbin/ujail", &s))
  603. return 0;
  604. blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb,
  605. blobmsg_data(attr), blobmsg_data_len(attr));
  606. jail->argc = 2;
  607. if (tb[JAIL_ATTR_NAME]) {
  608. jail->name = blobmsg_get_string(tb[JAIL_ATTR_NAME]);
  609. jail->argc += 2;
  610. }
  611. if (tb[JAIL_ATTR_HOSTNAME]) {
  612. jail->hostname = blobmsg_get_string(tb[JAIL_ATTR_HOSTNAME]);
  613. jail->argc += 2;
  614. }
  615. if (tb[JAIL_ATTR_PROCFS]) {
  616. jail->procfs = blobmsg_get_bool(tb[JAIL_ATTR_PROCFS]);
  617. jail->argc++;
  618. }
  619. if (tb[JAIL_ATTR_SYSFS]) {
  620. jail->sysfs = blobmsg_get_bool(tb[JAIL_ATTR_SYSFS]);
  621. jail->argc++;
  622. }
  623. if (tb[JAIL_ATTR_UBUS]) {
  624. jail->ubus = blobmsg_get_bool(tb[JAIL_ATTR_UBUS]);
  625. jail->argc++;
  626. }
  627. if (tb[JAIL_ATTR_LOG]) {
  628. jail->log = blobmsg_get_bool(tb[JAIL_ATTR_LOG]);
  629. jail->argc++;
  630. }
  631. if (tb[JAIL_ATTR_RONLY]) {
  632. jail->ronly = blobmsg_get_bool(tb[JAIL_ATTR_RONLY]);
  633. jail->argc++;
  634. }
  635. if (tb[JAIL_ATTR_MOUNT]) {
  636. struct blob_attr *cur;
  637. int rem;
  638. blobmsg_for_each_attr(cur, tb[JAIL_ATTR_MOUNT], rem)
  639. jail->argc += 2;
  640. instance_fill_array(&jail->mount, tb[JAIL_ATTR_MOUNT], NULL, false);
  641. }
  642. if (in->seccomp)
  643. jail->argc += 2;
  644. return 1;
  645. }
  646. static bool
  647. instance_config_parse_command(struct service_instance *in, struct blob_attr **tb)
  648. {
  649. struct blob_attr *cur, *cur2;
  650. bool ret = false;
  651. int rem;
  652. cur = tb[INSTANCE_ATTR_COMMAND];
  653. if (!cur) {
  654. in->command = NULL;
  655. return true;
  656. }
  657. if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
  658. return false;
  659. blobmsg_for_each_attr(cur2, cur, rem) {
  660. ret = true;
  661. break;
  662. }
  663. in->command = cur;
  664. return ret;
  665. }
  666. static bool
  667. instance_config_parse(struct service_instance *in)
  668. {
  669. struct blob_attr *tb[__INSTANCE_ATTR_MAX];
  670. struct blob_attr *cur, *cur2;
  671. int rem;
  672. blobmsg_parse(instance_attr, __INSTANCE_ATTR_MAX, tb,
  673. blobmsg_data(in->config), blobmsg_data_len(in->config));
  674. if (!instance_config_parse_command(in, tb))
  675. return false;
  676. if (tb[INSTANCE_ATTR_TERMTIMEOUT])
  677. in->term_timeout = blobmsg_get_u32(tb[INSTANCE_ATTR_TERMTIMEOUT]);
  678. if (tb[INSTANCE_ATTR_RESPAWN]) {
  679. int i = 0;
  680. uint32_t vals[3] = { 3600, 5, 5};
  681. blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_RESPAWN], rem) {
  682. if ((i >= 3) && (blobmsg_type(cur2) == BLOBMSG_TYPE_STRING))
  683. continue;
  684. vals[i] = atoi(blobmsg_get_string(cur2));
  685. i++;
  686. }
  687. in->respawn = true;
  688. in->respawn_count = 0;
  689. in->respawn_threshold = vals[0];
  690. in->respawn_timeout = vals[1];
  691. in->respawn_retry = vals[2];
  692. }
  693. if (tb[INSTANCE_ATTR_TRIGGER]) {
  694. in->trigger = tb[INSTANCE_ATTR_TRIGGER];
  695. trigger_add(in->trigger, in);
  696. }
  697. if (tb[INSTANCE_ATTR_WATCH]) {
  698. blobmsg_for_each_attr(cur2, tb[INSTANCE_ATTR_WATCH], rem) {
  699. if (blobmsg_type(cur2) != BLOBMSG_TYPE_STRING)
  700. continue;
  701. DEBUG(3, "watch for %s\n", blobmsg_get_string(cur2));
  702. watch_add(blobmsg_get_string(cur2), in);
  703. }
  704. }
  705. if ((cur = tb[INSTANCE_ATTR_NICE])) {
  706. in->nice = (int8_t) blobmsg_get_u32(cur);
  707. if (in->nice < -20 || in->nice > 20)
  708. return false;
  709. }
  710. if (tb[INSTANCE_ATTR_USER]) {
  711. struct passwd *p = getpwnam(blobmsg_get_string(tb[INSTANCE_ATTR_USER]));
  712. if (p) {
  713. in->uid = p->pw_uid;
  714. in->gid = p->pw_gid;
  715. }
  716. }
  717. if (tb[INSTANCE_ATTR_TRACE])
  718. in->trace = blobmsg_get_bool(tb[INSTANCE_ATTR_TRACE]);
  719. if (tb[INSTANCE_ATTR_NO_NEW_PRIVS])
  720. in->no_new_privs = blobmsg_get_bool(tb[INSTANCE_ATTR_NO_NEW_PRIVS]);
  721. if (!in->trace && tb[INSTANCE_ATTR_SECCOMP]) {
  722. char *seccomp = blobmsg_get_string(tb[INSTANCE_ATTR_SECCOMP]);
  723. struct stat s;
  724. if (stat(seccomp, &s))
  725. ERROR("%s: not starting seccomp as %s is missing\n", in->name, seccomp);
  726. else
  727. in->seccomp = seccomp;
  728. }
  729. if (tb[INSTANCE_ATTR_PIDFILE]) {
  730. char *pidfile = blobmsg_get_string(tb[INSTANCE_ATTR_PIDFILE]);
  731. if (pidfile)
  732. in->pidfile = pidfile;
  733. }
  734. if (tb[INSTANCE_ATTR_RELOADSIG])
  735. in->reload_signal = blobmsg_get_u32(tb[INSTANCE_ATTR_RELOADSIG]);
  736. if (!in->trace && tb[INSTANCE_ATTR_JAIL])
  737. in->has_jail = instance_jail_parse(in, tb[INSTANCE_ATTR_JAIL]);
  738. if (tb[INSTANCE_ATTR_STDOUT] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDOUT]))
  739. in->_stdout.fd.fd = -1;
  740. if (tb[INSTANCE_ATTR_STDERR] && blobmsg_get_bool(tb[INSTANCE_ATTR_STDERR]))
  741. in->_stderr.fd.fd = -1;
  742. instance_fill_any(&in->data, tb[INSTANCE_ATTR_DATA]);
  743. if (!instance_fill_array(&in->env, tb[INSTANCE_ATTR_ENV], NULL, false))
  744. return false;
  745. if (!instance_fill_array(&in->netdev, tb[INSTANCE_ATTR_NETDEV], instance_netdev_update, true))
  746. return false;
  747. if (!instance_fill_array(&in->file, tb[INSTANCE_ATTR_FILE], instance_file_update, true))
  748. return false;
  749. if (!instance_fill_array(&in->limits, tb[INSTANCE_ATTR_LIMITS], NULL, false))
  750. return false;
  751. if (!instance_fill_array(&in->errors, tb[INSTANCE_ATTR_ERROR], NULL, true))
  752. return false;
  753. return true;
  754. }
  755. static void
  756. instance_config_cleanup(struct service_instance *in)
  757. {
  758. blobmsg_list_free(&in->env);
  759. blobmsg_list_free(&in->data);
  760. blobmsg_list_free(&in->netdev);
  761. blobmsg_list_free(&in->file);
  762. blobmsg_list_free(&in->limits);
  763. blobmsg_list_free(&in->errors);
  764. blobmsg_list_free(&in->jail.mount);
  765. }
  766. static void
  767. instance_config_move(struct service_instance *in, struct service_instance *in_src)
  768. {
  769. instance_config_cleanup(in);
  770. blobmsg_list_move(&in->env, &in_src->env);
  771. blobmsg_list_move(&in->data, &in_src->data);
  772. blobmsg_list_move(&in->netdev, &in_src->netdev);
  773. blobmsg_list_move(&in->file, &in_src->file);
  774. blobmsg_list_move(&in->limits, &in_src->limits);
  775. blobmsg_list_move(&in->errors, &in_src->errors);
  776. blobmsg_list_move(&in->jail.mount, &in_src->jail.mount);
  777. in->trigger = in_src->trigger;
  778. in->command = in_src->command;
  779. in->pidfile = in_src->pidfile;
  780. in->name = in_src->name;
  781. in->node.avl.key = in_src->node.avl.key;
  782. free(in->config);
  783. in->config = in_src->config;
  784. in_src->config = NULL;
  785. }
  786. void
  787. instance_update(struct service_instance *in, struct service_instance *in_new)
  788. {
  789. bool changed = instance_config_changed(in, in_new);
  790. bool running = in->proc.pending;
  791. bool stopping = in->halt;
  792. if (!running || stopping) {
  793. instance_config_move(in, in_new);
  794. instance_start(in);
  795. } else {
  796. if (changed)
  797. instance_restart(in);
  798. instance_config_move(in, in_new);
  799. /* restart happens in the child callback handler */
  800. }
  801. }
  802. void
  803. instance_free(struct service_instance *in)
  804. {
  805. instance_free_stdio(in);
  806. uloop_process_delete(&in->proc);
  807. uloop_timeout_cancel(&in->timeout);
  808. trigger_del(in);
  809. watch_del(in);
  810. instance_config_cleanup(in);
  811. free(in->config);
  812. free(in);
  813. }
  814. void
  815. instance_init(struct service_instance *in, struct service *s, struct blob_attr *config)
  816. {
  817. config = blob_memdup(config);
  818. in->srv = s;
  819. in->name = blobmsg_name(config);
  820. in->config = config;
  821. in->timeout.cb = instance_timeout;
  822. in->proc.cb = instance_exit;
  823. in->term_timeout = 5;
  824. in->_stdout.fd.fd = -2;
  825. in->_stdout.stream.string_data = true;
  826. in->_stdout.stream.notify_read = instance_stdout;
  827. in->_stderr.fd.fd = -2;
  828. in->_stderr.stream.string_data = true;
  829. in->_stderr.stream.notify_read = instance_stderr;
  830. blobmsg_list_init(&in->netdev, struct instance_netdev, node, instance_netdev_cmp);
  831. blobmsg_list_init(&in->file, struct instance_file, node, instance_file_cmp);
  832. blobmsg_list_simple_init(&in->env);
  833. blobmsg_list_simple_init(&in->data);
  834. blobmsg_list_simple_init(&in->limits);
  835. blobmsg_list_simple_init(&in->errors);
  836. blobmsg_list_simple_init(&in->jail.mount);
  837. in->valid = instance_config_parse(in);
  838. }
  839. void instance_dump(struct blob_buf *b, struct service_instance *in, int verbose)
  840. {
  841. void *i;
  842. if (!in->valid)
  843. return;
  844. i = blobmsg_open_table(b, in->name);
  845. blobmsg_add_u8(b, "running", in->proc.pending);
  846. if (in->proc.pending)
  847. blobmsg_add_u32(b, "pid", in->proc.pid);
  848. if (in->command)
  849. blobmsg_add_blob(b, in->command);
  850. blobmsg_add_u32(b, "term_timeout", in->term_timeout);
  851. if (!avl_is_empty(&in->errors.avl)) {
  852. struct blobmsg_list_node *var;
  853. void *e = blobmsg_open_array(b, "errors");
  854. blobmsg_list_for_each(&in->errors, var)
  855. blobmsg_add_string(b, NULL, blobmsg_data(var->data));
  856. blobmsg_close_table(b, e);
  857. }
  858. if (!avl_is_empty(&in->env.avl)) {
  859. struct blobmsg_list_node *var;
  860. void *e = blobmsg_open_table(b, "env");
  861. blobmsg_list_for_each(&in->env, var)
  862. blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
  863. blobmsg_close_table(b, e);
  864. }
  865. if (!avl_is_empty(&in->data.avl)) {
  866. struct blobmsg_list_node *var;
  867. void *e = blobmsg_open_table(b, "data");
  868. blobmsg_list_for_each(&in->data, var)
  869. blobmsg_add_blob(b, var->data);
  870. blobmsg_close_table(b, e);
  871. }
  872. if (!avl_is_empty(&in->limits.avl)) {
  873. struct blobmsg_list_node *var;
  874. void *e = blobmsg_open_table(b, "limits");
  875. blobmsg_list_for_each(&in->limits, var)
  876. blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
  877. blobmsg_close_table(b, e);
  878. }
  879. if (in->reload_signal)
  880. blobmsg_add_u32(b, "reload_signal", in->reload_signal);
  881. if (in->respawn) {
  882. void *r = blobmsg_open_table(b, "respawn");
  883. blobmsg_add_u32(b, "threshold", in->respawn_threshold);
  884. blobmsg_add_u32(b, "timeout", in->respawn_timeout);
  885. blobmsg_add_u32(b, "retry", in->respawn_retry);
  886. blobmsg_close_table(b, r);
  887. }
  888. if (in->trace)
  889. blobmsg_add_u8(b, "trace", true);
  890. if (in->no_new_privs)
  891. blobmsg_add_u8(b, "no_new_privs", true);
  892. if (in->seccomp)
  893. blobmsg_add_string(b, "seccomp", in->seccomp);
  894. if (in->pidfile)
  895. blobmsg_add_string(b, "pidfile", in->pidfile);
  896. if (in->has_jail) {
  897. void *r = blobmsg_open_table(b, "jail");
  898. if (in->jail.name)
  899. blobmsg_add_string(b, "name", in->jail.name);
  900. if (in->jail.hostname)
  901. blobmsg_add_string(b, "hostname", in->jail.hostname);
  902. blobmsg_add_u8(b, "procfs", in->jail.procfs);
  903. blobmsg_add_u8(b, "sysfs", in->jail.sysfs);
  904. blobmsg_add_u8(b, "ubus", in->jail.ubus);
  905. blobmsg_add_u8(b, "log", in->jail.log);
  906. blobmsg_add_u8(b, "ronly", in->jail.ronly);
  907. blobmsg_close_table(b, r);
  908. if (!avl_is_empty(&in->jail.mount.avl)) {
  909. struct blobmsg_list_node *var;
  910. void *e = blobmsg_open_table(b, "mount");
  911. blobmsg_list_for_each(&in->jail.mount, var)
  912. blobmsg_add_string(b, blobmsg_name(var->data), blobmsg_data(var->data));
  913. blobmsg_close_table(b, e);
  914. }
  915. }
  916. if (verbose && in->trigger)
  917. blobmsg_add_blob(b, in->trigger);
  918. blobmsg_close_table(b, i);
  919. }