public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/erlang] f44: Backport fix for CVE-2026-48855
@ 2026-06-13 11:42 Peter Lemenkov
0 siblings, 0 replies; only message in thread
From: Peter Lemenkov @ 2026-06-13 11:42 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/erlang
Branch : f44
Commit : db1473519de186bfe2688dc6196ed989e3660fba
Author : Peter Lemenkov <lemenkov@gmail.com>
Date : 2026-06-13T12:59:00+02:00
Stats : +189/-1 in 2 file(s)
URL : https://src.fedoraproject.org/rpms/erlang/c/db1473519de186bfe2688dc6196ed989e3660fba?branch=f44
Log:
Backport fix for CVE-2026-48855
Signed-off-by: Peter Lemenkov <lemenkov@gmail.com>
---
diff --git a/erlang.spec b/erlang.spec
index 1ffe45c..5fff741 100644
--- a/erlang.spec
+++ b/erlang.spec
@@ -70,7 +70,7 @@
Name: erlang
Version: 26.2.5.21
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: General-purpose programming language and runtime environment
License: Apache-2.0
@@ -108,6 +108,7 @@ Patch6: otp-0006-Add-extra-search-directory.patch
Patch7: otp-0007-Avoid-forking-sed-to-get-basename.patch
Patch8: otp-0008-Load-man-pages-from-system-wide-directory.patch
Patch9: otp-0009-Add-GDB-tools.patch
+Patch10: otp-0010-Fix-absolute-path-leak-from-SSH_FXP_READLINK.patch
# end of autogenerated patch tag list
BuildRequires: gcc
@@ -1956,6 +1957,9 @@ ERL_TOP=${ERL_TOP} make TARGET=${TARGET} release_tests
%changelog
+* Sat Jun 13 2026 Peter Lemenkov <lemenkov@gmail.com> - 26.2.5.21-3
+- Backport fix for CVE-2026-48855
+
* Tue Jun 2 2026 Peter Lemenkov <lemenkov@gmail.com> - 26.2.5.21-2
- Ditch outdated src subpackage
diff --git a/otp-0010-Fix-absolute-path-leak-from-SSH_FXP_READLINK.patch b/otp-0010-Fix-absolute-path-leak-from-SSH_FXP_READLINK.patch
new file mode 100644
index 0000000..7394d52
--- /dev/null
+++ b/otp-0010-Fix-absolute-path-leak-from-SSH_FXP_READLINK.patch
@@ -0,0 +1,184 @@
+From: =?UTF-8?q?Micha=C5=82=20W=C4=85sowski?= <michal@erlang.org>
+Date: Mon, 8 Jun 2026 20:26:37 +0200
+Subject: [PATCH] Fix absolute path leak from SSH_FXP_READLINK
+
+(cherry picked from commit 8f4224a0d2676b0653d2c71a889a956e8c2c62d6)
+
+diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl
+index e0f8ce2a8f..ea29fb7c02 100644
+--- a/lib/ssh/src/ssh_sftpd.erl
++++ b/lib/ssh/src/ssh_sftpd.erl
+@@ -385,8 +385,10 @@ handle_op(?SSH_FXP_READLINK, ReqId, <<?UINT32(PLen), RelPath:PLen/binary>>,
+ {Res, FS1} = FileMod:read_link(AbsPath, FS0),
+ case Res of
+ {ok, NewPath} ->
+- ssh_xfer:xf_send_name(State#state.xf, ReqId, NewPath,
+- #ssh_xfer_attr{type=regular});
++ AbsTarget = filename:absname(NewPath, filename:dirname(AbsPath)),
++ ChrootedPath = chroot_filename(canonicalize_filename(AbsTarget), State),
++ ssh_xfer:xf_send_name(State#state.xf, ReqId, ChrootedPath,
++ #ssh_xfer_attr{type=regular});
+ {error, Error} ->
+ ssh_xfer:xf_send_status(State#state.xf, ReqId,
+ ssh_xfer:encode_erlang_status(Error))
+diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
+index 55c0401427..cb2eee14e7 100644
+--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
++++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
+@@ -35,6 +35,7 @@
+
+ -export([access_outside_root/1,
+ links/1,
++ links_root/1,
+ mk_rm_dir/1,
+ open_close_dir/1,
+ open_close_file/1,
+@@ -97,6 +98,7 @@ all() ->
+ retrieve_attributes,
+ set_attributes,
+ links,
++ links_root,
+ ver3_rename,
+ ver3_open_flags,
+ relpath,
+@@ -190,6 +192,14 @@ init_per_testcase(TestCase, Config) ->
+ SubSystems = [ssh_sftpd:subsystem_spec([{cwd, PrivDir},
+ {sftpd_vsn, 6}])],
+ ssh:daemon(0, [{subsystems, SubSystems}|Options]);
++ links ->
++ SubSystems = [ssh_sftpd:subsystem_spec([{cwd, PrivDir}])],
++ ssh:daemon(0, [{subsystems, SubSystems}|Options]);
++ links_root ->
++ RootDir = filename:join(PrivDir, links_root),
++ ok = file:make_dir(RootDir),
++ SubSystems = [ssh_sftpd:subsystem_spec([{root, RootDir}, {cwd, RootDir}])],
++ ssh:daemon(0, [{subsystems, SubSystems}|Options]);
+ _ ->
+ SubSystems = [ssh_sftpd:subsystem_spec(
+ [{max_handles, ?MAX_HANDLES},
+@@ -530,28 +540,108 @@ real_path(Config) when is_list(Config) ->
+ %%--------------------------------------------------------------------
+ links(Config) when is_list(Config) ->
+ case os:type() of
+- {win32, _} ->
+- {skip, "Links are not fully supported by windows"};
+- _ ->
+- ReqId = 0,
+- {Cm, Channel} = proplists:get_value(sftp, Config),
+- PrivDir = proplists:get_value(priv_dir, Config),
+- FileName = filename:join(PrivDir, "test.txt"),
+- LinkFileName = filename:join(PrivDir, "link_test.txt"),
++ {win32, _} ->
++ {skip, "Links are not fully supported by windows"};
++ _ ->
++ Sftp = proplists:get_value(sftp, Config),
++ PrivDir = string:trim(proplists:get_value(priv_dir, Config), trailing, "/"),
++ LinkPath = filename:join(".", "link"),
+
+- {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId),
+- ?UINT32(?SSH_FX_OK), _/binary>>, _} =
+- create_link(LinkFileName, FileName, Cm, Channel, ReqId),
++ AbsBelowCwd = filename:join(PrivDir, "file"),
++ links_helper(Sftp, PrivDir, 0, LinkPath, AbsBelowCwd, AbsBelowCwd, AbsBelowCwd, AbsBelowCwd),
+
+- NewReqId = 1,
+- {ok, <<?SSH_FXP_NAME, ?UINT32(NewReqId), ?UINT32(_), ?UINT32(Len),
+- Path:Len/binary, _/binary>>, _}
+- = read_link(LinkFileName, Cm, Channel, NewReqId),
++ AbsAtCwd = PrivDir,
++ links_helper(Sftp, PrivDir, 1, LinkPath, AbsAtCwd, AbsAtCwd, AbsAtCwd, AbsAtCwd),
+
++ AbsAboveCwd = filename:join([PrivDir, "..", "file"]),
++ AbsAboveCwdExpected = filename:join(filename:dirname(PrivDir), "file"),
++ links_helper(Sftp, PrivDir, 2, LinkPath, AbsAboveCwd, AbsAboveCwdExpected, AbsAboveCwd, AbsAboveCwdExpected),
+
+- true = binary_to_list(Path) == FileName,
++ RelBelowCwd = filename:join(".", "file"),
++ RelBelowCwdExpected = AbsBelowCwd,
++ links_helper(Sftp, PrivDir, 3, LinkPath, RelBelowCwd, RelBelowCwdExpected, RelBelowCwd, RelBelowCwdExpected),
+
+- ct:log("Path: ~p~n", [binary_to_list(Path)])
++ RelAtCwd = ".",
++ RelAtCwdExpected = AbsAtCwd,
++ links_helper(Sftp, PrivDir, 4, LinkPath, RelAtCwd, RelAtCwdExpected, RelAtCwd, RelAtCwdExpected),
++
++ RelAboveCwd = filename:join("..", "file"),
++ RelAboveCwdExpected = AbsAboveCwdExpected,
++ links_helper(Sftp, PrivDir, 5, LinkPath, RelAboveCwd, RelAboveCwdExpected, RelAboveCwd, RelAboveCwdExpected)
++ end.
++
++%%--------------------------------------------------------------------
++links_root(Config) when is_list(Config) ->
++ case os:type() of
++ {win32, _} ->
++ {skip, "Links are not fully supported by windows"};
++ _ ->
++ Sftp = proplists:get_value(sftp, Config),
++ PrivDir = proplists:get_value(priv_dir, Config),
++ Root = filename:join(PrivDir, links_root),
++ LinkPath = filename:join("/", "link"),
++
++ AbsBelowRoot = filename:join(Root, "file"),
++ AbsBelowRootClient = filename:join("/", "file"),
++ links_helper(Sftp, Root, 0, LinkPath, AbsBelowRoot, AbsBelowRoot, AbsBelowRootClient, AbsBelowRootClient),
++
++ AbsAtRoot = Root,
++ AbsAtRootExpected = AbsAtRoot,
++ links_helper(Sftp, Root, 1, LinkPath, AbsAtRoot, AbsAtRootExpected, "/", "/"),
++
++ AbsAboveRoot = filename:join(PrivDir, "file"),
++ AbsAboveRootExpected = AbsAtRootExpected,
++ AbsAboveRootClient = filename:join("/", ".."),
++ links_helper(Sftp, Root, 2, LinkPath, AbsAboveRoot, AbsAboveRootExpected, AbsAboveRootClient, "/"),
++
++ RelBelowRoot = filename:join(".", "file"),
++ RelBelowRootExpected = filename:join(Root, "file"),
++ RelBelowRootClient = RelBelowRoot,
++ RelBelowRootClientExpected = AbsBelowRootClient,
++ links_helper(Sftp, Root, 3, LinkPath, RelBelowRoot, RelBelowRootExpected, RelBelowRootClient, RelBelowRootClientExpected),
++
++ RelAtRoot = ".",
++ RelAtRootExpected = Root,
++ links_helper(Sftp, Root, 4, LinkPath, RelAtRoot, RelAtRootExpected, ".", "/"),
++
++ RelAboveRoot = "../file",
++ RelAboveRootExpected = Root,
++ RelAboveRootClient = filename:join("..", "file"),
++ links_helper(Sftp, Root, 5, LinkPath, RelAboveRoot, RelAboveRootExpected, RelAboveRootClient, "/")
++ end.
++
++links_helper({Cm, Channel}, Root, ReqId0, LinkPath, RawTarget, RawExpected, ClientTarget, ClientExpected) ->
++ ct:log("RawTarget: ~p, RawExpected: ~p~nClientTarget: ~p, ClientExpected: ~p~n",
++ [RawTarget, RawExpected, ClientTarget, ClientExpected]),
++
++ ReqId1 = ReqId0 * 3,
++ LinkLocation = filename:join(Root, "link"),
++ ok = file:make_symlink(RawTarget, LinkLocation),
++ try
++ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId1), ?UINT32(_),
++ ?UINT32(Len1), ClientActualB1:Len1/binary, _/binary>>, _} =
++ read_link(LinkPath, Cm, Channel, ReqId1),
++ ClientActual1 = binary_to_list(ClientActualB1),
++ ClientExpected = ClientActual1,
++
++ ok = file:delete(LinkLocation),
++
++ ReqId2 = ReqId1 + 1,
++ {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId2),
++ ?UINT32(?SSH_FX_OK), _/binary>>, _} =
++ create_link(LinkPath, ClientTarget, Cm, Channel, ReqId2),
++
++ {ok, RawActual} = file:read_link(LinkLocation),
++ RawExpected = string:trim(RawActual, trailing, "/"),
++
++ ReqId3 = ReqId2 + 1,
++ {ok, <<?SSH_FXP_NAME, ?UINT32(ReqId3), ?UINT32(_),
++ ?UINT32(Len3), ClientActualB2:Len3/binary, _/binary>>, _} =
++ read_link(LinkPath, Cm, Channel, ReqId3),
++ ClientActual2 = binary_to_list(ClientActualB2),
++ ClientExpected = ClientActual2
++ after
++ file:delete(LinkLocation)
+ end.
+
+ %%--------------------------------------------------------------------
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-06-13 11:42 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-13 11:42 [rpms/erlang] f44: Backport fix for CVE-2026-48855 Peter Lemenkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox