service_register(): guard against loss of command args

We use strtok() quite extensively in .conf parser.  Parsing of a service
line is split in two, with the command arguments being parsed very late.

Adding a new sub-option parser, based on strtok(), risk losing command
arguments.  Thus, change to use strtok_r() so that we always know where
the arg parser is.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg committed 2022-12-18 14:43:51 +01:00
1 parent 8b5435908c
commit 0e04ffd68f
3 files changed
+14 -17

No files matched your search

+8 -13
View File
@@ -1175,13 +1175,8 @@ static char *parse_name(char *cmd, char *arg)
/*
* Update the command line args in the svc struct
*
* strtok internal pointer must be positioned at first command line arg
* when this function is called.
*
* Side effect: strtok internal pointer will be modified.
*/
static void parse_cmdline_args(svc_t *svc, char *cmd)
static void parse_cmdline_args(svc_t *svc, char *cmd, char **args)
{
int diff = 0;
char sep = 0;
@@ -1196,7 +1191,7 @@ static void parse_cmdline_args(svc_t *svc, char *cmd)
* Copy supplied args. Stop at MAX_NUM_SVC_ARGS-1 to allow the args
* array to be zero-terminated.
*/
while ((arg = strtok(NULL, " ")) && i < (MAX_NUM_SVC_ARGS - 1)) {
while ((arg = strtok_r(NULL, " ", args)) && i < (MAX_NUM_SVC_ARGS - 1)) {
char prev[sizeof(svc->args[0])] = { 0 };
char ch = arg[0];
size_t len;
@@ -1327,7 +1322,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
int restart_max = SVC_RESPAWN_MAX;
int restart_tmo = 0;
unsigned oncrash_action = SVC_ONCRASH_IGNORE;
char *line;
char *line, *args;
svc_t *svc;
if (!cfg) {
@@ -1357,7 +1352,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
}
}
cmd = strtok(line, " \t");
cmd = strtok_r(line, " \t", &args);
if (!cmd) {
incomplete:
errx(1, "Incomplete service '%s', cannot register", cfg);
@@ -1430,7 +1425,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
break;
/* Check if valid command follows... */
cmd = strtok(NULL, " ");
cmd = strtok_r(NULL, " ", &args);
if (!cmd)
goto incomplete;
}
@@ -1448,7 +1443,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
if (type == SVC_TYPE_TTY) {
size_t i, len = 0;
if (tty_parse_args(cmd, &tty))
if (tty_parse_args(&tty, cmd, &args))
return errno;
if (tty.cmd)
@@ -1469,7 +1464,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
strlcat(line, tty.args[i], len);
}
cmd = strtok(line, " \t");
cmd = strtok_r(line, " \t", &args);
if (!cmd)
return errno;
@@ -1559,7 +1554,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
strlcpy(svc->id, id, sizeof(svc->id));
}
parse_cmdline_args(svc, cmd);
parse_cmdline_args(svc, cmd, &args);
/*
* Warn if svc generates same condition (based on name:id)
+5 -3
View File
@@ -133,7 +133,9 @@ char *tty_atcon(void)
/**
* tty_parse_args - Parse cmdline args for a tty
* @cmd: command or tty
* @tty: service tty
* @cmd: command or tty
* @args: args from strtok_r()
*
* A Finit tty line can use the internal getty implementation or an
* external one, like the BusyBox getty for instance. This function
@@ -151,7 +153,7 @@ char *tty_atcon(void)
* Different getty implementations prefer the TTY device argument in
* different order, so take care to investigate this first.
*/
int tty_parse_args(char *cmd, struct tty *tty)
int tty_parse_args(struct tty *tty, char *cmd, char **args)
{
char *dev = NULL;
int passenv = 0;
@@ -175,7 +177,7 @@ int tty_parse_args(char *cmd, struct tty *tty)
else
tty->args[tty->num++] = cmd;
cmd = strtok(NULL, " ");
cmd = strtok_r(NULL, " ", args);
} while (cmd && tty->num < NELEMS(tty->args));
/* rescue shells are always notty */
+1 -1
View File
@@ -48,7 +48,7 @@ char *tty_canonicalize (char *dev);
int tty_isatcon (char *dev);
char *tty_atcon (void);
int tty_parse_args (char *cmdline, struct tty *tty);
int tty_parse_args (struct tty *tty, char *cmd, char **args);
int tty_exists (char *dev);
int tty_exec (svc_t *tty);