Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 282 additions & 0 deletions SPECS/emacs/CVE-2026-79992.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
From f39b1124616c17ff8eaf6330aa466b16c51e8eeb Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Sun, 30 Aug 2026 20:19:33 +0000
Subject: [PATCH] Restrict Tramp user name

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://cgit.git.savannah.gnu.org/cgit/emacs.git/patch/?id=f3e7104d05bdb8e32ba13bf75604108ad88536dc

---
doc/misc/tramp.texi | 4 +++-
lisp/net/tramp-gvfs.el | 36 ++++++++++++++++++++----------------
lisp/net/tramp-rclone.el | 4 ++--
lisp/net/tramp-smb.el | 6 +++---
lisp/net/tramp.el | 16 ++++++++++++----
5 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 0bed7db..4573218 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -3420,7 +3420,9 @@ brackets @file{@value{ipv6prefix}} and @file{@value{ipv6postfix}}.
By default, @value{tramp} will use the current local user name as the
remote user name for log in to the remote host. Specifying a
different name using the proper syntax will override this default
-behavior: @file{@trampfn{method,user@@host,path/to/file}}.
+behavior: @file{@trampfn{method,user@@host,path/to/file}}. The user
+name can also be taken from an environment variable, like
+@file{@trampfn{method,@env{$MY_REMOTE_USER}@@host,path/to/file}}.

