summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/git/files/CVE-2023-23946.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/git/files/CVE-2023-23946.patch')
-rw-r--r--meta/recipes-devtools/git/files/CVE-2023-23946.patch184
1 files changed, 184 insertions, 0 deletions
diff --git a/meta/recipes-devtools/git/files/CVE-2023-23946.patch b/meta/recipes-devtools/git/files/CVE-2023-23946.patch
new file mode 100644
index 0000000000..3629ff57b2
--- /dev/null
+++ b/meta/recipes-devtools/git/files/CVE-2023-23946.patch
@@ -0,0 +1,184 @@
1From fade728df1221598f42d391cf377e9e84a32053f Mon Sep 17 00:00:00 2001
2From: Patrick Steinhardt <ps@pks.im>
3Date: Thu, 2 Feb 2023 11:54:34 +0100
4Subject: [PATCH] apply: fix writing behind newly created symbolic links
5
6When writing files git-apply(1) initially makes sure that none of the
7files it is about to create are behind a symlink:
8
9```
10 $ git init repo
11 Initialized empty Git repository in /tmp/repo/.git/
12 $ cd repo/
13 $ ln -s dir symlink
14 $ git apply - <<EOF
15 diff --git a/symlink/file b/symlink/file
16 new file mode 100644
17 index 0000000..e69de29
18 EOF
19 error: affected file 'symlink/file' is beyond a symbolic link
20```
21
22This safety mechanism is crucial to ensure that we don't write outside
23of the repository's working directory. It can be fooled though when the
24patch that is being applied creates the symbolic link in the first
25place, which can lead to writing files in arbitrary locations.
26
27Fix this by checking whether the path we're about to create is
28beyond a symlink or not. Tightening these checks like this should be
29fine as we already have these precautions in Git as explained
30above. Ideally, we should update the check we do up-front before
31starting to reflect the computed changes to the working tree so that
32we catch this case as well, but as part of embargoed security work,
33adding an equivalent check just before we try to write out a file
34should serve us well as a reasonable first step.
35
36Digging back into history shows that this vulnerability has existed
37since at least Git v2.9.0. As Git v2.8.0 and older don't build on my
38system anymore I cannot tell whether older versions are affected, as
39well.
40
41Reported-by: Joern Schneeweisz <jschneeweisz@gitlab.com>
42Signed-off-by: Patrick Steinhardt <ps@pks.im>
43Signed-off-by: Junio C Hamano <gitster@pobox.com>
44
45Upstream-Status: Backport
46[https://github.com/git/git/commit/fade728df1221598f42d391cf377e9e84a32053f]
47CVE: CVE-2023-23946
48Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
49---
50 apply.c | 27 ++++++++++++++
51 t/t4115-apply-symlink.sh | 81 ++++++++++++++++++++++++++++++++++++++++
52 2 files changed, 108 insertions(+)
53
54diff --git a/apply.c b/apply.c
55index f8a046a..4f303bf 100644
56--- a/apply.c
57+++ b/apply.c
58@@ -4373,6 +4373,33 @@ static int create_one_file(struct apply_state *state,
59 if (state->cached)
60 return 0;
61
62+ /*
63+ * We already try to detect whether files are beyond a symlink in our
64+ * up-front checks. But in the case where symlinks are created by any
65+ * of the intermediate hunks it can happen that our up-front checks
66+ * didn't yet see the symlink, but at the point of arriving here there
67+ * in fact is one. We thus repeat the check for symlinks here.
68+ *
69+ * Note that this does not make the up-front check obsolete as the
70+ * failure mode is different:
71+ *
72+ * - The up-front checks cause us to abort before we have written
73+ * anything into the working directory. So when we exit this way the
74+ * working directory remains clean.
75+ *
76+ * - The checks here happen in the middle of the action where we have
77+ * already started to apply the patch. The end result will be a dirty
78+ * working directory.
79+ *
80+ * Ideally, we should update the up-front checks to catch what would
81+ * happen when we apply the patch before we damage the working tree.
82+ * We have all the information necessary to do so. But for now, as a
83+ * part of embargoed security work, having this check would serve as a
84+ * reasonable first step.
85+ */
86+ if (path_is_beyond_symlink(state, path))
87+ return error(_("affected file '%s' is beyond a symbolic link"), path);
88+
89 res = try_create_file(state, path, mode, buf, size);
90 if (res < 0)
91 return -1;
92diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
93index 872fcda..1acb7b2 100755
94--- a/t/t4115-apply-symlink.sh
95+++ b/t/t4115-apply-symlink.sh
96@@ -44,4 +44,85 @@ test_expect_success 'apply --index symlink patch' '
97
98 '
99
100+test_expect_success 'symlink setup' '
101+ ln -s .git symlink &&
102+ git add symlink &&
103+ git commit -m "add symlink"
104+'
105+
106+test_expect_success SYMLINKS 'symlink escape when creating new files' '
107+ test_when_finished "git reset --hard && git clean -dfx" &&
108+
109+ cat >patch <<-EOF &&
110+ diff --git a/symlink b/renamed-symlink
111+ similarity index 100%
112+ rename from symlink
113+ rename to renamed-symlink
114+ --
115+ diff --git /dev/null b/renamed-symlink/create-me
116+ new file mode 100644
117+ index 0000000..039727e
118+ --- /dev/null
119+ +++ b/renamed-symlink/create-me
120+ @@ -0,0 +1,1 @@
121+ +busted
122+ EOF
123+
124+ test_must_fail git apply patch 2>stderr &&
125+ cat >expected_stderr <<-EOF &&
126+ error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link
127+ EOF
128+ test_cmp expected_stderr stderr &&
129+ ! test_path_exists .git/create-me
130+'
131+
132+test_expect_success SYMLINKS 'symlink escape when modifying file' '
133+ test_when_finished "git reset --hard && git clean -dfx" &&
134+ touch .git/modify-me &&
135+
136+ cat >patch <<-EOF &&
137+ diff --git a/symlink b/renamed-symlink
138+ similarity index 100%
139+ rename from symlink
140+ rename to renamed-symlink
141+ --
142+ diff --git a/renamed-symlink/modify-me b/renamed-symlink/modify-me
143+ index 1111111..2222222 100644
144+ --- a/renamed-symlink/modify-me
145+ +++ b/renamed-symlink/modify-me
146+ @@ -0,0 +1,1 @@
147+ +busted
148+ EOF
149+
150+ test_must_fail git apply patch 2>stderr &&
151+ cat >expected_stderr <<-EOF &&
152+ error: renamed-symlink/modify-me: No such file or directory
153+ EOF
154+ test_cmp expected_stderr stderr &&
155+ test_must_be_empty .git/modify-me
156+'
157+
158+test_expect_success SYMLINKS 'symlink escape when deleting file' '
159+ test_when_finished "git reset --hard && git clean -dfx && rm .git/delete-me" &&
160+ touch .git/delete-me &&
161+
162+ cat >patch <<-EOF &&
163+ diff --git a/symlink b/renamed-symlink
164+ similarity index 100%
165+ rename from symlink
166+ rename to renamed-symlink
167+ --
168+ diff --git a/renamed-symlink/delete-me b/renamed-symlink/delete-me
169+ deleted file mode 100644
170+ index 1111111..0000000 100644
171+ EOF
172+
173+ test_must_fail git apply patch 2>stderr &&
174+ cat >expected_stderr <<-EOF &&
175+ error: renamed-symlink/delete-me: No such file or directory
176+ EOF
177+ test_cmp expected_stderr stderr &&
178+ test_path_is_file .git/delete-me
179+'
180+
181 test_done
182--
1832.25.1
184