Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
c6bb30d525
!57 [sync] PR-53: fix CVE-2023-38633
From: @openeuler-sync-bot 
Reviewed-by: @t_feng 
Signed-off-by: @t_feng
2023-08-31 11:46:19 +00:00
zhangpan
08cfc0bca3 fix CVE-2023-38633
(cherry picked from commit 4d55b716d10a54034e0f41a3c443b2998113535b)
2023-08-31 14:13:33 +08:00
openeuler-ci-bot
53ae1c74ab !27 update to 2.50.5,delete libcroco dependency
From: @shirely16
Reviewed-by: @yanan-rock
Signed-off-by: @yanan-rock
2021-05-31 20:43:44 +08:00
shirely16
c6d8b9d352 update to 2.50.5,delete libcroco dependency 2021-05-31 18:44:56 +08:00
openeuler-ci-bot
9aa1653d14 !22 eliminate difference
From: @zzm_567
Reviewed-by: @dwl301
Signed-off-by: @dwl301
2021-05-24 10:34:50 +08:00
zhanzhimin
c3d5e03847 eliminate-difference 2021-04-19 14:39:31 +08:00
openeuler-ci-bot
13afc7c72b !6 Version upgrade to 2.46.4
From: @yangl777
Reviewed-by: @orange-snn
Signed-off-by: @orange-snn
2020-10-15 19:02:25 +08:00
s17723959267
5e6af579d2 version upgrade 2020-10-15 17:56:17 +08:00
openeuler-ci-bot
409945706f !2 librsvg2: update to 2.44.15
Merge pull request !2 from orange-snn/master
2020-01-16 15:06:12 +08:00
songnannan
6042d32df4 update to 2.44.15 2020-01-16 14:53:27 +08:00
4 changed files with 475 additions and 17 deletions

View File

