- Fix unchecked path extraction problem (CAN-2015-1198) Index: nix/sanitize.c @@ -0,0 +1,79 @@ +/* + * Path sanitation code by Ludwig Nussel . Public Domain. + */ + +#include +#include +#include + +#ifndef PATH_CHAR +#define PATH_CHAR '/' +#endif +#ifndef MIN +#define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +/* copy src into dest converting the path to a relative one inside the current + * directory. dest must hold at least len bytes */ +void copy_path_relative(char *dest, char *src, size_t len) +{ + char* o = dest; + char* p = src; + + *o = '\0'; + + while(*p && *p == PATH_CHAR) ++p; + for(; len && *p;) + { + src = p; + p = strchr(src, PATH_CHAR); + if(!p) p = src+strlen(src); + + /* . => skip */ + if(p-src == 1 && *src == '.' ) + { + if(*p) src = ++p; + } + /* .. => pop one */ + else if(p-src == 2 && *src == '.' && src[1] == '.') + { + if(o != dest) + { + char* tmp; + *o = '\0'; + tmp = strrchr(dest, PATH_CHAR); + if(!tmp) + { + len += o-dest; + o = dest; + if(*p) ++p; + } + else + { + len += o-tmp; + o = tmp; + if(*p) ++p; + } + } + else /* nothing to pop */ + if(*p) ++p; + } + else + { + size_t copy; + if(o != dest) + { + --len; + *o++ = PATH_CHAR; + } + copy = MIN(p-src,len); + memcpy(o, src, copy); + len -= copy; + src += copy; + o += copy; + if(*p) ++p; + } + while(*p && *p == PATH_CHAR) ++p; + } + o[len?0:-1] = '\0'; +} Index: nix/machine.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ static Mdhd mdhd; struct stat filestat; +void copy_path_relative(char *dest, char *src, size_t len); + static void sig_handler(int signo) { error(1,ERR_INT,signo); @@ -375,7 +378,7 @@ if (i==0) skipemptypath=1; else skipemptypath=0; if ((hapath=malloc(j+1-i))==NULL) error(1,ERR_MEM,"md_tohapath()"); - strcpy(hapath,mdpath+i); + copy_path_relative(hapath, mdpath+i, sizeof(hapath)); for (i=0;hapath[i];++i) if (hapath[i]=='/') hapath[i]=0xff; return md_strcase(hapath); } @@ -388,8 +391,10 @@ if (mdpath!=NULL) free(mdpath),mdpath=NULL; if ((mdpath=malloc(strlen(hapath)+1))==NULL) error(1,ERR_MEM,"md_tomdpath()"); - strcpy(mdpath,hapath); - for (i=0;mdpath[i];++i) if ((unsigned char)mdpath[i]==0xff) mdpath[i]='/'; + /* Kludge to avoid temp string allocation */ + for (i=0;hapath[i];++i) if (hapath[i]==0xff) hapath[i]='/'; + copy_path_relative(mdpath, hapath, sizeof(mdpath)); + for (i=0;hapath[i];++i) if (hapath[i]=='/') hapath[i]=0xff; return mdpath; }