aboutsummaryrefslogtreecommitdiff
path: root/archivers/ha/files/patch-CVE-2015-1198
blob: 2e3a3898573a24546f54b9a866a7ccaf63bd03ac (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
- Fix unchecked path extraction problem (CAN-2015-1198)

Index: nix/sanitize.c
@@ -0,0 +1,79 @@
+/*
+ * Path sanitation code by Ludwig Nussel <ludwig.nussel@suse.de>. Public Domain.
+ */
+
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+#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 <stdlib.h>
 #include <ctype.h>
 #include <stdio.h>
+#include <string.h>
 #include <sys/types.h>
 #include <utime.h>
 #include <time.h>
@@ -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;
 }