summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Mitchell <jumitche@rehat.com>2017-06-01 11:20:36 -0400
committerSteve Dickson <steved@redhat.com>2017-06-06 10:29:24 -0400
commit1c2c18806800198bf3f2336939a5b5c348f46b92 (patch)
tree2179dc7d05300a13281aee90c8a05fe888a3ae74
parentbc89ecb3146539e8a0afbd24ea6529aa8c4df175 (diff)
downloadnfs-utils-1c2c18806800198bf3f2336939a5b5c348f46b92.tar.gz
nfs-utils-1c2c18806800198bf3f2336939a5b5c348f46b92.tar.xz
nfs-utils-1c2c18806800198bf3f2336939a5b5c348f46b92.zip
nfs.conf: Removed buffer overruns
Remove the line length parameter and associated code which led to buffer overruns in the line parsing code. Also drops the undocumented 'include' directive. Signed-off-by: Justin Mitchell <jumitche@rehat.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--support/nfs/conffile.c201
1 files changed, 117 insertions, 84 deletions
diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c
index 6cbc009..b209c17 100644
--- a/support/nfs/conffile.c
+++ b/support/nfs/conffile.c
@@ -214,15 +214,10 @@ conf_set_now(char *section, char *arg, char *tag,
* headers and feed tag-value pairs into our configuration database.
*/
static void
-conf_parse_line(int trans, char *line, size_t sz, char **section, char **subsection)
+conf_parse_line(int trans, char *line, int lineno, char **section, char **subsection)
{
char *val, *ptr;
- size_t i;
- size_t j;
- static int ln = 0;
- /* Lines starting with '#' or ';' are comments. */
- ln++;
/* Ignore blank lines */
if (*line == '\0')
return;
@@ -231,113 +226,149 @@ conf_parse_line(int trans, char *line, size_t sz, char **section, char **subsect
while (isblank(*line))
line++;
+ /* Lines starting with '#' or ';' are comments. */
if (*line == '#' || *line == ';')
return;
/* '[section]' parsing... */
if (*line == '[') {
line++;
+
+ if (*section) {
+ free(*section);
+ *section = NULL;
+ }
+ if (*subsection) {
+ free(*subsection);
+ *subsection = NULL;
+ }
+
/* Strip off any blanks after '[' */
while (isblank(*line))
line++;
- for (i = 0; i < sz; i++) {
- if (line[i] == ']') {
- break;
- }
- }
- if (*section)
- free(*section);
- if (i == sz) {
+
+ /* find the closing ] */
+ ptr = strchr(line, ']');
+ if (ptr == NULL) {
xlog_warn("config file error: line %d: "
- "non-matched ']', ignoring until next section", ln);
- *section = NULL;
+ "non-matched ']', ignoring until next section", lineno);
return;
}
+
+ /* just ignore everything after the closing ] */
+ *(ptr--) = '\0';
+
/* Strip off any blanks before ']' */
- val = line;
- j=0;
- while (*val && !isblank(*val))
- val++, j++;
- if (*val)
- i = j;
- *section = malloc(i+1);
+ while (ptr >= line && isblank(*ptr))
+ *(ptr--)='\0';
+
+ /* look for an arg to split from the section name */
+ val = strchr(line, '"');
+ if (val != NULL) {
+ ptr = val - 1;
+ *(val++) = '\0';
+
+ /* trim away any whitespace before the " */
+ while (ptr > line && isblank(*ptr))
+ *(ptr--)='\0';
+ }
+
+ /* copy the section name */
+ *section = strdup(line);
if (!*section) {
- xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
- (unsigned long)i);
+ xlog_warn("conf_parse_line: %d: malloc failed", lineno);
return;
}
- strncpy(*section, line, i);
- (*section)[i] = '\0';
- if (*subsection) {
- free(*subsection);
- *subsection = NULL;
- }
+ /* there is no arg, we are done */
+ if (val == NULL) return;
+ /* check for the closing " */
ptr = strchr(val, '"');
- if (ptr == NULL)
- return;
- line = ++ptr;
- while (*ptr && *ptr != '"' && *ptr != ']')
- ptr++;
- if (*ptr == '\0' || *ptr == ']') {
+ if (ptr == NULL) {
xlog_warn("config file error: line %d: "
- "non-matched '\"', ignoring until next section", ln);
- } else {
- *ptr = '\0';
- *subsection = strdup(line);
- if (!*subsection)
- xlog_warn("conf_parse_line: %d: malloc arg failed", ln);
+ "non-matched '\"', ignoring until next section", lineno);
+ return;
}
+ *ptr = '\0';
+ *subsection = strdup(val);
+ if (!*subsection)
+ xlog_warn("conf_parse_line: %d: malloc arg failed", lineno);
return;
}
/* Deal with assignments. */
- for (i = 0; i < sz; i++) {
- if (line[i] == '=') {
- /* If no section, we are ignoring the lines. */
- if (!*section) {
+ ptr = strchr(line, '=');
+
+ /* not an assignment line */
+ if (ptr == NULL) {
+ /* Other non-empty lines are weird. */
+ if (line[strspn(line, " \t")])
xlog_warn("config file error: line %d: "
- "ignoring line due to no section", ln);
- return;
- }
- line[strcspn (line, " \t=")] = '\0';
- val = line + i + 1 + strspn (line + i + 1, " \t");
-
- if (val[0] == '"') {
- val ++;
- j = strcspn(val, "\"");
- val[j] = 0;
- } else if (val[0] == '\'') {
- val ++;
- j = strcspn(val, "'");
- val[j] = 0;
- } else {
- /* Skip trailing spaces and comments */
- for (j = 0; val[j]; j++) {
- if ((val[j] == '#' || val[j] == ';')
- && (j == 0 || isspace(val[j-1]))) {
- val[j] = '\0';
- break;
- }
- }
- while (j && isspace(val[j-1]))
- val[--j] = '\0';
- }
- if (strcasecmp(line, "include") == 0)
- conf_load(trans, val);
- else
- /* XXX Perhaps should we not ignore errors? */
- conf_set(trans, *section, *subsection, line, val, 0, 0);
+ "line not empty and not an assignment", lineno);
+ return;
+ }
+
+ /* If no section, we are ignoring the line. */
+ if (!*section) {
+ xlog_warn("config file error: line %d: "
+ "ignoring line due to no section", lineno);
+ return;
+ }
+
+ val = ptr + 1;
+ *(ptr--) = '\0';
+
+ /* strip spaces before and after the = */
+ while (ptr >= line && isblank(*ptr))
+ *(ptr--)='\0';
+ while (*val != '\0' && isblank(*val))
+ val++;
+
+ if (*val == '"') {
+ val++;
+ ptr = strchr(val, '"');
+ if (ptr == NULL) {
+ xlog_warn("config file error: line %d: "
+ "unmatched quotes", lineno);
return;
}
+ *ptr = '\0';
+ } else
+ if (*val == '\'') {
+ val++;
+ ptr = strchr(val, '\'');
+ if (ptr == NULL) {
+ xlog_warn("config file error: line %d: "
+ "unmatched quotes", lineno);
+ return;
+ }
+ *ptr = '\0';
+ } else {
+ /* Trim any trailing spaces and comments */
+ if ((ptr=strchr(val, '#'))!=NULL)
+ *ptr = '\0';
+ if ((ptr=strchr(val, ';'))!=NULL)
+ *ptr = '\0';
+
+ ptr = val + strlen(val) - 1;
+ while (ptr > val && isspace(*ptr))
+ *(ptr--) = '\0';
}
- /* Other non-empty lines are weird. */
- i = strspn(line, " \t");
- if (line[i])
- xlog_warn("config file error: line %d:", ln);
- return;
+ if (*line == '\0') {
+ xlog_warn("config file error: line %d: "
+ "missing tag in assignment", lineno);
+ return;
+ }
+ if (*val == '\0') {
+ xlog_warn("config file error: line %d: "
+ "missing value in assignment", lineno);
+ return;
+ }
+
+ /* XXX Perhaps should we not ignore errors? */
+ conf_set(trans, *section, *subsection, line, val, 0, 0);
}
/* Parse the mapped configuration file. */
@@ -349,6 +380,7 @@ conf_parse(int trans, char *buf, size_t sz)
char *line;
char *section = NULL;
char *subsection = NULL;
+ int lineno = 0;
line = cp;
while (cp < bufend) {
@@ -358,7 +390,8 @@ conf_parse(int trans, char *buf, size_t sz)
*(cp - 1) = *cp = ' ';
else {
*cp = '\0';
- conf_parse_line(trans, line, cp - line, &section, &subsection);
+ lineno++;
+ conf_parse_line(trans, line, lineno, &section, &subsection);
line = cp + 1;
}
}