[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Avoiding arbitrary code execution with macroexpansion
From: |
Wilfred Hughes |
Subject: |
Avoiding arbitrary code execution with macroexpansion |
Date: |
Wed, 15 Aug 2018 22:52:04 +0100 |
Hi emacs-devel
Today I realised that macroexpand-all isn't safe to call on arbitrary elisp:
(macroexpand-all '(eval-when-compile (debug)))
Using a macro that calls eval, such as eval-when-compile,
eval-and-compile, c-lang-defconst-eval-immediately (undoubtedly others
too), means anything can happen at macroexpansion time.
Unfortunately, some emacs packages assume this is a safe thing to do.
I used to think so, because macroexpand-all only executes macros that
are loaded (and therefore trusted) in the current Emacs instance.
Macros that eval code break this.
Even elisp-mode.el assumes this:
(let ((fooo (eval-when-compile (progn (debug)))))
foo ;; <- put point here and M-x completion-at-point
)
This means that I can get arbitrary code execution by you opening and
calling code completion a maliciously crafted elisp file!
Is this a security bug in Emacs?
In any case, is there a safe way to do macroexpansion? The best I can
think of is this:
(let ((macro-whitelist '(when pcase))
all-macros
safe-env)
(mapatoms
(lambda (sym)
(when (macrop sym)
(push sym all-macros))))
(mapc
(lambda (sym)
(unless (memq sym macro-whitelist)
(push (cons sym (symbol-function 'ignore))
safe-env)))
all-macros)
(macroexpand-all
arbitrary-form-here
safe-env))
Thanks
Wilfred
- Avoiding arbitrary code execution with macroexpansion,
Wilfred Hughes <=