diff options
author | Jo-Philipp Wich <jow@openwrt.org> | 2014-09-22 15:20:01 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jow@openwrt.org> | 2014-09-22 15:21:06 +0200 |
commit | 4bdc9a6325c8113ca11d107ef875371ad8363ade (patch) | |
tree | 2f989902ee3c4e5a8128eda9fa1a58761e511477 | |
parent | e57bf6d8bfa465a50eea2c30269acdfe751a46fd (diff) | |
download | uhttpd-4bdc9a6325c8113ca11d107ef875371ad8363ade.tar.gz |
Fix possible buffer overruns in path handling
* Implement safe uh_realpath() wrapper
* Fix possible buffer overrun in canonpath()
* Fix possible buffer overrun in uh_path_lookup()
Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
-rw-r--r-- | uhttpd-utils.c | 35 | ||||
-rw-r--r-- | uhttpd-utils.h | 3 |
2 files changed, 31 insertions, 7 deletions
diff --git a/uhttpd-utils.c b/uhttpd-utils.c index ad8813e..e4ac26c 100644 --- a/uhttpd-utils.c +++ b/uhttpd-utils.c @@ -483,13 +483,12 @@ static char * canonpath(const char *path, char *path_resolved) /* relative -> absolute */ if (*path != '/') { - getcwd(path_copy, PATH_MAX); - strncat(path_copy, "/", PATH_MAX - strlen(path_copy)); - strncat(path_copy, path, PATH_MAX - strlen(path_copy)); + getcwd(path_copy, sizeof(path_copy)); + snprintf(path_copy, sizeof(path_copy) - strlen(path_copy), "/%s", path); } else { - strncpy(path_copy, path, PATH_MAX); + strncpy(path_copy, path, sizeof(path_copy) - 1); } /* normalize */ @@ -545,6 +544,28 @@ static char * canonpath(const char *path, char *path_resolved) return NULL; } +char * uh_realpath(const char *path, char *resolved_path) +{ + char *res = realpath(path, NULL); + + if (res && strlen(res) >= PATH_MAX) + { + free(res); + errno = ENAMETOOLONG; + + return NULL; + } + else if (res) + { + strncpy(resolved_path, res, PATH_MAX - 1); + free(res); + + return resolved_path; + } + + return NULL; +} + struct index_file *uh_index_files = NULL; @@ -632,7 +653,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) memset(path_info, 0, sizeof(path_info)); memcpy(path_info, buffer, min(i + 1, sizeof(path_info) - 1)); - if (no_sym ? realpath(path_info, path_phys) + if (no_sym ? uh_realpath(path_info, path_phys) : canonpath(path_info, path_phys)) { memset(path_info, 0, sizeof(path_info)); @@ -673,7 +694,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) /* try to locate index file */ memset(buffer, 0, sizeof(buffer)); - memcpy(buffer, path_phys, sizeof(buffer)); + memcpy(buffer, path_phys, sizeof(buffer) - 1); pathptr = &buffer[strlen(buffer)]; /* if requested url resolves to a directory and a trailing slash @@ -696,7 +717,7 @@ struct path_info * uh_path_lookup(struct client *cl, const char *url) { for (idx = uh_index_files; idx; idx = idx->next) { - strncat(buffer, idx->name, sizeof(buffer)); + strncpy(pathptr, idx->name, sizeof(buffer) - (pathptr - buffer) - 1); if (!stat(buffer, &s) && (s.st_mode & S_IFREG)) { diff --git a/uhttpd-utils.h b/uhttpd-utils.h index 2c6785d..d597e49 100644 --- a/uhttpd-utils.h +++ b/uhttpd-utils.h @@ -117,6 +117,9 @@ int uh_auth_check( ); +char * uh_realpath(const char *path, char *resolved_path); + + extern struct index_file *uh_index_files; struct index_file * uh_index_add(const char *filename); |