summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2014-09-22 15:20:01 +0200
committerJo-Philipp Wich <jow@openwrt.org>2014-09-22 15:21:06 +0200
commit4bdc9a6325c8113ca11d107ef875371ad8363ade (patch)
tree2f989902ee3c4e5a8128eda9fa1a58761e511477
parente57bf6d8bfa465a50eea2c30269acdfe751a46fd (diff)
downloaduhttpd-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.c35
-rw-r--r--uhttpd-utils.h3
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);