1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-26 14:04:03 +03:00

Merge pull request #19515 from keszybz/config-parser-crash-fix

Fix crashes in config parsing
This commit is contained in:
Yu Watanabe 2021-05-06 12:46:13 +09:00 committed by GitHub
commit d8c1422439
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 113 additions and 129 deletions

View File

@ -1431,10 +1431,9 @@ int log_syntax_invalid_utf8_internal(
if (rvalue)
p = utf8_escape_invalid(rvalue);
log_syntax_internal(unit, level, config_file, config_line, 0, file, line, func,
"String is not UTF-8 clean, ignoring assignment: %s", strna(p));
return -EINVAL;
return log_syntax_internal(unit, level, config_file, config_line,
SYNTHETIC_ERRNO(EINVAL), file, line, func,
"String is not UTF-8 clean, ignoring assignment: %s", strna(p));
}
void log_set_upgrade_syslog_to_journal(bool b) {

View File

@ -2213,14 +2213,14 @@ int config_parse_service_sockets(
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Trailing garbage in sockets, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = unit_name_printf(UNIT(s), word, &k);
if (r < 0) {
@ -2488,14 +2488,14 @@ int config_parse_user_group_strv_compat(
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax: %s", rvalue);
return -ENOEXEC;
}
if (r == 0)
return 0;
r = unit_full_printf(u, word, &k);
if (r < 0) {
@ -2654,8 +2654,6 @@ int config_parse_environ(
_cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -2663,6 +2661,8 @@ int config_parse_environ(
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
if (u) {
r = unit_full_printf(u, word, &resolved);
@ -2719,8 +2719,6 @@ int config_parse_pass_environ(
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -2728,6 +2726,8 @@ int config_parse_pass_environ(
"Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
if (r == 0)
break;
if (u) {
r = unit_full_printf(u, word, &k);
@ -2794,8 +2794,6 @@ int config_parse_unset_environ(
_cleanup_free_ char *word = NULL, *k = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -2803,6 +2801,8 @@ int config_parse_unset_environ(
"Trailing garbage in %s, ignoring: %s", lvalue, rvalue);
break;
}
if (r == 0)
break;
if (u) {
r = unit_full_printf(u, word, &k);
@ -2868,14 +2868,14 @@ int config_parse_log_extra_fields(
const char *eq;
r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = unit_full_printf(u, word, &k);
if (r < 0) {
@ -3080,8 +3080,6 @@ int config_parse_unit_requires_mounts_for(
_cleanup_free_ char *word = NULL, *resolved = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -3089,6 +3087,8 @@ int config_parse_unit_requires_mounts_for(
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = unit_full_printf(u, word, &resolved);
if (r < 0) {
@ -3218,8 +3218,6 @@ int config_parse_syscall_filter(
int num;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -3227,6 +3225,8 @@ int config_parse_syscall_filter(
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = parse_syscall_and_errno(word, &name, &num);
if (r < 0) {
@ -3304,14 +3304,14 @@ int config_parse_syscall_log(
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = seccomp_parse_syscall_filter(
word, -1, c->syscall_log,
@ -3349,8 +3349,6 @@ int config_parse_syscall_archs(
uint32_t a;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -3358,6 +3356,8 @@ int config_parse_syscall_archs(
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
r = seccomp_arch_from_string(word, &a);
if (r < 0) {
@ -3463,8 +3463,6 @@ int config_parse_address_families(
int af;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
@ -3472,6 +3470,8 @@ int config_parse_address_families(
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
af = af_from_name(word);
if (af < 0) {
@ -3821,14 +3821,14 @@ int config_parse_delegate(
CGroupController cc;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
break;
cc = cgroup_controller_from_string(word);
if (cc < 0) {
@ -3954,13 +3954,8 @@ int config_parse_device_allow(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device path and rights from '%s', ignoring.", rvalue);
return 0;
}
@ -4025,13 +4020,8 @@ int config_parse_io_device_weight(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device path and weight from '%s', ignoring.", rvalue);
return 0;
}
@ -4099,13 +4089,8 @@ int config_parse_io_device_latency(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device path and latency from '%s', ignoring.", rvalue);
return 0;
}
@ -4174,13 +4159,8 @@ int config_parse_io_limit(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
@ -4265,13 +4245,8 @@ int config_parse_blockio_device_weight(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device node and weight from '%s', ignoring.", rvalue);
return 0;
}
@ -4343,13 +4318,8 @@ int config_parse_blockio_bandwidth(
r = extract_first_word(&p, &path, NULL, EXTRACT_UNQUOTE);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0 || isempty(p)) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to extract device node and bandwidth from '%s', ignoring.", rvalue);
return 0;
}
@ -4751,14 +4721,14 @@ int config_parse_namespace_path_strv(
bool ignore_enoent = false, shall_prefix = false;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
break;
w = word;
if (startswith(w, "-")) {
@ -4828,14 +4798,14 @@ int config_parse_temporary_filesystems(
const char *w;
r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
if (r == 0)
return 0;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
w = word;
r = extract_first_word(&w, &path, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
@ -4902,14 +4872,14 @@ int config_parse_bind_paths(
bool rbind = true, ignore_enoent = false;
r = extract_first_word(&p, &source, ":" WHITESPACE, EXTRACT_UNQUOTE|EXTRACT_DONT_COALESCE_SEPARATORS);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
return 0;
}
if (r == 0)
break;
r = unit_full_printf(u, source, &sresolved);
if (r < 0) {
@ -5630,7 +5600,7 @@ int config_parse_bpf_foreign_program(
r = extract_first_word(&rvalue, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
if (r <= 0 || isempty(rvalue)) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse foreign BPF program, ignoring: %s", rvalue);
return 0;
}
@ -5670,11 +5640,11 @@ int config_parse_cgroup_socket_bind(
void *data,
void *userdata) {
_cleanup_free_ CGroupSocketBindItem *item = NULL;
const char *address_family = NULL, *user_port;
const char *user_port;
uint16_t nr_ports = 0, port_min = 0;
CGroupSocketBindItem **head = data;
_cleanup_free_ char *word = NULL;
int af = AF_UNSPEC, r;
int af, r;
if (isempty(rvalue)) {
cgroup_context_remove_socket_bind(head);
@ -5684,29 +5654,40 @@ int config_parse_cgroup_socket_bind(
r = extract_first_word(&rvalue, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (rvalue)
address_family = word;
if (address_family) {
if (streq(address_family, "IPv4"))
af = AF_INET;
else if (streq(address_family, "IPv6"))
af = AF_INET6;
else
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
"Only IPv4 or IPv6 protocols are supported, ignoring");
if (r <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Unable to parse %s= assignment, ignoring: %s", lvalue, rvalue);
return 0;
}
if (rvalue) {
if (streq(word, "IPv4"))
af = AF_INET;
else if (streq(word, "IPv6"))
af = AF_INET6;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Only IPv4 and IPv6 protocols are supported, ignoring.");
return 0;
}
user_port = rvalue;
} else {
af = AF_UNSPEC;
user_port = word;
}
user_port = rvalue ?: word;
if (!streq(user_port, "any")) {
uint16_t port_max;
r = parse_ip_port_range(user_port, &port_min, &port_max);
if (r == -ENOMEM)
return log_oom();
if (r < 0)
return log_warning_errno(r, "Invalid port or port range, ignoring: %m");
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid port or port range, ignoring: %m");
return 0;
}
nr_ports = 1 + port_max - port_min;
}

View File

@ -10,6 +10,11 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size == 0)
return 0;
/* We don't want to fill the logs with assert warnings.
* Disable most logging if not running standalone */
if (!getenv("SYSTEMD_LOG_LEVEL"))
log_set_max_level(LOG_CRIT);
dummy_server_init(&s, data, size);
dev_kmsg_record(&s, s.buffer, size);
server_done(&s);

View File

@ -245,72 +245,69 @@ _public_ int sd_device_new_from_devnum(sd_device **ret, char type, dev_t devnum)
}
_public_ int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname) {
char *name, *syspath;
size_t len = 0;
char syspath[PATH_MAX], *name;
assert_return(ret, -EINVAL);
assert_return(subsystem, -EINVAL);
assert_return(sysname, -EINVAL);
assert_return(strlen(sysname) < PATH_MAX - strlen("/sys/bus/"), -ENAMETOOLONG);
if (streq(subsystem, "subsystem")) {
syspath = strjoina("/sys/subsystem/", sysname);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s", sysname) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/bus/", sysname);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s", sysname) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/class/", sysname);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/class/%s", sysname) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
} else if (streq(subsystem, "module")) {
syspath = strjoina("/sys/module/", sysname);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/module/%s", sysname) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
} else if (streq(subsystem, "drivers")) {
char subsys[PATH_MAX];
char *driver;
const char *subsys, *sep;
strscpy(subsys, sizeof(subsys), sysname);
driver = strchr(subsys, ':');
if (driver) {
driver[0] = '\0';
driver++;
sep = strchr(sysname, ':');
if (sep && sep[1] != '\0') { /* Require ":" and something non-empty after that. */
subsys = memdupa_suffix0(sysname, sep - sysname);
syspath = strjoina("/sys/subsystem/", subsys, "/drivers/", driver);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s/drivers/%s", subsys, sep + 1) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/bus/", subsys, "/drivers/", driver);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s/drivers/%s", subsys, sep + 1) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
}
}
/* translate sysname back to sysfs filename */
name = strdupa(sysname);
while (name[len] != '\0') {
if (name[len] == '/')
name[len] = '!';
len++;
}
for (size_t i = 0; name[i]; i++)
if (name[i] == '/')
name[i] = '!';
syspath = strjoina("/sys/subsystem/", subsystem, "/devices/", name);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/subsystem/%s/devices/%s", subsystem, name) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/bus/", subsystem, "/devices/", name);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/bus/%s/devices/%s", subsystem, name) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/class/", subsystem, "/", name);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/class/%s/%s", subsystem, name) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
if (access(syspath, F_OK) >= 0)
if (snprintf_ok(syspath, sizeof syspath, "/sys/firmware/%s/%s", subsystem, sysname) &&
access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
return -ENODEV;
@ -652,17 +649,15 @@ _public_ int sd_device_new_from_device_id(sd_device **ret, const char *id) {
}
case '+': {
char subsys[NAME_MAX+1]; /* NAME_MAX does not include the trailing NUL. */
const char *sysname;
const char *subsys, *sep;
sysname = strchr(id + 1, ':');
if (!sysname)
sep = strchr(id + 1, ':');
if (!sep || sep - id - 1 > NAME_MAX)
return -EINVAL;
(void) strnscpy(subsys, sizeof(subsys), id + 1, sysname - id - 1);
sysname++;
subsys = memdupa_suffix0(id + 1, sep - id - 1);
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
return sd_device_new_from_subsystem_sysname(ret, subsys, sep + 1);
}
default:

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.