mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 05:22:48 +07:00
Fix #45: add support for rlimit per service/run/task/inetd/tty
This patch extends the existing rlimit implementation to support setting limits per service, run/task, inetd, and tty. Use rlimit in /etc/finit.conf to change the global setting, which is then inherited to each /etc/finit.d/*.conf. For each .conf file the rlimit is reinitialized to the global finit.conf settings. Also, add `unlimited` keyword, to replace the now deprecated `infinity` keyword. The latter is however kept, for compatibility with previous releases, for the foreseeable future. Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
+7
-4
@@ -51,12 +51,15 @@ Syntax
|
|||||||
* `network <PATH>`
|
* `network <PATH>`
|
||||||
Script or program to bring up networking, with optional arguments
|
Script or program to bring up networking, with optional arguments
|
||||||
|
|
||||||
* `rlimit <hard|soft> RESOURCE <LIMIT|infinity>`
|
* `rlimit <hard|soft> RESOURCE <LIMIT|unlimited>`
|
||||||
Set the hard or soft limit for a resource. `RESOURCE` is a lower-case
|
Set the hard or soft limit for a resource. `RESOURCE` is a lower-case
|
||||||
string matching the `RLIMIT_` constants from `setrlimit(2)`, without
|
string matching the `RLIMIT_` constants from `setrlimit(2)`, without
|
||||||
the prefix. E.g. to set `RLIMIT_CPU`, use `cpu`. The limit is an
|
the prefix. E.g. to set `RLIMIT_CPU`, use `cpu`.
|
||||||
integer that depends on the resource being modified, see the man page
|
|
||||||
for more information. The special limit `infinity` means unlimited.
|
The limit is an integer that depends on the resource being modified,
|
||||||
|
see the man page, or the kernel `/proc/PID/limits` file, for more
|
||||||
|
information. Finit versions before v3.1 used `infinity` for
|
||||||
|
`unlimited`, which is still a supported keyword.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# No process is allowed more than 8MB of address space
|
# No process is allowed more than 8MB of address space
|
||||||
|
|||||||
+2
-1
@@ -29,6 +29,7 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
#define DAEMON "dbus-daemon"
|
#define DAEMON "dbus-daemon"
|
||||||
#define ARGS "--nofork --system"
|
#define ARGS "--nofork --system"
|
||||||
@@ -58,7 +59,7 @@ static void setup(void *arg)
|
|||||||
|
|
||||||
/* Register service with Finit */
|
/* Register service with Finit */
|
||||||
snprintf(line, sizeof(line), "[S12345] %s %s -- %s", cmd, ARGS, DESC);
|
snprintf(line, sizeof(line), "[S12345] %s %s -- %s", cmd, ARGS, DESC);
|
||||||
if (service_register(SVC_TYPE_SERVICE, line, NULL))
|
if (service_register(SVC_TYPE_SERVICE, line, global_rlimit, NULL))
|
||||||
_pe("Failed registering %s", DAEMON);
|
_pe("Failed registering %s", DAEMON);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
|
||||||
|
|||||||
+87
-49
@@ -38,6 +38,7 @@
|
|||||||
#define MATCH_CMD(l, c, x) \
|
#define MATCH_CMD(l, c, x) \
|
||||||
(!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
|
(!strncasecmp(l, c, strlen(c)) && (x = (l) + strlen(c)))
|
||||||
|
|
||||||
|
struct rlimit global_rlimit[RLIMIT_NLIMITS];
|
||||||
static int parse_conf(char *file);
|
static int parse_conf(char *file);
|
||||||
|
|
||||||
|
|
||||||
@@ -163,59 +164,74 @@ static const struct rlimit_name rlimit_names[] = {
|
|||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void conf_parse_rlimit(char *line)
|
int str2rlim(char *str)
|
||||||
{
|
{
|
||||||
struct rlimit rlim;
|
const struct rlimit_name *rn;
|
||||||
rlim_t cfg, *set;
|
|
||||||
const struct rlimit_name *name;
|
for (rn = rlimit_names; rn->name; rn++) {
|
||||||
|
if (!strcmp(str, rn->name))
|
||||||
|
return rn->val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *rlim2str(int rlim)
|
||||||
|
{
|
||||||
|
const struct rlimit_name *rn;
|
||||||
|
|
||||||
|
for (rn = rlimit_names; rn->name; rn++) {
|
||||||
|
if (rn->val == rlim)
|
||||||
|
return rn->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
void conf_parse_rlimit(char *line, struct rlimit arr[])
|
||||||
|
{
|
||||||
|
char *level, *limit, *val;
|
||||||
int resource = -1;
|
int resource = -1;
|
||||||
|
rlim_t cfg, *set;
|
||||||
|
|
||||||
char *tok = strtok(line, " \t");
|
level = strtok(line, " \t");
|
||||||
|
if (!level)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (tok && !strcmp(tok, "soft"))
|
limit = strtok(NULL, " \t");
|
||||||
set = &rlim.rlim_cur;
|
if (!limit)
|
||||||
else if (tok && !strcmp(tok, "hard"))
|
goto error;
|
||||||
set = &rlim.rlim_max;
|
|
||||||
|
resource = str2rlim(limit);
|
||||||
|
if (resource < 0 || resource > RLIMIT_NLIMITS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
val = strtok(NULL, " \t");
|
||||||
|
if (!val)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (!strcmp(level, "soft"))
|
||||||
|
set = &arr[resource].rlim_cur;
|
||||||
|
else if (!strcmp(level, "hard"))
|
||||||
|
set = &arr[resource].rlim_max;
|
||||||
else
|
else
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
tok = strtok(NULL, " \t");
|
/* Official keyword from v3.1 is `unlimited`, from prlimit(1) */
|
||||||
if (!tok)
|
if (!strcmp(val, "unlimited") || !strcmp(val, "infinity")) {
|
||||||
goto error;
|
|
||||||
|
|
||||||
for (name = rlimit_names; name->name; name++) {
|
|
||||||
if (!strcmp(tok, name->name))
|
|
||||||
resource = name->val;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resource < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
tok = strtok(NULL, " \t");
|
|
||||||
if (!tok)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (!strcmp(tok, "infinity")) {
|
|
||||||
cfg = RLIM_INFINITY;
|
cfg = RLIM_INFINITY;
|
||||||
} else {
|
} else {
|
||||||
const char *err = NULL;
|
const char *err = NULL;
|
||||||
|
|
||||||
cfg = strtonum(tok, 0, (long long)2 << 31, &err);
|
cfg = strtonum(val, 0, (long long)2 << 31, &err);
|
||||||
if (err)
|
if (err) {
|
||||||
goto fail;
|
logit(LOG_WARNING, "rlimit: invalid %s value: %s",
|
||||||
|
rlim2str(resource), val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getrlimit(resource, &rlim))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
*set = cfg;
|
*set = cfg;
|
||||||
if (setrlimit(resource, &rlim))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
logit(LOG_WARNING, "rlimit: Failed setting rlimit %s", name->name ? : "unknown");
|
|
||||||
return;
|
return;
|
||||||
error:
|
error:
|
||||||
logit(LOG_WARNING, "rlimit: parse error");
|
logit(LOG_WARNING, "rlimit: parse error");
|
||||||
@@ -289,7 +305,7 @@ static void parse_static(char *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_dynamic(char *line, struct timeval *mtime)
|
static void parse_dynamic(char *line, struct rlimit rlimit[], struct timeval *mtime)
|
||||||
{
|
{
|
||||||
char *x;
|
char *x;
|
||||||
char cmd[CMD_SIZE];
|
char cmd[CMD_SIZE];
|
||||||
@@ -315,26 +331,26 @@ static void parse_dynamic(char *line, struct timeval *mtime)
|
|||||||
|
|
||||||
/* Monitored daemon, will be respawned on exit */
|
/* Monitored daemon, will be respawned on exit */
|
||||||
if (MATCH_CMD(line, "service ", x)) {
|
if (MATCH_CMD(line, "service ", x)) {
|
||||||
service_register(SVC_TYPE_SERVICE, x, mtime);
|
service_register(SVC_TYPE_SERVICE, x, rlimit, mtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One-shot task, will not be respawned */
|
/* One-shot task, will not be respawned */
|
||||||
if (MATCH_CMD(line, "task ", x)) {
|
if (MATCH_CMD(line, "task ", x)) {
|
||||||
service_register(SVC_TYPE_TASK, x, mtime);
|
service_register(SVC_TYPE_TASK, x, rlimit, mtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like task but waits for completion, useful w/ [S] */
|
/* Like task but waits for completion, useful w/ [S] */
|
||||||
if (MATCH_CMD(line, "run ", x)) {
|
if (MATCH_CMD(line, "run ", x)) {
|
||||||
service_register(SVC_TYPE_RUN, x, mtime);
|
service_register(SVC_TYPE_RUN, x, rlimit, mtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Classic inetd service */
|
/* Classic inetd service */
|
||||||
if (MATCH_CMD(line, "inetd ", x)) {
|
if (MATCH_CMD(line, "inetd ", x)) {
|
||||||
#ifdef INETD_ENABLED
|
#ifdef INETD_ENABLED
|
||||||
service_register(SVC_TYPE_INETD, x, mtime);
|
service_register(SVC_TYPE_INETD, x, rlimit, mtime);
|
||||||
#else
|
#else
|
||||||
_e("Finit built with inetd support disabled, cannot register service inetd %s!", x);
|
_e("Finit built with inetd support disabled, cannot register service inetd %s!", x);
|
||||||
#endif
|
#endif
|
||||||
@@ -343,13 +359,13 @@ static void parse_dynamic(char *line, struct timeval *mtime)
|
|||||||
|
|
||||||
/* Read resource limits */
|
/* Read resource limits */
|
||||||
if (MATCH_CMD(line, "rlimit ", x)) {
|
if (MATCH_CMD(line, "rlimit ", x)) {
|
||||||
conf_parse_rlimit(x);
|
conf_parse_rlimit(x, rlimit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Regular or serial TTYs to run getty */
|
/* Regular or serial TTYs to run getty */
|
||||||
if (MATCH_CMD(line, "tty ", x)) {
|
if (MATCH_CMD(line, "tty ", x)) {
|
||||||
tty_register(strip_line(x), mtime);
|
tty_register(strip_line(x), rlimit, mtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,6 +384,7 @@ static void tabstospaces(char *line)
|
|||||||
static int parse_conf_dynamic(char *file, struct timeval *mtime)
|
static int parse_conf_dynamic(char *file, struct timeval *mtime)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
struct rlimit rlimit[RLIMIT_NLIMITS];
|
||||||
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
@@ -375,6 +392,9 @@ static int parse_conf_dynamic(char *file, struct timeval *mtime)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Prepare default limits for each service */
|
||||||
|
memcpy(rlimit, global_rlimit, sizeof(rlimit));
|
||||||
|
|
||||||
_d("Parsing %s", file);
|
_d("Parsing %s", file);
|
||||||
while (!feof(fp)) {
|
while (!feof(fp)) {
|
||||||
char line[LINE_SIZE] = "";
|
char line[LINE_SIZE] = "";
|
||||||
@@ -386,7 +406,7 @@ static int parse_conf_dynamic(char *file, struct timeval *mtime)
|
|||||||
tabstospaces(line);
|
tabstospaces(line);
|
||||||
_d("%s", line);
|
_d("%s", line);
|
||||||
|
|
||||||
parse_dynamic(line, mtime);
|
parse_dynamic(line, rlimit, mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -394,11 +414,19 @@ static int parse_conf_dynamic(char *file, struct timeval *mtime)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reads /etc/finit.conf, once at boot */
|
||||||
static int parse_conf(char *file)
|
static int parse_conf(char *file)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char line[LINE_SIZE] = "";
|
char line[LINE_SIZE] = "";
|
||||||
char *x;
|
|
||||||
|
/*
|
||||||
|
* Get current global limits, which may be overridden from both
|
||||||
|
* finit.conf, for Finit and its services like inetd+getty, and
|
||||||
|
* *.conf in finit.d/, for each service(s) listed there.
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < RLIMIT_NLIMITS; i++)
|
||||||
|
getrlimit(i, &global_rlimit[i]);
|
||||||
|
|
||||||
fp = fopen(file, "r");
|
fp = fopen(file, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
@@ -414,11 +442,17 @@ static int parse_conf(char *file)
|
|||||||
_d("%s", line);
|
_d("%s", line);
|
||||||
|
|
||||||
parse_static(line);
|
parse_static(line);
|
||||||
parse_dynamic(line, NULL);
|
parse_dynamic(line, global_rlimit, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
/* Set global limits */
|
||||||
|
for (int i = 0; i < RLIMIT_NLIMITS; i++) {
|
||||||
|
if (setrlimit(i, &global_rlimit[i]) == -1)
|
||||||
|
logit(LOG_WARNING, "rlimit: Failed setting %s", rlim2str(i));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,6 +473,10 @@ int conf_reload_dynamic(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update global limits in case operator used prlimit(1) on us */
|
||||||
|
for (i = 0; i < RLIMIT_NLIMITS; i++)
|
||||||
|
getrlimit(i, &global_rlimit[i]);
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
char *name = e[i]->d_name;
|
char *name = e[i]->d_name;
|
||||||
char path[LINE_SIZE];
|
char path[LINE_SIZE];
|
||||||
|
|||||||
@@ -26,6 +26,11 @@
|
|||||||
|
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
|
extern struct rlimit global_rlimit[];
|
||||||
|
|
||||||
|
int str2rlim(char *str);
|
||||||
|
char *rlim2str(int rlim);
|
||||||
|
|
||||||
void conf_parse_cmdline (void);
|
void conf_parse_cmdline (void);
|
||||||
int conf_parse_runlevels (char *runlevels);
|
int conf_parse_runlevels (char *runlevels);
|
||||||
void conf_parse_cond (svc_t *svc, char *cond);
|
void conf_parse_cond (svc_t *svc, char *cond);
|
||||||
|
|||||||
+11
-5
@@ -234,7 +234,7 @@ int exec_runtask(char *cmd, char *args[])
|
|||||||
return execvp(_PATH_BSHELL, argv);
|
return execvp(_PATH_BSHELL, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_tty(char *tty, speed_t speed, char *procname)
|
static void prepare_tty(char *tty, speed_t speed, char *procname, struct rlimit rlimit[])
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
struct termios term;
|
struct termios term;
|
||||||
@@ -270,6 +270,12 @@ static void prepare_tty(char *tty, speed_t speed, char *procname)
|
|||||||
sigaction(SIGINT, &sa, NULL);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
sigaction(SIGQUIT, &sa, NULL);
|
sigaction(SIGQUIT, &sa, NULL);
|
||||||
|
|
||||||
|
/* Set configured limits */
|
||||||
|
for (int i = 0; i < RLIMIT_NLIMITS; i++) {
|
||||||
|
if (setrlimit(i, &rlimit[i]) == -1)
|
||||||
|
logit(LOG_WARNING, "%s: rlimit: Failed setting %s", tty, rlim2str(i));
|
||||||
|
}
|
||||||
|
|
||||||
/* Create new session and process group */
|
/* Create new session and process group */
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
@@ -348,7 +354,7 @@ static int activate_console(int noclear, int nowait)
|
|||||||
* since /bin/login usually only disables ECHO until a password line has
|
* since /bin/login usually only disables ECHO until a password line has
|
||||||
* been entered. Upon starting the user's $SHELL the ISIG flag is reset
|
* been entered. Upon starting the user's $SHELL the ISIG flag is reset
|
||||||
*/
|
*/
|
||||||
pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait)
|
pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait, struct rlimit rlimit[])
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
@@ -362,7 +368,7 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait)
|
|||||||
logit(LOG_CRIT, "TTY %s: Invalid speed %s", tty, baud);
|
logit(LOG_CRIT, "TTY %s: Invalid speed %s", tty, baud);
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare_tty(tty, speed, "finit-getty");
|
prepare_tty(tty, speed, "finit-getty", rlimit);
|
||||||
if (activate_console(noclear, nowait))
|
if (activate_console(noclear, nowait))
|
||||||
_exit(getty(tty, speed, term, NULL));
|
_exit(getty(tty, speed, term, NULL));
|
||||||
}
|
}
|
||||||
@@ -370,7 +376,7 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait)
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait)
|
pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[])
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
@@ -400,7 +406,7 @@ pid_t run_getty2(char *tty, char *cmd, char *args[], int noclear, int nowait)
|
|||||||
dup2(fd, STDERR_FILENO);
|
dup2(fd, STDERR_FILENO);
|
||||||
|
|
||||||
/* Dunno speed, tell stty() to not mess with it */
|
/* Dunno speed, tell stty() to not mess with it */
|
||||||
prepare_tty(tty, B0, "getty");
|
prepare_tty(tty, B0, "getty", rlimit);
|
||||||
|
|
||||||
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
if (ioctl(STDIN_FILENO, TIOCSCTTY, 1) < 0)
|
||||||
_pe("Failed TIOCSCTTY");
|
_pe("Failed TIOCSCTTY");
|
||||||
|
|||||||
+1
-1
@@ -357,7 +357,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
/* Register udevd as a monitored service, started much later */
|
/* Register udevd as a monitored service, started much later */
|
||||||
snprintf(cmd, sizeof(cmd), "[12345] %s -- Device event manager daemon", path);
|
snprintf(cmd, sizeof(cmd), "[12345] %s -- Device event manager daemon", path);
|
||||||
if (service_register(SVC_TYPE_SERVICE, cmd, NULL)) {
|
if (service_register(SVC_TYPE_SERVICE, cmd, global_rlimit, NULL)) {
|
||||||
_pe("Failed registering %s", path);
|
_pe("Failed registering %s", path);
|
||||||
udev = 0;
|
udev = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -26,6 +26,7 @@
|
|||||||
#define FINIT_HELPERS_H_
|
#define FINIT_HELPERS_H_
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ttydefaults.h> /* Not included by default in musl libc */
|
#include <sys/ttydefaults.h> /* Not included by default in musl libc */
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
@@ -71,8 +72,8 @@ int complete (char *cmd, int pid);
|
|||||||
int run (char *cmd);
|
int run (char *cmd);
|
||||||
int run_interactive (char *cmd, char *fmt, ...);
|
int run_interactive (char *cmd, char *fmt, ...);
|
||||||
int exec_runtask (char *cmd, char *args[]);
|
int exec_runtask (char *cmd, char *args[]);
|
||||||
pid_t run_getty (char *tty, char *baud, char *term, int noclear, int nowait);
|
pid_t run_getty (char *tty, char *baud, char *term, int noclear, int nowait, struct rlimit rlimit[]);
|
||||||
pid_t run_getty2 (char *tty, char *cmd, char *args[], int noclear, int nowait);
|
pid_t run_getty2 (char *tty, char *cmd, char *args[], int noclear, int nowait, struct rlimit rlimit[]);
|
||||||
int run_parts (char *dir, char *cmd);
|
int run_parts (char *dir, char *cmd);
|
||||||
|
|
||||||
static inline void create(char *path, mode_t mode, uid_t uid, gid_t gid)
|
static inline void create(char *path, mode_t mode, uid_t uid, gid_t gid)
|
||||||
|
|||||||
+19
-7
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <ctype.h> /* isblank() */
|
#include <ctype.h> /* isblank() */
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <lite/lite.h>
|
#include <lite/lite.h>
|
||||||
@@ -192,6 +193,14 @@ static int service_start(svc_t *svc)
|
|||||||
#endif
|
#endif
|
||||||
char *args[MAX_NUM_SVC_ARGS];
|
char *args[MAX_NUM_SVC_ARGS];
|
||||||
|
|
||||||
|
/* Set configured limits */
|
||||||
|
for (int i = 0; i < RLIMIT_NLIMITS; i++) {
|
||||||
|
if (setrlimit(i, &svc->rlimit[i]) == -1)
|
||||||
|
logit(LOG_WARNING,
|
||||||
|
"%s: rlimit: Failed setting %s",
|
||||||
|
svc->cmd, rlim2str(i));
|
||||||
|
}
|
||||||
|
|
||||||
/* Set desired user+group */
|
/* Set desired user+group */
|
||||||
if (gid >= 0)
|
if (gid >= 0)
|
||||||
setgid(gid);
|
setgid(gid);
|
||||||
@@ -471,9 +480,10 @@ void service_runlevel(int newlevel)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* service_register - Register service, task or run commands
|
* service_register - Register service, task or run commands
|
||||||
* @type: %SVC_TYPE_SERVICE(0), %SVC_TYPE_TASK(1), %SVC_TYPE_RUN(2)
|
* @type: %SVC_TYPE_SERVICE(0), %SVC_TYPE_TASK(1), %SVC_TYPE_RUN(2)
|
||||||
* @svcline: A complete command line with -- separated description text
|
* @cfg: Configuration, complete command, with -- for description text
|
||||||
* @mtime: The modification time if service is loaded from /etc/finit.d
|
* @rlimit: Limits for this service/task/run/inetd, may be global limits
|
||||||
|
* @mtime: The modification time if service is loaded from /etc/finit.d
|
||||||
*
|
*
|
||||||
* This function is used to register commands to be run on different
|
* This function is used to register commands to be run on different
|
||||||
* system runlevels with optional username. The @type argument details
|
* system runlevels with optional username. The @type argument details
|
||||||
@@ -520,7 +530,7 @@ void service_runlevel(int newlevel)
|
|||||||
* Returns:
|
* Returns:
|
||||||
* POSIX OK(0) on success, or non-zero errno exit status on failure.
|
* POSIX OK(0) on success, or non-zero errno exit status on failure.
|
||||||
*/
|
*/
|
||||||
int service_register(int type, char *svcline, struct timeval *mtime)
|
int service_register(int type, char *cfg, struct rlimit rlimit[], struct timeval *mtime)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int id = 1; /* Default to ID:1 */
|
int id = 1; /* Default to ID:1 */
|
||||||
@@ -534,12 +544,12 @@ int service_register(int type, char *svcline, struct timeval *mtime)
|
|||||||
svc_t *svc;
|
svc_t *svc;
|
||||||
plugin_t *plugin = NULL;
|
plugin_t *plugin = NULL;
|
||||||
|
|
||||||
if (!svcline) {
|
if (!cfg) {
|
||||||
_e("Invalid input argument");
|
_e("Invalid input argument");
|
||||||
return errno = EINVAL;
|
return errno = EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
line = strdup(svcline);
|
line = strdup(cfg);
|
||||||
if (!line)
|
if (!line)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -555,7 +565,7 @@ int service_register(int type, char *svcline, struct timeval *mtime)
|
|||||||
cmd = strtok(line, " ");
|
cmd = strtok(line, " ");
|
||||||
if (!cmd) {
|
if (!cmd) {
|
||||||
incomplete:
|
incomplete:
|
||||||
_e("Incomplete service '%s', cannot register", svcline);
|
_e("Incomplete service '%s', cannot register", cfg);
|
||||||
free(line);
|
free(line);
|
||||||
return errno = ENOENT;
|
return errno = ENOENT;
|
||||||
}
|
}
|
||||||
@@ -718,6 +728,8 @@ recreate:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* Set configured limits */
|
||||||
|
memcpy(svc->rlimit, rlimit, sizeof(svc->rlimit));
|
||||||
|
|
||||||
/* New, recently modified or unchanged ... used on reload. */
|
/* New, recently modified or unchanged ... used on reload. */
|
||||||
svc_check_dirty(svc, mtime);
|
svc_check_dirty(svc, mtime);
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@
|
|||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
void service_runlevel (int newlevel);
|
void service_runlevel (int newlevel);
|
||||||
int service_register (int type, char *line, struct timeval *mtime);
|
int service_register (int type, char *line, struct rlimit rlimit[], struct timeval *mtime);
|
||||||
void service_unregister (svc_t *svc);
|
void service_unregister (svc_t *svc);
|
||||||
int service_enabled (svc_t *svc);
|
int service_enabled (svc_t *svc);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define FINIT_SVC_H_
|
#define FINIT_SVC_H_
|
||||||
|
|
||||||
#include <sys/ipc.h> /* IPC_CREAT */
|
#include <sys/ipc.h> /* IPC_CREAT */
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/shm.h> /* shmat() */
|
#include <sys/shm.h> /* shmat() */
|
||||||
#include <sys/types.h> /* pid_t */
|
#include <sys/types.h> /* pid_t */
|
||||||
#include <lite/lite.h>
|
#include <lite/lite.h>
|
||||||
@@ -84,6 +85,9 @@ typedef struct svc {
|
|||||||
/* Instance specifics */
|
/* Instance specifics */
|
||||||
int job, id; /* JOB:ID */
|
int job, id; /* JOB:ID */
|
||||||
|
|
||||||
|
/* Limits and scoping */
|
||||||
|
struct rlimit rlimit[RLIMIT_NLIMITS];
|
||||||
|
|
||||||
/* Service details */
|
/* Service details */
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
const svc_state_t state; /* Paused, Reloading, Restart, Running, ... */
|
const svc_state_t state; /* Paused, Reloading, Restart, Running, ... */
|
||||||
|
|||||||
@@ -127,8 +127,9 @@ void tty_sweep(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_register - Register a getty on a device
|
* tty_register - Register a getty on a device
|
||||||
* @line: Configuration, text after initial "tty"
|
* @line: Configuration, text after initial "tty"
|
||||||
* @mtime: Modification time, to propagate to lower layers
|
* @rlimit: Limits for this service/task/run/inetd, may be global limits
|
||||||
|
* @mtime: Modification time, to propagate to lower layers
|
||||||
*
|
*
|
||||||
* A Finit tty line can use the internal getty implementation or an
|
* A Finit tty line can use the internal getty implementation or an
|
||||||
* external one, like the BusyBox getty for instance. This function
|
* external one, like the BusyBox getty for instance. This function
|
||||||
@@ -146,7 +147,7 @@ void tty_sweep(void)
|
|||||||
* Different getty implementations prefer the TTY device argument in
|
* Different getty implementations prefer the TTY device argument in
|
||||||
* different order, so take care to investigate this first.
|
* different order, so take care to investigate this first.
|
||||||
*/
|
*/
|
||||||
int tty_register(char *line, struct timeval *mtime)
|
int tty_register(char *line, struct rlimit rlimit[], struct timeval *mtime)
|
||||||
{
|
{
|
||||||
tty_node_t *entry;
|
tty_node_t *entry;
|
||||||
int insert = 0, noclear = 0, nowait = 0;
|
int insert = 0, noclear = 0, nowait = 0;
|
||||||
@@ -278,6 +279,9 @@ int tty_register(char *line, struct timeval *mtime)
|
|||||||
if (insert)
|
if (insert)
|
||||||
LIST_INSERT_HEAD(&tty_list, entry, link);
|
LIST_INSERT_HEAD(&tty_list, entry, link);
|
||||||
|
|
||||||
|
/* Register configured limits */
|
||||||
|
memcpy(entry->data.rlimit, rlimit, sizeof(entry->data.rlimit));
|
||||||
|
|
||||||
tty_check(entry, mtime);
|
tty_check(entry, mtime);
|
||||||
_d("TTY %s is %sdirty", dev, entry->dirty ? "" : "NOT ");
|
_d("TTY %s is %sdirty", dev, entry->dirty ? "" : "NOT ");
|
||||||
|
|
||||||
@@ -399,9 +403,9 @@ void tty_start(finit_tty_t *tty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!tty->cmd)
|
if (!tty->cmd)
|
||||||
tty->pid = run_getty(dev, tty->baud, tty->term, tty->noclear, tty->nowait);
|
tty->pid = run_getty(dev, tty->baud, tty->term, tty->noclear, tty->nowait, tty->rlimit);
|
||||||
else
|
else
|
||||||
tty->pid = run_getty2(dev, tty->cmd, tty->args, tty->noclear, tty->nowait);
|
tty->pid = run_getty2(dev, tty->cmd, tty->args, tty->noclear, tty->nowait, tty->rlimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tty_stop(finit_tty_t *tty)
|
void tty_stop(finit_tty_t *tty)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define FINIT_TTY_H_
|
#define FINIT_TTY_H_
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <lite/queue.h> /* BSD sys/queue.h API */
|
#include <lite/queue.h> /* BSD sys/queue.h API */
|
||||||
|
|
||||||
#define TTY_MAX_ARGS 16
|
#define TTY_MAX_ARGS 16
|
||||||
@@ -43,6 +44,9 @@ typedef struct {
|
|||||||
char *args[TTY_MAX_ARGS];
|
char *args[TTY_MAX_ARGS];
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
|
/* Limits and scoping */
|
||||||
|
struct rlimit rlimit[RLIMIT_NLIMITS];
|
||||||
} finit_tty_t;
|
} finit_tty_t;
|
||||||
|
|
||||||
typedef struct tty_node {
|
typedef struct tty_node {
|
||||||
@@ -61,7 +65,7 @@ void tty_mark (void);
|
|||||||
void tty_check (tty_node_t *tty, struct timeval *mtime);
|
void tty_check (tty_node_t *tty, struct timeval *mtime);
|
||||||
void tty_sweep (void);
|
void tty_sweep (void);
|
||||||
|
|
||||||
int tty_register (char *line, struct timeval *mtime);
|
int tty_register (char *line, struct rlimit rlimit[], struct timeval *mtime);
|
||||||
int tty_unregister (tty_node_t *tty);
|
int tty_unregister (tty_node_t *tty);
|
||||||
|
|
||||||
tty_node_t *tty_find (char *dev);
|
tty_node_t *tty_find (char *dev);
|
||||||
|
|||||||
Reference in New Issue
Block a user