autofs-5.1.7 - add some buffer length checks to master map parser From: Ian Kent Add some checks for buffer overflow to the master map parser. Signed-off-by: Ian Kent --- CHANGELOG | 1 + daemon/master_parse.y | 38 +++++++++++++++----------- daemon/master_tok.l | 73 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 88 insertions(+), 24 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index be0b9d85..ded0f00f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -85,6 +85,7 @@ - fix incorrect print format specifiers in get_pkt(). - add mapent path length check in handle_packet_expire_direct(). - add copy length check in umount_autofs_indirect(). +- add some buffer length checks to master map parser. 25/01/2021 autofs-5.1.7 - make bind mounts propagation slave by default. diff --git a/daemon/master_parse.y b/daemon/master_parse.y index 7480c36a..2d78f082 100644 --- a/daemon/master_parse.y +++ b/daemon/master_parse.y @@ -29,6 +29,7 @@ #include "master.h" #define MAX_ERR_LEN 512 +#define STRTYPE_LEN 2048 extern struct master *master_list; @@ -79,6 +80,7 @@ static int local_argc; static unsigned int propagation; static char errstr[MAX_ERR_LEN]; +static int errlen; static unsigned int verbose; static unsigned int debug; @@ -521,10 +523,11 @@ dnattrs: DNATTR EQUAL DNNAME strcasecmp($1, "ou") && strcasecmp($1, "automountMapName") && strcasecmp($1, "nisMapName")) { - strcpy(errstr, $1); - strcat(errstr, "="); - strcat(errstr, $3); - master_notify(errstr); + errlen = snprintf(errstr, MAX_ERR_LEN, "%s=%s", $1, $3); + if (errlen < MAX_ERR_LEN) + master_notify(errstr); + else + master_notify("error string too long"); YYABORT; } strcpy($$, $1); @@ -537,10 +540,11 @@ dnattrs: DNATTR EQUAL DNNAME strcasecmp($1, "ou") && strcasecmp($1, "automountMapName") && strcasecmp($1, "nisMapName")) { - strcpy(errstr, $1); - strcat(errstr, "="); - strcat(errstr, $3); - master_notify(errstr); + errlen = snprintf(errstr, MAX_ERR_LEN, "%s=%s", $1, $3); + if (errlen < MAX_ERR_LEN) + master_notify(errstr); + else + master_notify("error string too long"); YYABORT; } strcpy($$, $1); @@ -565,10 +569,11 @@ dnattr: DNATTR EQUAL DNNAME { if (!strcasecmp($1, "automountMapName") || !strcasecmp($1, "nisMapName")) { - strcpy(errstr, $1); - strcat(errstr, "="); - strcat(errstr, $3); - master_notify(errstr); + errlen = snprintf(errstr, MAX_ERR_LEN, "%s=%s", $1, $3); + if (errlen < MAX_ERR_LEN) + master_notify(errstr); + else + master_notify("error string too long"); YYABORT; } strcpy($$, $1); @@ -579,10 +584,11 @@ dnattr: DNATTR EQUAL DNNAME { if (!strcasecmp($1, "automountMapName") || !strcasecmp($1, "nisMapName")) { - strcpy(errstr, $1); - strcat(errstr, "="); - strcat(errstr, $3); - master_notify(errstr); + errlen = snprintf(errstr, MAX_ERR_LEN, "%s=%s", $1, $3); + if (errlen < MAX_ERR_LEN) + master_notify(errstr); + else + master_notify("error string too long"); YYABORT; } strcpy($$, $1); diff --git a/daemon/master_tok.l b/daemon/master_tok.l index 87a6b958..e2d15bce 100644 --- a/daemon/master_tok.l +++ b/daemon/master_tok.l @@ -23,6 +23,7 @@ #endif /* ECHO */ static void master_echo(void); /* forward definition */ #define ECHO master_echo() +static void master_error(char *s); #include #include @@ -80,6 +81,8 @@ char *bptr; char *optr = buff; unsigned int tlen; +#define STRTYPE_LEN 2048 + %} %option nounput @@ -217,7 +220,13 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) bptr += tlen; yyless(tlen); } else { - strcpy(master_lval.strtype, master_text); + if (tlen <= STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("MULTITYPE: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return(MULTITYPE); } } @@ -239,7 +248,13 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) bptr += tlen; yyless(tlen); } else { - strcpy(master_lval.strtype, master_text); + if (tlen <= STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("MAPTYPE: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return(MAPTYPE); } } @@ -327,12 +342,24 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) {OPTWS}\\\n{OPTWS} {} {DNSERVERSTR} { - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("DNSERVER: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return DNSERVER; } {DNATTRSTR}/"=" { - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("DNATTR: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return DNATTR; } @@ -341,12 +368,24 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) } {DNNAMESTR1}/","{DNATTRSTR}"=" { - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("DNNAME: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return DNNAME; } {DNNAMESTR2} { - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("DNNAME: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return DNNAME; } @@ -357,7 +396,13 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) {WS}"=" | "="{WS} { BEGIN(INITIAL); - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("SPACE: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return SPACE; } @@ -419,7 +464,13 @@ MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS}) } {OPTIONSTR} { - strcpy(master_lval.strtype, master_text); + if (master_leng < STRTYPE_LEN) + strcpy(master_lval.strtype, master_text); + else { + master_error("OPTION: value too large, truncated"); + strncpy(master_lval.strtype, master_text, STRTYPE_LEN - 2); + master_lval.strtype[STRTYPE_LEN - 1] = 0; + } return(OPTION); } @@ -459,6 +510,12 @@ static void master_echo(void) return; } +static void master_error(char *s) +{ + logmsg("%s"); + return; +} + #ifdef FLEX_SCANNER void master_set_scan_buffer(const char *buffer)