@file{@trampfn{ssh,daniel@@melancholia,.emacs}} is for file
@file{.emacs} in @code{daniel}'s home directory on the host,
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 2ccba85..5081a81 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1202,7 +1202,7 @@ file names."
(tramp-compat-rx bos "/" (+ (not "/")) (group "/.." (? "/")))
localname)
(setq localname (replace-match "/" t t localname 1)))
- (when (string-match (rx bol "/.." (? "/")) localname)
+ (when (string-match (rx bos "/.." (? "/")) localname)
(setq localname (replace-match "/" t t localname))))
;; There might be a double slash. Remove this.
(while (string-match "//" localname)
@@ -1296,9 +1296,9 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(with-parsed-tramp-file-name filename nil
(setq localname (tramp-compat-file-name-unquote localname))
(if (or (and (string-match-p
- (rx bol (| "afp" (: "dav" (? "s")) "smb") eol) method)
+ (rx bos (| "afp" (: "dav" (? "s")) "smb") eos) method)
(string-match-p
- (tramp-compat-rx bol (? "/") (+ (not "/")) eol) localname))
+ (tramp-compat-rx bos (? "/") (+ (not "/")) eos) localname))
(string-equal localname "/"))
(tramp-gvfs-get-root-attributes filename)
(assoc
@@ -1332,7 +1332,11 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(lambda (x)
(unibyte-string (string-to-number (match-string 1 x) 16)))
res-symlink-target)
- 'utf-8)))
+ 'utf-8))
+ ;; If the resulting localname looks remote, we must quote it
+ ;; for security reasons.
+ (when (tramp-tramp-file-p res-symlink-target)
+ (setq res-symlink-target (file-name-quote res-symlink-target 'top))))
;; ... number links
(setq res-numlinks
(string-to-number
@@ -1755,7 +1759,7 @@ ID-FORMAT valid values are `string' and `integer'."
"Retrieve file name from D-Bus OBJECT-PATH."
(dbus-unescape-from-identifier
(replace-regexp-in-string
- (tramp-compat-rx bol (* nonl) "/" (group (+ (not "/"))) eol) "\\1"
+ (tramp-compat-rx bos (* nonl) "/" (group (+ (not "/"))) eos) "\\1"
object-path)))

(defun tramp-gvfs-url-host (url)
@@ -1763,7 +1767,7 @@ ID-FORMAT valid values are `string' and `integer'."
We cannot use `url-host', because `url-generic-parse-url' returns
a downcased host name only."
(and (stringp url)
- (string-match (rx bol (+ alnum) "://" (group (+ (not (any "/:"))))) url)
+ (string-match (rx bos (+ alnum) "://" (group (+ (not (any "/:"))))) url)
(match-string 1 url)))


@@ -1899,7 +1903,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(cadr (assoc "ssl" (cadr mount-spec)))))
(uri (tramp-gvfs-dbus-byte-array-to-string
(cadr (assoc "uri" (cadr mount-spec))))))
- (when (string-match (rx bol (group (| "afp" "smb"))) method)
+ (when (string-match (rx bos (group (| "afp" "smb"))) method)
(setq method (match-string 1 method)))
(when (and (string-equal "dav" method) (string-equal "true" ssl))
(setq method "davs"))
@@ -1999,7 +2003,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(or
(cadr (assoc "share" (cadr mount-spec)))
(cadr (assoc "volume" (cadr mount-spec)))))))
- (when (string-match (rx bol (group (| "afp" "smb"))) method)
+ (when (string-match (rx bos (group (| "afp" "smb"))) method)
(setq method (match-string 1 method)))
(when (and (string-equal "dav" method) (string-equal "true" ssl))
(setq method "davs"))
@@ -2032,7 +2036,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(string-equal host (tramp-file-name-host vec))
(string-equal port (tramp-file-name-port vec))
(string-match-p
- (tramp-compat-rx bol "/" (literal (or share "")))
+ (tramp-compat-rx bos "/" (literal (or share "")))
(tramp-file-name-unquote-localname vec)))
;; Set mountpoint and location.
(tramp-set-file-property vec "/" "fuse-mountpoint" fuse-mountpoint)
@@ -2058,7 +2062,7 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and
(defun tramp-gvfs-mount-spec-entry (key value)
"Construct a mount-spec entry to be used in a mount_spec.
It was \"a(say)\", but has changed to \"a{sv})\"."
- (if (string-match-p (rx bol "(aya{sv})") tramp-gvfs-mountlocation-signature)
+ (if (string-match-p (rx bos "(aya{sv})") tramp-gvfs-mountlocation-signature)
(list :dict-entry key
(list :variant (tramp-gvfs-dbus-string-to-byte-array value)))
(list :struct key (tramp-gvfs-dbus-string-to-byte-array value))))
@@ -2077,10 +2081,10 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
(tramp-media-device-port media) (tramp-file-name-port vec)))
(localname (tramp-file-name-unquote-localname vec))
(share (when (string-match
- (tramp-compat-rx bol (? "/") (group (+ (not "/"))))
+ (tramp-compat-rx bos (? "/") (group (+ (not "/"))))
localname)
(match-string 1 localname)))
- (ssl (if (string-match-p (rx bol (| "davs" "nextcloud")) method)
+ (ssl (if (string-match-p (rx bos (| "davs" "nextcloud")) method)
"true" "false"))
(mount-spec
`(:array
@@ -2089,7 +2093,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
(list (tramp-gvfs-mount-spec-entry "type" "smb-share")
(tramp-gvfs-mount-spec-entry "server" host)
(tramp-gvfs-mount-spec-entry "share" share)))
- ((string-match-p (rx bol (| "davs" "nextcloud")) method)
+ ((string-match-p (rx bos (| "davs" "nextcloud")) method)
(list (tramp-gvfs-mount-spec-entry "type" "dav")
(tramp-gvfs-mount-spec-entry "host" host)
(tramp-gvfs-mount-spec-entry "ssl" ssl)))
@@ -2103,7 +2107,7 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
((string-equal "nextcloud" method)
(list (tramp-gvfs-mount-spec-entry "type" "owncloud")
(tramp-gvfs-mount-spec-entry "host" host)))
- ((string-match-p (rx bol "http") method)
+ ((string-match-p (rx bos "http") method)
(list (tramp-gvfs-mount-spec-entry "type" "http")
(tramp-gvfs-mount-spec-entry
"uri"
@@ -2120,9 +2124,9 @@ It was \"a(say)\", but has changed to \"a{sv})\"."
,@(when port
(list (tramp-gvfs-mount-spec-entry "port" port)))))
(mount-pref
- (if (and (string-match-p (rx bol "dav") method)
+ (if (and (string-match-p (rx bos "dav") method)
(string-match
- (tramp-compat-rx bol (? "/") (+ (not "/"))) localname))
+ (tramp-compat-rx bos (? "/") (+ (not "/"))) localname))
(match-string 0 localname)
(tramp-gvfs-get-remote-prefix vec))))

diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 6ebd17d..3aa63db 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -188,7 +188,7 @@ arguments to pass to the OPERATION."
(delq nil
(mapcar
(lambda (line)
- (when (string-match (rx bol (group (+ (not blank))) ":" eol) line)
+ (when (string-match (rx bos (group (+ (not blank))) ":" eos) line)
`(nil ,(match-string 1 line))))
(tramp-process-lines nil tramp-rclone-program "listremotes")))))

