[emacs] CVE-2012-0035: CEDET global-ede-mode file loading vulnerability (rhbz#773024)
Karel Klíč
kklic at fedoraproject.org
Thu Jan 12 18:27:06 UTC 2012
commit 198f28a4fab3b6dc78b1d2021bfb448c08573cef
Author: Karel Klic <kklic at redhat.com>
Date: Thu Jan 12 20:27:23 2012 +0100
CVE-2012-0035: CEDET global-ede-mode file loading vulnerability (rhbz#773024)
emacs-ede-cve-2012-0035.patch | 483 +++++++++++++++++++++++++++++++++++++++++
emacs.spec | 8 +-
2 files changed, 490 insertions(+), 1 deletions(-)
---
diff --git a/emacs-ede-cve-2012-0035.patch b/emacs-ede-cve-2012-0035.patch
new file mode 100644
index 0000000..df39d54
--- /dev/null
+++ b/emacs-ede-cve-2012-0035.patch
@@ -0,0 +1,483 @@
+diff -r -c emacs-23.3-old/lisp/cedet/ede/auto.el emacs-23.3/lisp/cedet/ede/auto.el
+*** emacs-23.3-old/lisp/cedet/ede/auto.el 2011-01-09 01:45:14.000000000 +0800
+--- emacs-23.3/lisp/cedet/ede/auto.el 2012-01-09 13:20:12.410502713 +0800
+***************
+*** 58,63 ****
+--- 58,70 ----
+ :initform t
+ :documentation
+ "Non-nil if this is an option when a user creates a project.")
++ (safe-p :initarg :safe-p
++ :initform t
++ :documentation
++ "Non-nil if the project load files are \"safe\".
++ An unsafe project is one that loads project variables via Emacs
++ Lisp code. A safe project is one that loads project variables by
++ scanning files without loading Lisp code from them.")
+ )
+ "Class representing minimal knowledge set to run preliminary EDE functions.
+ When more advanced functionality is needed from a project type, that projects
+***************
+*** 69,81 ****
+ :name "Make" :file 'ede/proj
+ :proj-file "Project.ede"
+ :load-type 'ede-proj-load
+! :class-sym 'ede-proj-project)
+ (ede-project-autoload "edeproject-automake"
+ :name "Automake" :file 'ede/proj
+ :proj-file "Project.ede"
+ :initializers '(:makefile-type Makefile.am)
+ :load-type 'ede-proj-load
+! :class-sym 'ede-proj-project)
+ (ede-project-autoload "automake"
+ :name "automake" :file 'ede/project-am
+ :proj-file "Makefile.am"
+--- 76,90 ----
+ :name "Make" :file 'ede/proj
+ :proj-file "Project.ede"
+ :load-type 'ede-proj-load
+! :class-sym 'ede-proj-project
+! :safe-p nil)
+ (ede-project-autoload "edeproject-automake"
+ :name "Automake" :file 'ede/proj
+ :proj-file "Project.ede"
+ :initializers '(:makefile-type Makefile.am)
+ :load-type 'ede-proj-load
+! :class-sym 'ede-proj-project
+! :safe-p nil)
+ (ede-project-autoload "automake"
+ :name "automake" :file 'ede/project-am
+ :proj-file "Makefile.am"
+***************
+*** 84,89 ****
+--- 93,100 ----
+ :new-p nil))
+ "List of vectors defining how to determine what type of projects exist.")
+
++ (put 'ede-project-class-files 'risky-local-variable t)
++
+ ;;; EDE project-autoload methods
+ ;;
+ (defmethod ede-project-root ((this ede-project-autoload))
+***************
+*** 122,127 ****
+--- 133,151 ----
+ (when (and f (file-exists-p f))
+ f)))
+
++ (defmethod ede-auto-load-project ((this ede-project-autoload) dir)
++ "Load in the project associated with THIS project autoload description.
++ THIS project description should be valid for DIR, where the project will
++ be loaded."
++ ;; Last line of defense: don't load unsafe projects.
++ (when (not (or (oref this :safe-p)
++ (ede-directory-safe-p dir)))
++ (error "Attempt to load an unsafe project (bug elsewhere in EDE)"))
++ ;; Things are good - so load the project.
++ (let ((o (funcall (oref this load-type) dir)))
++ (when (not o)
++ (error "Project type error: :load-type failed to create a project"))
++ (ede-add-project-to-global-list o)))
+
+ (provide 'ede/auto)
+
+diff -r -c emacs-23.3-old/lisp/cedet/ede/simple.el emacs-23.3/lisp/cedet/ede/simple.el
+*** emacs-23.3-old/lisp/cedet/ede/simple.el 2011-01-09 01:45:14.000000000 +0800
+--- emacs-23.3/lisp/cedet/ede/simple.el 2012-01-09 13:17:20.010502312 +0800
+***************
+*** 50,56 ****
+ :name "Simple" :file 'ede/simple
+ :proj-file 'ede-simple-projectfile-for-dir
+ :load-type 'ede-simple-load
+! :class-sym 'ede-simple-project)
+ t)
+
+ (defcustom ede-simple-save-directory "~/.ede"
+--- 50,57 ----
+ :name "Simple" :file 'ede/simple
+ :proj-file 'ede-simple-projectfile-for-dir
+ :load-type 'ede-simple-load
+! :class-sym 'ede-simple-project
+! :safe-p nil)
+ t)
+
+ (defcustom ede-simple-save-directory "~/.ede"
+diff -r -c emacs-23.3-old/lisp/cedet/ede.el emacs-23.3/lisp/cedet/ede.el
+*** emacs-23.3-old/lisp/cedet/ede.el 2011-01-09 01:45:14.000000000 +0800
+--- emacs-23.3/lisp/cedet/ede.el 2012-01-09 13:24:44.854503349 +0800
+***************
+*** 94,99 ****
+--- 94,135 ----
+ :group 'ede
+ :type 'sexp) ; make this be a list of options some day
+
++ (defcustom ede-project-directories nil
++ "Directories in which EDE may search for project files.
++ If the value is t, EDE may search in any directory.
++
++ If the value is a function, EDE calls that function with one
++ argument, the directory name; the function should return t iff
++ EDE should look for project files in the directory.
++
++ Otherwise, the value should be a list of fully-expanded directory
++ names. EDE searches for project files only in those directories.
++ If you invoke the commands \\[ede] or \\[ede-new] on a directory
++ that is not listed, Emacs will offer to add it to the list.
++
++ Any other value disables searching for EDE project files."
++ :group 'ede
++ :type '(choice (const :tag "Any directory" t)
++ (repeat :tag "List of directories"
++ (directory))
++ (function :tag "Predicate"))
++ :version "23.4"
++ :risky t)
++
++ (defun ede-directory-safe-p (dir)
++ "Return non-nil if DIR is a safe directory to load projects from.
++ Projects that do not load a project definition as Emacs Lisp code
++ are safe, and can be loaded automatically. Other project types,
++ such as those created with Project.ede files, are safe only if
++ specified by `ede-project-directories'."
++ (setq dir (directory-file-name (expand-file-name dir)))
++ ;; Load only if allowed by `ede-project-directories'.
++ (or (eq ede-project-directories t)
++ (and (functionp ede-project-directories)
++ (funcall ede-project-directories dir))
++ (and (listp ede-project-directories)
++ (member dir ede-project-directories))))
++
+
+ ;;; Management variables
+
+***************
+*** 419,442 ****
+ Sets buffer local variables for EDE."
+ (let* ((ROOT nil)
+ (proj (ede-directory-get-open-project default-directory
+! 'ROOT)))
+ (when (or proj ROOT
+! (ede-directory-project-p default-directory t))
+
+! (when (not proj)
+! ;; @todo - this could be wasteful.
+! (setq proj (ede-load-project-file default-directory 'ROOT)))
+
+! (setq ede-object (ede-buffer-object (current-buffer)
+ 'ede-object-project))
+
+! (setq ede-object-root-project
+! (or ROOT (ede-project-root ede-object-project)))
+
+! (if (and (not ede-object) ede-object-project)
+! (ede-auto-add-to-target))
+
+! (ede-apply-target-options))))
+
+ (defun ede-reset-all-buffers (onoff)
+ "Reset all the buffers due to change in EDE.
+--- 455,496 ----
+ Sets buffer local variables for EDE."
+ (let* ((ROOT nil)
+ (proj (ede-directory-get-open-project default-directory
+! 'ROOT))
+! (projauto nil))
+!
+ (when (or proj ROOT
+! ;; If there is no open project, look up the project
+! ;; autoloader to see if we should initialize.
+! (setq projauto (ede-directory-project-p default-directory t)))
+!
+! (when (and (not proj) projauto)
+!
+! ;; No project was loaded, but we have a project description
+! ;; object. This means that we can check if it is a safe
+! ;; project to load before requesting it to be loaded.
+!
+! (when (or (oref projauto safe-p)
+! ;; The project style is not safe, so check if it is
+! ;; in `ede-project-directories'.
+! (let ((top (ede-toplevel-project default-directory)))
+! (ede-directory-safe-p top)))
+
+! ;; The project is safe, so load it in.
+! (setq proj (ede-load-project-file default-directory 'ROOT))))
+
+! ;; Only initialize EDE state in this buffer if we found a project.
+! (when proj
+!
+! (setq ede-object (ede-buffer-object (current-buffer)
+ 'ede-object-project))
+
+! (setq ede-object-root-project
+! (or ROOT (ede-project-root ede-object-project)))
+
+! (if (and (not ede-object) ede-object-project)
+! (ede-auto-add-to-target))
+
+! (ede-apply-target-options)))))
+
+ (defun ede-reset-all-buffers (onoff)
+ "Reset all the buffers due to change in EDE.
+***************
+*** 555,567 ****
+
+ ;;; Interactive method invocations
+ ;;
+! (defun ede (file)
+! "Start up EDE on something.
+! Argument FILE is the file or directory to load a project from."
+! (interactive "fProject File: ")
+! (if (not (file-exists-p file))
+! (ede-new file)
+! (ede-load-project-file (file-name-directory file))))
+
+ (defun ede-new (type &optional name)
+ "Create a new project starting of project type TYPE.
+--- 609,681 ----
+
+ ;;; Interactive method invocations
+ ;;
+! (defun ede (dir)
+! "Start up EDE for directory DIR.
+! If DIR has an existing project file, load it.
+! Otherwise, create a new project for DIR."
+! (interactive
+! ;; When choosing a directory to turn on, and we see some directory here,
+! ;; provide that as the default.
+! (let* ((top (ede-toplevel-project default-directory))
+! (promptdflt (or top default-directory)))
+! (list (read-directory-name "Project directory: "
+! promptdflt promptdflt t))))
+! (unless (file-directory-p dir)
+! (error "%s is not a directory" dir))
+! (when (ede-directory-get-open-project dir)
+! (error "%s already has an open project associated with it" dir))
+!
+! ;; Check if the directory has been added to the list of safe
+! ;; directories. It can also add the directory to the safe list if
+! ;; the user chooses.
+! (if (ede-check-project-directory dir)
+! (progn
+! ;; If there is a project in DIR, load it, otherwise do
+! ;; nothing.
+! (ede-load-project-file dir)
+!
+! ;; Check if we loaded anything on the previous line.
+! (if (ede-current-project dir)
+!
+! ;; We successfully opened an existing project. Some open
+! ;; buffers may also be referring to this project.
+! ;; Resetting all the buffers will get them to also point
+! ;; at this new open project.
+! (ede-reset-all-buffers 1)
+!
+! ;; ELSE
+! ;; There was no project, so switch to `ede-new' which is how
+! ;; a user can select a new kind of project to create.
+! (let ((default-directory (expand-file-name dir)))
+! (call-interactively 'ede-new))))
+!
+! ;; If the proposed directory isn't safe, then say so.
+! (error "%s is not an allowed project directory in `ede-project-directories'"
+! dir)))
+!
+! (defun ede-check-project-directory (dir)
+! "Check if DIR should be in `ede-project-directories'.
+! If it is not, try asking the user if it should be added; if so,
+! add it and save `ede-project-directories' via Customize.
+! Return nil iff DIR should not be in `ede-project-directories'."
+! (setq dir (directory-file-name (expand-file-name dir))) ; strip trailing /
+! (or (eq ede-project-directories t)
+! (and (functionp ede-project-directories)
+! (funcall ede-project-directories dir))
+! ;; If `ede-project-directories' is a list, maybe add it.
+! (when (listp ede-project-directories)
+! (or (member dir ede-project-directories)
+! (when (y-or-n-p (format "`%s' is not listed in `ede-project-directories'.
+! Add it to the list of allowed project directories? "
+! dir))
+! (push dir ede-project-directories)
+! ;; If possible, save `ede-project-directories'.
+! (if (or custom-file user-init-file)
+! (let ((coding-system-for-read nil))
+! (customize-save-variable
+! 'ede-project-directories
+! ede-project-directories)))
+! t)))))
+
+ (defun ede-new (type &optional name)
+ "Create a new project starting of project type TYPE.
+***************
+*** 596,601 ****
+--- 710,720 ----
+ (error "Cannot create project in non-existent directory %s" default-directory))
+ (when (not (file-writable-p default-directory))
+ (error "No write permissions for %s" default-directory))
++ (unless (ede-check-project-directory default-directory)
++ (error "%s is not an allowed project directory in `ede-project-directories'"
++ default-directory))
++ ;; Make sure the project directory is loadable in the future.
++ (ede-check-project-directory default-directory)
+ ;; Create the project
+ (let* ((obj (object-assoc type 'name ede-project-class-files))
+ (nobj (let ((f (oref obj file))
+***************
+*** 629,634 ****
+--- 748,757 ----
+ (ede-add-subproject pp nobj)
+ (ede-commit-project pp)))
+ (ede-commit-project nobj))
++ ;; Once the project is created, load it again. This used to happen
++ ;; lazily, but with project loading occurring less often and with
++ ;; security in mind, this is now the safe time to reload.
++ (ede-load-project-file default-directory)
+ ;; Have the menu appear
+ (setq ede-minor-mode t)
+ ;; Allert the user
+***************
+*** 651,661 ****
+ (defun ede-rescan-toplevel ()
+ "Rescan all project files."
+ (interactive)
+! (let ((toppath (ede-toplevel-project default-directory))
+! (ede-deep-rescan t))
+! (project-rescan (ede-load-project-file toppath))
+! (ede-reset-all-buffers 1)
+! ))
+
+ (defun ede-new-target (&rest args)
+ "Create a new target specific to this type of project file.
+--- 774,789 ----
+ (defun ede-rescan-toplevel ()
+ "Rescan all project files."
+ (interactive)
+! (if (not (ede-directory-get-open-project default-directory))
+! ;; This directory isn't open. Can't rescan.
+! (error "Attempt to rescan a project that isn't open")
+!
+! ;; Continue
+! (let ((toppath (ede-toplevel-project default-directory))
+! (ede-deep-rescan t))
+!
+! (project-rescan (ede-load-project-file toppath))
+! (ede-reset-all-buffers 1))))
+
+ (defun ede-new-target (&rest args)
+ "Create a new target specific to this type of project file.
+***************
+*** 891,897 ****
+ ;; Do the load
+ ;;(message "EDE LOAD : %S" file)
+ (let* ((file dir)
+! (path (expand-file-name (file-name-directory file)))
+ (pfc (ede-directory-project-p path))
+ (toppath nil)
+ (o nil))
+--- 1019,1025 ----
+ ;; Do the load
+ ;;(message "EDE LOAD : %S" file)
+ (let* ((file dir)
+! (path (file-name-as-directory (expand-file-name dir)))
+ (pfc (ede-directory-project-p path))
+ (toppath nil)
+ (o nil))
+***************
+*** 920,932 ****
+ ;; See if it's been loaded before
+ (setq o (object-assoc (ede-dir-to-projectfile pfc toppath) 'file
+ ede-projects))
+! (if (not o)
+! ;; If not, get it now.
+! (let ((ede-constructing pfc))
+! (setq o (funcall (oref pfc load-type) toppath))
+! (when (not o)
+! (error "Project type error: :load-type failed to create a project"))
+! (ede-add-project-to-global-list o)))
+
+ ;; Return the found root project.
+ (when rootreturn (set rootreturn o))
+--- 1048,1058 ----
+ ;; See if it's been loaded before
+ (setq o (object-assoc (ede-dir-to-projectfile pfc toppath) 'file
+ ede-projects))
+!
+! ;; If not open yet, load it.
+! (unless o
+! (let ((ede-constructing pfc))
+! (setq o (ede-auto-load-project pfc toppath))))
+
+ ;; Return the found root project.
+ (when rootreturn (set rootreturn o))
+***************
+*** 980,992 ****
+ (and root
+ (ede-find-subproject-for-directory root updir))
+ ;; Try the all structure based search.
+! (ede-directory-get-open-project updir)
+! ;; Load up the project file as a last resort.
+! ;; Last resort since it uses file-truename, and other
+! ;; slow features.
+! (and (ede-directory-project-p updir)
+! (ede-load-project-file
+! (file-name-as-directory updir))))))))))
+
+ (defun ede-current-project (&optional dir)
+ "Return the current project file.
+--- 1106,1112 ----
+ (and root
+ (ede-find-subproject-for-directory root updir))
+ ;; Try the all structure based search.
+! (ede-directory-get-open-project updir))))))))
+
+ (defun ede-current-project (&optional dir)
+ "Return the current project file.
+***************
+*** 1000,1010 ****
+ ;; No current project.
+ (when (not ans)
+ (let* ((ldir (or dir default-directory)))
+! (setq ans (ede-directory-get-open-project ldir))
+! (or ans
+! ;; No open project, if this dir pass project-p, then load.
+! (when (ede-directory-project-p ldir)
+! (setq ans (ede-load-project-file ldir))))))
+ ;; Return what we found.
+ ans))
+
+--- 1120,1126 ----
+ ;; No current project.
+ (when (not ans)
+ (let* ((ldir (or dir default-directory)))
+! (setq ans (ede-directory-get-open-project ldir))))
+ ;; Return what we found.
+ ans))
+
+***************
+*** 1059,1070 ****
+ "Return the project which is the parent of TARGET.
+ It is recommended you track the project a different way as this function
+ could become slow in time."
+! ;; @todo - use ede-object-project as a starting point.
+! (let ((ans nil) (projs ede-projects))
+! (while (and (not ans) projs)
+! (setq ans (ede-target-in-project-p (car projs) target)
+! projs (cdr projs)))
+! ans))
+
+ (defmethod ede-find-target ((proj ede-project) buffer)
+ "Fetch the target in PROJ belonging to BUFFER or nil."
+--- 1175,1187 ----
+ "Return the project which is the parent of TARGET.
+ It is recommended you track the project a different way as this function
+ could become slow in time."
+! (or ede-object-project
+! ;; If not cached, derive it from the current directory of the target.
+! (let ((ans nil) (projs ede-projects))
+! (while (and (not ans) projs)
+! (setq ans (ede-target-in-project-p (car projs) target)
+! projs (cdr projs)))
+! ans)))
+
+ (defmethod ede-find-target ((proj ede-project) buffer)
+ "Fetch the target in PROJ belonging to BUFFER or nil."
diff --git a/emacs.spec b/emacs.spec
index a5cacf2..4c46683 100644
--- a/emacs.spec
+++ b/emacs.spec
@@ -3,7 +3,7 @@ Summary: GNU Emacs text editor
Name: emacs
Epoch: 1
Version: 23.3
-Release: 18%{?dist}
+Release: 19%{?dist}
License: GPLv3+
URL: http://www.gnu.org/software/emacs/
Group: Applications/Editors
@@ -40,6 +40,8 @@ Patch8: emacs-wm-state-hidden.patch
Patch9: emacs-xgselect.patch
# http://bzr.savannah.gnu.org/lh/emacs/trunk/revision/103228
Patch10: 103228_103227.diff
+# http://lists.gnu.org/archive/html/emacs-devel/2012-01/msg00387.html
+Patch11: emacs-ede-cve-2012-0035.patch
BuildRequires: atk-devel, cairo-devel, freetype-devel, fontconfig-devel, dbus-devel, giflib-devel, glibc-devel, gtk2-devel, libpng-devel
BuildRequires: libjpeg-devel, libtiff-devel, libX11-devel, libXau-devel, libXdmcp-devel, libXrender-devel, libXt-devel
@@ -166,6 +168,7 @@ packages that add functionality to Emacs.
%patch8 -p1 -b .wm-state-hidden
%patch9 -p1 -b .xgselect
%patch10 -p0 -b .svn17
+%patch11 -p1 -b .ede-cve-2012-0035
# Install site-lisp files
cp %SOURCE7 %SOURCE10 site-lisp
@@ -446,6 +449,9 @@ update-desktop-database &> /dev/null || :
%dir %{_datadir}/emacs/site-lisp/site-start.d
%changelog
+* Thu Jan 12 2012 Karel Klíč <kklic at redhat.com> - 1:23.3-19
+- Added patch to handle CVE-2012-0035: CEDET global-ede-mode file loading vulnerability (rhbz#773024)
+
* Sun Nov 27 2011 Ville Skyttä <ville.skytta at iki.fi> - 1:23.3-18
- Apply upstream Subversion >= 1.7 dir structure fix for vc-svn.el.
More information about the scm-commits
mailing list