* GNU General Public License for more details.
*/
+#define _GNU_SOURCE
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <unistd.h>
#include <stdint.h>
+#include <stdio.h>
#include <fcntl.h>
#include <pwd.h>
#include <libgen.h>
struct blobmsg_list_node *var;
struct blob_attr *cur;
char **argv;
+ char *ld_preload;
int argc = 1; /* NULL terminated */
int rem, _stdin;
+ bool seccomp = !in->trace && !in->has_jail && in->seccomp;
+ bool setlbf = _stdout >= 0;
if (in->nice)
setpriority(PRIO_PROCESS, 0, in->nice);
blobmsg_list_for_each(&in->env, var)
setenv(blobmsg_name(var->data), blobmsg_data(var->data), 1);
- if (!in->trace && !in->has_jail && in->seccomp) {
+ if (seccomp)
setenv("SECCOMP_FILE", in->seccomp, 1);
- setenv("LD_PRELOAD", "/lib/libpreload-seccomp.so", 1);
- }
+
+ if ((seccomp || setlbf) && asprintf(&ld_preload, "LD_PRELOAD=%s%s%s",
+ seccomp ? "/lib/libpreload-seccomp.so" : "",
+ seccomp && setlbf ? ":" : "",
+ setlbf ? "/lib/libsetlbf.so" : "") > 0)
+ putenv(ld_preload);
blobmsg_list_for_each(&in->limits, var)
instance_limits(blobmsg_name(var->data), blobmsg_data(var->data));
closefd(_stderr);
}
- if (in->uid || in->gid) {
- setuid(in->uid);
- setgid(in->gid);
+ if (in->gid && setgid(in->gid)) {
+ ERROR("failed to set group id %d: %d (%s)\n", in->gid, errno, strerror(errno));
+ exit(127);
+ }
+ if (in->uid && setuid(in->uid)) {
+ ERROR("failed to set user id %d: %d (%s)\n", in->uid, errno, strerror(errno));
+ exit(127);
}
+
execvp(argv[0], argv);
exit(127);
}
+static void
+instance_free_stdio(struct service_instance *in)
+{
+ if (in->_stdout.fd.fd > -1) {
+ ustream_free(&in->_stdout.stream);
+ close(in->_stdout.fd.fd);
+ in->_stdout.fd.fd = -1;
+ }
+
+ if (in->_stderr.fd.fd > -1) {
+ ustream_free(&in->_stderr.stream);
+ close(in->_stderr.fd.fd);
+ in->_stderr.fd.fd = -1;
+ }
+}
+
void
instance_start(struct service_instance *in)
{
if (in->proc.pending)
return;
+ instance_free_stdio(in);
if (in->_stdout.fd.fd > -2) {
if (pipe(opipe)) {
ULOG_WARN("pipe() failed: %d (%s)\n", errno, strerror(errno));
char *newline, *str, *arg0, ident[32];
int len;
+ arg0 = basename(blobmsg_data(blobmsg_data(in->command)));
+ snprintf(ident, sizeof(ident), "%s[%d]", arg0, in->proc.pid);
+ ulog_open(ULOG_SYSLOG, LOG_DAEMON, ident);
+
do {
str = ustream_get_read_buf(s, NULL);
if (!str)
break;
*newline = 0;
- len = newline + 1 - str;
-
- arg0 = basename(blobmsg_data(blobmsg_data(in->command)));
- snprintf(ident, sizeof(ident), "%s[%d]", arg0, in->proc.pid);
-
- ulog_open(ULOG_SYSLOG, LOG_DAEMON, ident);
ulog(prio, "%s\n", str);
- ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
+ len = newline + 1 - str;
ustream_consume(s, len);
} while (1);
+
+ ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd");
}
static void
void
instance_free(struct service_instance *in)
{
- if (in->_stdout.fd.fd > -1) {
- ustream_free(&in->_stdout.stream);
- close(in->_stdout.fd.fd);
- }
-
- if (in->_stderr.fd.fd > -1) {
- ustream_free(&in->_stderr.stream);
- close(in->_stderr.fd.fd);
- }
-
+ instance_free_stdio(in);
uloop_process_delete(&in->proc);
uloop_timeout_cancel(&in->timeout);
trigger_del(in);
{
void *i;
+ if (!in->valid)
+ return;
+
i = blobmsg_open_table(b, in->name);
blobmsg_add_u8(b, "running", in->proc.pending);
if (in->proc.pending)
if (in->respawn) {
void *r = blobmsg_open_table(b, "respawn");
- blobmsg_add_u32(b, "timeout", in->respawn_timeout);
blobmsg_add_u32(b, "threshold", in->respawn_threshold);
+ blobmsg_add_u32(b, "timeout", in->respawn_timeout);
blobmsg_add_u32(b, "retry", in->respawn_retry);
blobmsg_close_table(b, r);
}