@@ -362,7 +362,7 @@ file names."
(tramp-rclone-maybe-open-connection v)
;; TODO: This shall be handled by `expand-file-name'.
(setq localname
- (replace-regexp-in-string (rx bol ".") "" (or localname "")))
+ (replace-regexp-in-string (rx bos ".") "" (or localname "")))
(format "%s%s" (tramp-fuse-mounted-p v) localname)))
;; It is a local file name.
filename))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 6d5697a..d07b81d 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1650,7 +1650,7 @@ VEC or USER, or if there is no home directory, return nil."
(save-match-data
(let ((localname (tramp-file-name-unquote-localname vec)))
(when (string-match
- (tramp-compat-rx bol (? "/") (group (+ (not "/"))) "/") localname)
+ (tramp-compat-rx bos (? "/") (group (+ (not "/"))) "/") localname)
(match-string 1 localname)))))

(defun tramp-smb-get-localname (vec)
@@ -1661,7 +1661,7 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"."
(setq
localname
(if (string-match
- (tramp-compat-rx bol (? "/") (+ (not "/")) (group "/" (* nonl)))
+ (tramp-compat-rx bos (? "/") (+ (not "/")) (group "/" (* nonl)))
localname)
;; There is a share, separated by "/".
(if (not (tramp-smb-get-cifs-capabilities vec))
@@ -1671,7 +1671,7 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"."
(match-string 1 localname))
;; There is just a share.
(if (string-match
- (tramp-compat-rx bol (? "/") (group (+ (not "/"))) eol) localname)
+ (tramp-compat-rx bos (? "/") (group (+ (not "/"))) eos) localname)
(match-string 1 localname)
"")))

diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 2d6db31..66c8d95 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -931,11 +931,11 @@ Used in `tramp-make-tramp-file-name'.")

(defun tramp-build-prefix-regexp ()
"Return `tramp-prefix-regexp'."
- (tramp-compat-rx bol (literal (tramp-build-prefix-format))))
+ (tramp-compat-rx bos (literal (tramp-build-prefix-format))))

(defvar tramp-prefix-regexp nil ; Initialized when defining `tramp-syntax'!
"Regexp matching the very beginning of Tramp file names.
-Should always start with \"^\". Derived from `tramp-prefix-format'.")
+Should always start with \"\\\\=`\". Derived from `tramp-prefix-format'.")

(defconst tramp-method-regexp-alist
`((default . ,(tramp-compat-rx
@@ -976,7 +976,10 @@ Used in `tramp-make-tramp-file-name'.")
"Regexp matching delimiter between method and user or host names.
Derived from `tramp-postfix-method-format'.")

-(defconst tramp-user-regexp (rx (+ (not (any "/:|" blank))))
+(defconst tramp-user-regexp
+ (rx (| (+ (not (any "/\\^$?*:;|[]{}()<>`'\"" blank)))
+ ;; Environment variable.
+ (: "$" (+ (any "_" alnum)))))
"Regexp matching user names.")

(defconst tramp-prefix-domain-format "%"
@@ -1735,6 +1738,8 @@ default values are used."
(hop (match-string (nth 5 tramp-file-name-structure) name))
domain port v)
(when user
+ (while (string-match (rx bos "$" (group (+ (any "_" alnum))) eos) user)
+ (setq user (getenv (match-string 1 user))))
(when (string-match tramp-user-with-domain-regexp user)
(setq domain (match-string 2 user)
user (match-string 1 user))))
@@ -2753,9 +2758,9 @@ Fall back to normal file name handler if no Tramp file name handler exists."
;; `file-remote-p' is called for everything, even for symbolic
;; links which look remote. We don't want to get an error.
(non-essential (or non-essential (eq operation 'file-remote-p))))
+ (setq filename (tramp-replace-environment-variables filename))
(if (tramp-tramp-file-p filename)
(save-match-data
- (setq filename (tramp-replace-environment-variables filename))
(with-parsed-tramp-file-name filename nil
(let ((current-connection tramp-current-connection)
(foreign
@@ -6352,6 +6357,9 @@ to cache the result. Return the modified ATTR."
(caar attr))
(decode-coding-string
(match-string 1 (caar attr)) 'utf-8))))
+ ;; Quote remote-like symlink.
+ (when (and (stringp (car attr)) (tramp-tramp-file-p (car attr)))
+ (setcar attr (file-name-quote (car attr) 'top)))
;; Set file's gid change bit.
(setcar
(nthcdr 9 attr)
--
2.45.4

6 changes: 5 additions & 1 deletion SPECS/emacs/emacs.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Summary: GNU Emacs text editor
Name: emacs
Version: 29.4
Release: 4%{?dist}
Release: 5%{?dist}
License: GPLv3+ AND CC0-1.0
Vendor: Microsoft Corporation
Distribution: Azure Linux
Expand All @@ -13,6 +13,7 @@ Source2: default.el
Patch0: CVE-2025-1244.patch
Patch1: CVE-2024-53920.patch
Patch2: CVE-2026-6861.patch
Patch3: CVE-2026-79992.patch
BuildRequires: gcc
BuildRequires: glibc-devel
BuildRequires: gnutls-devel
Expand Down Expand Up @@ -131,6 +132,9 @@ rm -f *-filelist {common,el}-*-files
%dir %{_datadir}/emacs/site-lisp/site-start.d

%changelog
* Sun Aug 30 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 29.4-5
- Patch for CVE-2026-79992

* Wed Apr 29 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 29.4-4
- Patch for CVE-2026-6861

Expand Down
Loading