Merge pull request #25718 from yuwata/locale-cleanups

locale: avoid TOCTOU in reading config files
This commit is contained in:
Yu Watanabe
2022-12-16 00:51:13 +09:00
committed by GitHub
8 changed files with 247 additions and 136 deletions
+70 -6
View File
@@ -12,11 +12,17 @@
#include "tmpfile-util.h"
#include "utf8.h"
typedef int (*push_env_func_t)(
const char *filename,
unsigned line,
const char *key,
char *value,
void *userdata);
static int parse_env_file_internal(
FILE *f,
const char *fname,
int (*push) (const char *filename, unsigned line,
const char *key, char *value, void *userdata),
push_env_func_t push,
void *userdata) {
size_t n_key = 0, n_value = 0, last_value_whitespace = SIZE_MAX, last_key_whitespace = SIZE_MAX;
@@ -37,6 +43,9 @@ static int parse_env_file_internal(
COMMENT_ESCAPE
} state = PRE_KEY;
assert(f || fname);
assert(push);
if (f)
r = read_full_stream(f, &contents, NULL);
else
@@ -274,6 +283,8 @@ static int check_utf8ness_and_warn(
const char *filename, unsigned line,
const char *key, char *value) {
assert(key);
if (!utf8_is_valid(key)) {
_cleanup_free_ char *p = NULL;
@@ -304,6 +315,8 @@ static int parse_env_file_push(
va_list aq, *ap = userdata;
int r;
assert(key);
r = check_utf8ness_and_warn(filename, line, key, value);
if (r < 0)
return r;
@@ -338,6 +351,8 @@ int parse_env_filev(
int r;
va_list aq;
assert(f || fname);
va_copy(aq, ap);
r = parse_env_file_internal(f, fname, parse_env_file_push, &aq);
va_end(aq);
@@ -352,6 +367,37 @@ int parse_env_file_sentinel(
va_list ap;
int r;
assert(f || fname);
va_start(ap, fname);
r = parse_env_filev(f, fname, ap);
va_end(ap);
return r;
}
int parse_env_file_fd_sentinel(
int fd,
const char *fname, /* only used for logging */
...) {
_cleanup_close_ int fd_ro = -EBADFD;
_cleanup_fclose_ FILE *f = NULL;
va_list ap;
int r;
assert(fd >= 0);
fd_ro = fd_reopen(fd, O_CLOEXEC | O_RDONLY);
if (fd_ro < 0)
return fd_ro;
f = fdopen(fd_ro, "re");
if (!f)
return -errno;
TAKE_FD(fd_ro);
va_start(ap, fname);
r = parse_env_filev(f, fname, ap);
va_end(ap);
@@ -363,10 +409,13 @@ static int load_env_file_push(
const char *filename, unsigned line,
const char *key, char *value,
void *userdata) {
char ***m = userdata;
char *p;
int r;
assert(key);
r = check_utf8ness_and_warn(filename, line, key, value);
if (r < 0)
return r;
@@ -383,15 +432,18 @@ static int load_env_file_push(
return 0;
}
int load_env_file(FILE *f, const char *fname, char ***rl) {
int load_env_file(FILE *f, const char *fname, char ***ret) {
_cleanup_strv_free_ char **m = NULL;
int r;
assert(f || fname);
assert(ret);
r = parse_env_file_internal(f, fname, load_env_file_push, &m);
if (r < 0)
return r;
*rl = TAKE_PTR(m);
*ret = TAKE_PTR(m);
return 0;
}
@@ -403,6 +455,8 @@ static int load_env_file_push_pairs(
char ***m = ASSERT_PTR(userdata);
int r;
assert(key);
r = check_utf8ness_and_warn(filename, line, key, value);
if (r < 0)
return r;
@@ -426,15 +480,17 @@ static int load_env_file_push_pairs(
return strv_extend(m, "");
}
int load_env_file_pairs(FILE *f, const char *fname, char ***rl) {
int load_env_file_pairs(FILE *f, const char *fname, char ***ret) {
_cleanup_strv_free_ char **m = NULL;
int r;
assert(f || fname);
r = parse_env_file_internal(f, fname, load_env_file_push_pairs, &m);
if (r < 0)
return r;
*rl = TAKE_PTR(m);
*ret = TAKE_PTR(m);
return 0;
}
@@ -446,6 +502,8 @@ static int merge_env_file_push(
char ***env = ASSERT_PTR(userdata);
char *expanded_value;
assert(key);
if (!value) {
log_error("%s:%u: invalid syntax (around \"%s\"), ignoring.", strna(filename), line, key);
return 0;
@@ -476,6 +534,9 @@ int merge_env_file(
FILE *f,
const char *fname) {
assert(env);
assert(f || fname);
/* NOTE: this function supports braceful and braceless variable expansions,
* plus "extended" substitutions, unlike other exported parsing functions.
*/
@@ -486,6 +547,9 @@ int merge_env_file(
static void write_env_var(FILE *f, const char *v) {
const char *p;
assert(f);
assert(v);
p = strchr(v, '=');
if (!p) {
/* Fallback */
+4 -2
View File
@@ -9,8 +9,10 @@
int parse_env_filev(FILE *f, const char *fname, va_list ap);
int parse_env_file_sentinel(FILE *f, const char *fname, ...) _sentinel_;
#define parse_env_file(f, fname, ...) parse_env_file_sentinel(f, fname, __VA_ARGS__, NULL)
int load_env_file(FILE *f, const char *fname, char ***l);
int load_env_file_pairs(FILE *f, const char *fname, char ***l);
int parse_env_file_fd_sentinel(int fd, const char *fname, ...) _sentinel_;
#define parse_env_file_fd(fd, fname, ...) parse_env_file_fd_sentinel(fd, fname, __VA_ARGS__, NULL)
int load_env_file(FILE *f, const char *fname, char ***ret);
int load_env_file_pairs(FILE *f, const char *fname, char ***ret);
int merge_env_file(char ***env, FILE *f, const char *fname);