summaryrefslogtreecommitdiff
path: root/graphics/librsvg/patches/patch-CVE-2013-1881
blob: 84a5fb434037ef2c845034f341364191fb8c0a4b (plain)
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
$NetBSD: patch-CVE-2013-1881,v 1.1.2.2 2013/10/09 18:44:39 tron Exp $

from https://git.gnome.org/browse/librsvg/patch/?id=f01aded72c38f0e18bc7ff67dee800e380251c8e

From f01aded72c38f0e18bc7ff67dee800e380251c8e Mon Sep 17 00:00:00 2001
From: Christian Persch <chpe@gnome.org>
Date: Mon, 11 Feb 2013 21:36:58 +0000
Subject: io: Implement strict load policy

Allow any file to load from data:, and any resource to load from other
resources. Only allow file: to load other file: URIs from below the path
of the base file. Any other loads are denied.

Bug #691708.
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 1f88479..9d7c1ea 100644
--- rsvg-base.c.orig	2013-10-03 07:33:50.579625000 -0500
+++ rsvg-base.c	2013-10-03 07:35:26.518496200 -0500
@@ -25,6 +25,7 @@
 */
 
 #include "config.h"
+#define _GNU_SOURCE 1
 
 #include "rsvg.h"
 #include "rsvg-private.h"
@@ -1001,6 +1002,7 @@
 rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri)
 {
     gchar *uri;
+    GFile *file;
 
     g_return_if_fail (handle != NULL);
 
@@ -1012,11 +1014,10 @@
     else
         uri = rsvg_get_base_uri_from_filename (base_uri);
 
-    if (uri) {
-        if (handle->priv->base_uri)
-            g_free (handle->priv->base_uri);
-        handle->priv->base_uri = uri;
-    }
+    file = g_file_new_for_uri (uri ? uri : "data:");
+    rsvg_handle_set_base_gfile (handle, file);
+    g_object_unref (file);
+    g_free (uri);
 }
 
 /**
@@ -2146,12 +2147,79 @@
                          const char *uri,
                          GError **error)
 {
-    RsvgLoadPolicy policy = handle->priv->load_policy;
+    RsvgHandlePrivate *priv = handle->priv;
+    GFile *base;
+    char *path, *dir;
+    char *scheme = NULL, *cpath = NULL, *cdir = NULL;
+    char cpath_buffer[PATH_MAX], cdir_buffer[PATH_MAX];
 
-    if (policy == RSVG_LOAD_POLICY_ALL_PERMISSIVE)
-        return TRUE;
+    g_assert (handle->priv->load_policy == RSVG_LOAD_POLICY_STRICT);
+
+    scheme = g_uri_parse_scheme (uri);
+
+    /* Not a valid URI */
+    if (scheme == NULL)
+        goto deny;
+
+    /* Allow loads of data: from any location */
+    if (g_str_equal (scheme, "data"))
+        goto allow;
+
+    /* No base to compare to? */
+    if (priv->base_gfile == NULL)
+        goto deny;
+
+    /* Deny loads from differing URI schemes */
+    if (!g_file_has_uri_scheme (priv->base_gfile, scheme))
+        goto deny;
+
+    /* resource: is allowed to load anything from other resources */
+    if (g_str_equal (scheme, "resource"))
+        goto allow;
 
+    /* Non-file: isn't allowed to load anything */
+    if (!g_str_equal (scheme, "file"))
+        goto deny;
+
+    base = g_file_get_parent (priv->base_gfile);
+    if (base == NULL)
+        goto deny;
+
+    dir = g_file_get_path (base);
+    g_object_unref (base);
+
+    cdir = realpath (dir,cdir_buffer);
+    g_free (dir);
+    if (cdir == NULL)
+        goto deny;
+
+    path = g_filename_from_uri (uri, NULL, NULL);
+    if (path == NULL)
+        goto deny;
+
+    cpath = realpath (path, cpath_buffer);
+    g_free (path);
+
+    if (cpath == NULL)
+        goto deny;
+
+    /* Now check that @cpath is below @cdir */
+    if (!g_str_has_prefix (cpath, cdir) ||
+        cpath[strlen (cdir)] != G_DIR_SEPARATOR)
+        goto deny;
+
+    /* Allow load! */
+
+ allow:
+    g_free (scheme);
     return TRUE;
+
+ deny:
+    g_free (scheme);
+
+    g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
+                 "File may not link to URI \"%s\"", uri);
+    return FALSE;
 }
 
 guint8* 
diff --git a/rsvg-io.c b/rsvg-io.c
index 3d6c8b5..818d2ec 100644
--- rsvg-io.c
+++ rsvg-io.c
@@ -79,7 +79,7 @@ rsvg_acquire_data_data (const char *uri,
     gboolean base64 = FALSE;
 
     g_assert (out_len != NULL);
-    g_assert (g_str_has_prefix (uri, "data:"));
+    g_assert (strncmp (uri, "data:", 5) == 0);
 
     mime_type = NULL;
     start = uri + 5;
diff --git a/rsvg-private.h b/rsvg-private.h
index 25283d4..1961eaf 100644
--- rsvg-private.h
+++ rsvg-private.h
@@ -123,10 +123,10 @@ struct RsvgSaxHandler {
 };
 
 typedef enum {
-    RSVG_LOAD_POLICY_ALL_PERMISSIVE
+    RSVG_LOAD_POLICY_STRICT
 } RsvgLoadPolicy;
 
-#define RSVG_LOAD_POLICY_DEFAULT (RSVG_LOAD_POLICY_ALL_PERMISSIVE)
+#define RSVG_LOAD_POLICY_DEFAULT (RSVG_LOAD_POLICY_STRICT)
 
 struct RsvgHandlePrivate {
     RsvgHandleFlags flags;
--
cgit v0.9.2