public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/erlang] f43: 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 : f43
            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=f43

            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] f43: 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