@ -0,0 +1,417 @@
From d1f066bf2198bd46c5ba80cb5123b768ec16e37d Mon Sep 17 00:00:00 2001
From: Federico Mena Quintero <federico@gnome.org>
Date: Thu, 20 Jul 2023 11:12:53 -0600
Subject: [PATCH] (#996): Fix arbitrary file read when href has special
characters
In UrlResolver::resolve_href() we now explicitly disallow URLs that
have a query string ("?") or a fragment identifier ("#").
We also explicitly check for a base URL and not resolving to a path,
for example, "file:///base/foo.svg" + "." would resolve to
"file:///base/" - this is technically correct, but we don't want to
resolve to directories.
Also, we pass a canonicalized path name as a URL upstream, so that
g_file_new_from_url() will consume it later, instead of passing the
original and potentially malicious URL.
Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/996
Reference:https://gitlab.gnome.org/GNOME/librsvg/-/commit/d1f066bf2198bd46c5ba80cb5123b768ec16e37d
Conflict:NA
---
librsvg/rsvg-handle.c | 6 +-
rsvg_internals/src/allowed_url.rs | 229 +++++++++++++-----
.../src/filters/component_transfer.rs | 2 +-
tests/Makefile.am | 1 +
tests/fixtures/loading/bar.svg | 1 +
tests/fixtures/loading/foo.svg | 1 +
tests/fixtures/loading/subdir/baz.svg | 1 +
7 files changed, 180 insertions(+), 61 deletions(-)
create mode 100644 tests/fixtures/loading/bar.svg
create mode 100644 tests/fixtures/loading/foo.svg
create mode 100644 tests/fixtures/loading/subdir/baz.svg
diff --git a/librsvg/rsvg-handle.c b/librsvg/rsvg-handle.c
index 95364db34..f49e4d30e 100644
--- a/librsvg/rsvg-handle.c
+++ b/librsvg/rsvg-handle.c
@@ -78,7 +78,11 @@
* </listitem>
*
* <listitem>
- * All other URL schemes in references require a base URL. For
+ * URLs with queries ("?") or fragment identifiers ("#") are not allowed.
+ * </listitem>
+ *
+ * <listitem>
+ * All other URL schemes other than data: in references require a base URL. For
* example, this means that if you load an SVG with
* rsvg_handle_new_from_data() without calling rsvg_handle_set_base_uri(),
* then any referenced files will not be allowed (e.g. raster images to be
diff --git a/rsvg_internals/src/allowed_url.rs b/rsvg_internals/src/allowed_url.rs
index 3a99e00b8..ffa9a2315 100644
--- a/rsvg_internals/src/allowed_url.rs
+++ b/rsvg_internals/src/allowed_url.rs
@@ -2,9 +2,7 @@
use std::error;
use std::fmt;
-use std::io;
use std::ops::Deref;
-use std::path::{Path, PathBuf};
use url::Url;
use crate::error::HrefError;
@@ -37,6 +35,12 @@ pub enum AllowedUrlError {
/// or in one directory below the base file.
NotSiblingOrChildOfBaseFile,
+ /// Loaded file:// URLs cannot have a query part, e.g. `file:///foo?blah`
+ NoQueriesAllowed,
+
+ /// URLs may not have fragment identifiers at this stage
+ NoFragmentIdentifierAllowed,
+
/// Error when obtaining the file path or the base file path
InvalidPath,
@@ -59,6 +63,17 @@ impl AllowedUrl {
return Ok(AllowedUrl(url));
}
+ // Queries are not allowed.
+ if url.query().is_some() {
+ return Err(AllowedUrlError::NoQueriesAllowed);
+ }
+
+ // Fragment identifiers are not allowed. They should have been stripped
+ // upstream, by NodeId.
+ if url.fragment().is_some() {
+ return Err(AllowedUrlError::NoFragmentIdentifierAllowed);
+ }
+
// All other sources require a base url
if base_url.is_none() {
return Err(AllowedUrlError::BaseRequired);
@@ -81,6 +96,26 @@ impl AllowedUrl {
return Err(AllowedUrlError::DisallowedScheme);
}
+ // The rest of this function assumes file: URLs; guard against
+ // incorrect refactoring.
+ assert!(url.scheme() == "file");
+
+ // If we have a base_uri of "file:///foo/bar.svg", and resolve an href of ".",
+ // Url.parse() will give us "file:///foo/". We don't want that, so check
+ // if the last path segment is empty - it will not be empty for a normal file.
+
+ if let Some(segments) = url.path_segments() {
+ if segments
+ .last()
+ .expect("URL path segments always contain at last 1 element")
+ .is_empty()
+ {
+ return Err(AllowedUrlError::NotSiblingOrChildOfBaseFile);
+ }
+ } else {
+ unreachable!("the file: URL cannot have an empty path");
+ }
+
// We have two file: URIs. Now canonicalize them (remove .. and symlinks, etc.)
// and see if the directories match
@@ -98,13 +133,17 @@ impl AllowedUrl {
let base_parent = base_parent.unwrap();
- let url_canon =
- canonicalize(&url_path).map_err(|_| AllowedUrlError::CanonicalizationError)?;
- let parent_canon =
- canonicalize(&base_parent).map_err(|_| AllowedUrlError::CanonicalizationError)?;
-
- if url_canon.starts_with(parent_canon) {
- Ok(AllowedUrl(url))
+ let path_canon = url_path
+ .canonicalize()
+ .map_err(|_| AllowedUrlError::CanonicalizationError)?;
+ let parent_canon = base_parent
+ .canonicalize()
+ .map_err(|_| AllowedUrlError::CanonicalizationError)?;
+
+ if path_canon.starts_with(parent_canon) {
+ // Finally, convert the canonicalized path back to a URL.
+ let path_to_url = Url::from_file_path(path_canon).unwrap();
+ Ok(AllowedUrl(path_to_url))
} else {
Err(AllowedUrlError::NotSiblingOrChildOfBaseFile)
}
@@ -129,32 +168,22 @@ impl error::Error for AllowedUrlError {}
impl fmt::Display for AllowedUrlError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match *self {
- AllowedUrlError::HrefParseError(e) => write!(f, "href parse error: {}", e),
- AllowedUrlError::BaseRequired => write!(f, "base required"),
- AllowedUrlError::DifferentURISchemes => write!(f, "different URI schemes"),
- AllowedUrlError::DisallowedScheme => write!(f, "disallowed scheme"),
- AllowedUrlError::NotSiblingOrChildOfBaseFile => {
- write!(f, "not sibling or child of base file")
- }
- AllowedUrlError::InvalidPath => write!(f, "invalid path"),
- AllowedUrlError::BaseIsRoot => write!(f, "base is root"),
- AllowedUrlError::CanonicalizationError => write!(f, "canonicalization error"),
+ use AllowedUrlError::*;
+ match self {
+ HrefParseError(e) => write!(f, "URL parse error: {}", e),
+ BaseRequired => write!(f, "base required"),
+ DifferentUriSchemes => write!(f, "different URI schemes"),
+ DisallowedScheme => write!(f, "disallowed scheme"),
+ NotSiblingOrChildOfBaseFile => write!(f, "not sibling or child of base file"),
+ NoQueriesAllowed => write!(f, "no queries allowed"),
+ NoFragmentIdentifierAllowed => write!(f, "no fragment identifier allowed"),
+ InvalidPath => write!(f, "invalid path"),
+ BaseIsRoot => write!(f, "base is root"),
+ CanonicalizationError => write!(f, "canonicalization error"),
}
}
}
-// For tests, we don't want to touch the filesystem. In that case,
-// assume that we are being passed canonical file names.
-#[cfg(not(test))]
-fn canonicalize<P: AsRef<Path>>(path: P) -> Result<PathBuf, io::Error> {
- path.as_ref().canonicalize()
-}
-#[cfg(test)]
-fn canonicalize<P: AsRef<Path>>(path: P) -> Result<PathBuf, io::Error> {
- Ok(path.as_ref().to_path_buf())
-}
-
/// Parsed result of an href from an SVG or CSS file
///
/// Sometimes in SVG element references (e.g. the `href` in the `<feImage>` element) we
@@ -234,6 +263,8 @@ impl Href {
mod tests {
use super::*;
+ use std::path::PathBuf;
+
#[test]
fn disallows_relative_file_with_no_base_file() {
assert_eq!(
@@ -284,56 +315,136 @@ mod tests {
);
}
+ fn url_from_test_fixtures(filename_relative_to_librsvg_srcdir: &str) -> Url {
+ let path = PathBuf::from(filename_relative_to_librsvg_srcdir);
+ let absolute = path
+ .canonicalize()
+ .expect("files from test fixtures are supposed to canonicalize");
+ Url::from_file_path(absolute).unwrap()
+ }
+
#[test]
fn allows_relative() {
- assert_eq!(
- AllowedUrl::from_href(
- "foo.svg",
- Some(Url::parse("file:///example/bar.svg").unwrap()).as_ref()
- )
- .unwrap()
- .as_ref(),
- "file:///example/foo.svg",
- );
+ let resolved = AllowedUrl::from_href(
+ "foo.svg",
+ Some(url_from_test_fixtures("../tests/fixtures/loading/bar.svg")).as_ref()
+ ).unwrap();
+
+ let resolved_str = resolved.as_str();
+ assert!(resolved_str.ends_with("/loading/foo.svg"));
}
#[test]
fn allows_sibling() {
- assert_eq!(
- AllowedUrl::from_href(
- "file:///example/foo.svg",
- Some(Url::parse("file:///example/bar.svg").unwrap()).as_ref()
- )
- .unwrap()
- .as_ref(),
- "file:///example/foo.svg",
- );
+ let sibling = url_from_test_fixtures("../tests/fixtures/loading/foo.svg");
+ let resolved = AllowedUrl::from_href(
+ sibling.as_str(),
+ Some(url_from_test_fixtures("../tests/fixtures/loading/bar.svg")).as_ref()
+ ).unwrap();
+
+ let resolved_str = resolved.as_str();
+ assert!(resolved_str.ends_with("/loading/foo.svg"));
}
#[test]
fn allows_child_of_sibling() {
- assert_eq!(
- AllowedUrl::from_href(
- "file:///example/subdir/foo.svg",
- Some(Url::parse("file:///example/bar.svg").unwrap()).as_ref()
- )
- .unwrap()
- .as_ref(),
- "file:///example/subdir/foo.svg",
- );
+ let child_of_sibling = url_from_test_fixtures("../tests/fixtures/loading/subdir/baz.svg");
+ let resolved = AllowedUrl::from_href(
+ child_of_sibling.as_str(),
+ Some(url_from_test_fixtures("../tests/fixtures/loading/bar.svg")).as_ref()
+ ).unwrap();
+
+ let resolved_str = resolved.as_str();
+ assert!(resolved_str.ends_with("/loading/subdir/baz.svg"));
}
+ // Ignore on Windows since we test for /etc/passwd
+ #[cfg(unix)]
#[test]
fn disallows_non_sibling() {
assert_eq!(
AllowedUrl::from_href(
"file:///etc/passwd",
- Some(Url::parse("file:///example/bar.svg").unwrap()).as_ref()
+ Some(url_from_test_fixtures("../tests/fixtures/loading/bar.svg")).as_ref()
),
Err(AllowedUrlError::NotSiblingOrChildOfBaseFile)
);
}
+ #[test]
+ fn disallows_queries() {
+ assert!(matches!(
+ AllowedUrl::from_href(
+ ".?../../../../../../../../../../etc/passwd",
+ Some(url_from_test_fixtures("../tests/fixtures/loading/bar.svg")).as_ref(),
+ ),
+ Err(AllowedUrlError::NoQueriesAllowed)
+ ));
+ }
+
+ #[test]
+ fn disallows_weird_relative_uris() {
+ let base_url = url_from_test_fixtures("../tests/fixtures/loading/bar.svg");
+
+ assert!(
+ AllowedUrl::from_href(
+ ".@../../../../../../../../../../etc/passwd",
+ Some(&base_url),
+ ).is_err()
+ );
+ assert!(
+ AllowedUrl::from_href(
+ ".$../../../../../../../../../../etc/passwd",
+ Some(&base_url),
+ ).is_err()
+ );
+ assert!(
+ AllowedUrl::from_href(
+ ".%../../../../../../../../../../etc/passwd",
+ Some(&base_url),
+ ).is_err()
+ );
+ assert!(
+ AllowedUrl::from_href(
+ ".*../../../../../../../../../../etc/passwd",
+ Some(&base_url),
+ ).is_err()
+ );
+ assert!(
+ AllowedUrl::from_href(
+ "~/../../../../../../../../../../etc/passwd",
+ Some(&base_url),
+ ).is_err()
+ );
+ }
+
+ #[test]
+ fn disallows_dot_sibling() {
+ println!("cwd: {:?}", std::env::current_dir());
+ let base_url = url_from_test_fixtures("../tests/fixtures/loading/bar.svg");
+
+ assert!(matches!(
+ AllowedUrl::from_href(".", Some(&base_url)),
+ Err(AllowedUrlError::NotSiblingOrChildOfBaseFile)
+ ));
+ assert!(matches!(
+ AllowedUrl::from_href(".#../../../../../../../../../../etc/passwd", Some(&base_url)),
+ Err(AllowedUrlError::NoFragmentIdentifierAllowed)
+ ));
+ }
+
+ #[test]
+ fn disallows_fragment() {
+ // AllowedUrl::from_href() explicitly disallows fragment identifiers.
+ // This is because they should have been stripped before calling that function,
+ // by the Iri machinery.
+
+ assert!(matches!(
+ AllowedUrl::from_href("bar.svg#fragment", Some(Url::parse("https://example.com/foo.svg").unwrap()).as_ref()),
+ Err(AllowedUrlError::NoFragmentIdentifierAllowed)
+ ));
+ }
+
#[test]
fn parses_href() {
assert_eq!(
diff --git a/rsvg_internals/src/filters/component_transfer.rs b/rsvg_internals/src/filters/component_transfer.rs
index 235435ffa..6845eac18 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -261,7 +261,7 @@ macro_rules! func_or_default {
}
}
_ => &$func_default,
- };
+ }
};
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 13c2d51f2..b3faf2da5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -82,6 +82,7 @@ dist_installed_test_data = \
$(wildcard $(srcdir)/fixtures/errors/*) \
$(wildcard $(srcdir)/fixtures/infinite-loop/*) \
$(wildcard $(srcdir)/fixtures/loading/*) \
+ $(wildcard $(srcdir)/fixtures/loading/subdir/*) \
$(wildcard $(srcdir)/fixtures/reftests/*.css) \
$(wildcard $(srcdir)/fixtures/reftests/*.svg) \
$(wildcard $(srcdir)/fixtures/reftests/*.png) \
diff --git a/tests/fixtures/loading/bar.svg b/tests/fixtures/loading/bar.svg
new file mode 100644
index 000000000..304670099
--- /dev/null
+++ b/tests/fixtures/loading/bar.svg
@@ -0,0 +1 @@
+<!-- Empty file, used just to test URL validation -->
diff --git a/tests/fixtures/loading/foo.svg b/tests/fixtures/loading/foo.svg
new file mode 100644
index 000000000..304670099
--- /dev/null
+++ b/tests/fixtures/loading/foo.svg
@@ -0,0 +1 @@
+<!-- Empty file, used just to test URL validation -->
diff --git a/tests/fixtures/loading/subdir/baz.svg b/tests/fixtures/loading/subdir/baz.svg
new file mode 100644
index 000000000..304670099
--- /dev/null
+++ b/tests/fixtures/loading/subdir/baz.svg
@@ -0,0 +1 @@
+<!-- Empty file, used just to test URL validation -->
--
GitLab

Binary file not shown.

BIN
librsvg-2.50.5.tar.xz Normal file

Binary file not shown.

View File

@ -1,19 +1,18 @@
Name: librsvg2 Name: librsvg2
Version: 2.44.6 Version: 2.50.5
Release: 3 Release: 2
Summary: An SVG library based on cairo Summary: An SVG library based on cairo
License: LGPLv2+ License: LGPLv2+
URL: https://wiki.gnome.org/Projects/LibRsvg URL: https://wiki.gnome.org/Projects/LibRsvg
Source0: https://download.gnome.org/sources/librsvg/2.44/librsvg-%{version}.tar.xz Source0: https://download.gnome.org/sources/librsvg/2.46/librsvg-%{version}.tar.xz
Patch6000: backport-CVE-2023-38633.patch
BuildRequires: chrpath gcc gobject-introspection-devel cairo-devel libxml2-devel BuildRequires: chrpath gcc gobject-introspection-devel cairo-devel libxml2-devel
BuildRequires: fontconfig-devel gdk-pixbuf2-devel glib2-devel gtk3-devel BuildRequires: fontconfig-devel gdk-pixbuf2-devel glib2-devel pkgconfig(cairo-gobject) >= 1.16.0
BuildRequires: libcroco-devel pango-devel vala cargo rust BuildRequires: pango-devel vala cargo rust
Requires: gdk-pixbuf2 Requires: gdk-pixbuf2 cairo >= 1.16.0
Provides: %{name}-tools = %{version}-%{release}
Obsoletes: %{name}-tools < %{version}-%{release}
%description %description
An SVG library based on cairo. An SVG library based on cairo.
@ -26,28 +25,38 @@ Requires: %{name} = %{version}-%{release}
This package provides the necessary development libraries and include This package provides the necessary development libraries and include
files to allow you to develop with librsvg. files to allow you to develop with librsvg.
%package tools
Summary: Extra tools for librsvg
Requires: %{name} = %{version}-%{release}
%description tools
This package provides extra utilities based on the librsvg library.
%package_help %package_help
%prep %prep
%autosetup -n librsvg-%{version} -p1 %autosetup -n librsvg-%{version} -p1
%build %build
%configure --disable-gtk-doc --enable-introspection --enable-vala autoreconf
%make_build export CFLAGS=$(echo %{?optflags} | sed 's/ -g / /g')
%configure --disable-static --disable-gtk-doc --enable-introspection --enable-vala
make
%install %install
%make_install %make_install
%delete_la %delete_la
%find_lang librsvg
chrpath --delete %{buildroot}%{_bindir}/rsvg-convert chrpath --delete %{buildroot}%{_bindir}/rsvg-convert
chrpath --delete %{buildroot}%{_bindir}/rsvg-view-3
chrpath --delete %{buildroot}%{_libdir}/gdk-pixbuf-2.0/*/loaders/libpixbufloader-svg.so chrpath --delete %{buildroot}%{_libdir}/gdk-pixbuf-2.0/*/loaders/libpixbufloader-svg.so
rm -vrf %{buildroot}%{_datadir}/doc rm -vrf %{buildroot}%{_datadir}/doc
%files %files -f librsvg.lang
%defattr(-,root,root) %defattr(-,root,root)
%license COPYING COPYING.LIB %license COPYING.LIB
%{_bindir}/rsvg-*
%{_libdir}/librsvg-2.so.* %{_libdir}/librsvg-2.so.*
%{_libdir}/gdk-pixbuf-2.0/*/loaders/libpixbufloader-svg.so %{_libdir}/gdk-pixbuf-2.0/*/loaders/libpixbufloader-svg.so
%{_libdir}/girepository-1.0/Rsvg-2.0.typelib %{_libdir}/girepository-1.0/Rsvg-2.0.typelib
@ -56,13 +65,15 @@ rm -vrf %{buildroot}%{_datadir}/doc
%files devel %files devel
%defattr(-,root,root) %defattr(-,root,root)
%{_libdir}/*.so %{_libdir}/*.so
%{_libdir}/*.a
%{_libdir}/gdk-pixbuf-2.0/*/loaders/*.a
%{_libdir}/pkgconfig/*.pc %{_libdir}/pkgconfig/*.pc
%{_includedir}/librsvg-2.0/ %{_includedir}/librsvg-2.0/
%{_datadir}/gir-1.0/Rsvg-2.0.gir %{_datadir}/gir-1.0/Rsvg-2.0.gir
%{_datadir}/vala/vapi/librsvg-2.0.vapi %{_datadir}/vala/vapi/librsvg-2.0.vapi
%files tools
%defattr(-,root,root)
%{_bindir}/rsvg-convert
%files help %files help
%defattr(-,root,root) %defattr(-,root,root)
%doc CONTRIBUTING.md README.md %doc CONTRIBUTING.md README.md
@ -70,6 +81,36 @@ rm -vrf %{buildroot}%{_datadir}/doc
%{_mandir}/man1/*.1* %{_mandir}/man1/*.1*
%changelog %changelog
* Wed Aug 30 2023 zhangpan <zhangpan103@h-partners.com> - 2.50.5-2
- Type: CVE
- ID: CVE-2023-38633
- SUG: NA
- DESC: fix CVE-2023-38633
* Mon May 31 2021 hanhui <hanhui15@huawei.com> - 2.50.5-1
- Type: enhancement
- ID: NA
- SUG: NA
- DESC: update to 2.50.5,delete libcroco dependency
* Mon Apr 19 2021 zhanzhimin<zhanzhimin@huawei.com> - 2.46.4-2
- Type: bugfix
- ID: NA
- SUG: NA
- DESC: eliminate-difference
* Thu Oct 15 2020 yanglu <yanglu60@huawei.com> - 2.46.4-1
- Type:bugfix
- Id:NA
- SUG:NA
- DESC:update to 2.46.4
* Thu Jan 16 2020 openEuler Buildteam <buildteam@openeuler.org> - 2.44.15-1
- Type:bugfix
- Id:NA
- SUG:NA
- DESC:update to 2.44.15
* Wed Dec 25 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.44.6-3 * Wed Dec 25 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.44.6-3
- Type:bugfix - Type:bugfix
- ID:NA - ID:NA