From f6f04d1a3a536e1c4815f59b224964498de03ae3 Mon Sep 17 00:00:00 2001 From: tsoome Date: Wed, 20 Feb 2019 21:07:09 +0000 Subject: [PATCH] loader: really fix cd9660 dirmatch The cd9660_open() does pass whole path to dirmatch() and we need to compare only the current path component, not full path. Additinally, skip over duplicate / (if any) and check if the last component in the path was meant to be directory (having trailing /). If it is in fact a file, error out. --- stand/libsa/cd9660.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/stand/libsa/cd9660.c b/stand/libsa/cd9660.c index 60b830de483b..aa87466dc591 100644 --- a/stand/libsa/cd9660.c +++ b/stand/libsa/cd9660.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); */ #include #include +#include #include #include #include @@ -227,8 +228,8 @@ static int dirmatch(struct open_file *f, const char *path, struct iso_directory_record *dp, int use_rrip, int lenskip) { - size_t len; - char *cp; + size_t len, plen; + char *cp, *sep; int i, icase; if (use_rrip) @@ -242,7 +243,14 @@ dirmatch(struct open_file *f, const char *path, struct iso_directory_record *dp, } else icase = 0; - if (strlen(path) != len) + sep = strchr(path, '/'); + if (sep != NULL) { + plen = sep - path; + } else { + plen = strlen(path); + } + + if (plen != len) return (0); for (i = len; --i >= 0; path++, cp++) { @@ -283,6 +291,7 @@ cd9660_open(const char *path, struct open_file *f) struct iso_directory_record rec; struct iso_directory_record *dp = NULL; int rc, first, use_rrip, lenskip; + bool isdir = false; /* First find the volume descriptor */ buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); @@ -372,7 +381,24 @@ cd9660_open(const char *path, struct open_file *f) rec = *dp; while (*path && *path != '/') /* look for next component */ path++; - if (*path) path++; /* skip '/' */ + + if (*path) /* this component was directory */ + isdir = true; + + while (*path == '/') + path++; /* skip '/' */ + + if (*path) /* We do have next component. */ + isdir = false; + } + + /* + * if the path had trailing / but the path does point to file, + * report the error ENOTDIR. + */ + if (isdir == true && (isonum_711(rec.flags) & 2) == 0) { + rc = ENOTDIR; + goto out; } /* allocate file system specific data structure */