branch: elpa/age
commit 63e9b156abf048dd9ff4a6fdb10c3153dc81eaba
Author: Bas Alberts <[email protected]>
Commit: Bas Alberts <[email protected]>
Make any temporary decryptions run through /dev/shm when available
Apparently epg runs temporary decryption through whatever the
temporary-file-directory is set to. This is /tmp by default and
that is not ideal, to say the least. This means that Emacs gpg
decryptions litter the /tmp directory with plaintext copies of
your gpg files (during a small window when opening or saving).
It does this with a predicatable pattern gpg-output* or gpg-input*
since age.el is a port of epg functionality, it has the same
weakness.
As a stopgap, age.el will run these operations through /dev/shm
when and where it is available. I'll think about how we can do a
buffer-only operation, since in our threat model limiting our
plaintext exposure to emacs memory contents is the best we can
hope for. While someone that has user privileges to monitor e.g.
/dev/shm for file creations can obviously also dump memory from
the emacs process, this would be a more annoying proposition than
placing a filewatch and harvesting plaintext copies of decrypted
files out of a temporary directory.
Making these intermediate writes at least remain memory resident
as opposed to disk resident when /dev/shm is an option is a
reasonable first step I reckon.
I'll note that memory contents can/will be flushed to disk
in a variety of scenarios, but I don't like the idea of such a
simple harvesting mechanism being available by default.
I think I should be able to just rework it such that everything runs
over process stdio as opposed to intermediate plaintext files.
---
age.el | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/age.el b/age.el
index 1d8cf08b2e5..eb848ca2386 100644
--- a/age.el
+++ b/age.el
@@ -310,6 +310,14 @@ or higher is installed."
;;;; Context Methods
+(cl-defmacro age-with-dev-shm (&body body)
+ "Bind temporary-file-directory to /dev/shm if it exists."
+ `(let ((temporary-file-directory
+ (if (file-directory-p "/dev/shm/")
+ "/dev/shm/"
+ ,temporary-file-directory)))
+ ,@body))
+
;; This is not an alias, just so we can mark it as autoloaded.
;;;###autoload
(defun age-make-context (&optional protocol armor)
@@ -592,7 +600,7 @@ If PLAIN is nil, it returns the result as a string."
(unwind-protect
(progn
(setf (age-context-output-file context)
- (or plain (make-temp-file "age-output")))
+ (or plain (age-with-dev-shm (make-temp-file "age-output"))))
(age-start-decrypt context (age-make-data-from-file cipher))
(age-wait-for-completion context)
(age--check-error-for-decrypt context)
@@ -604,13 +612,13 @@ If PLAIN is nil, it returns the result as a string."
(defun age-decrypt-string (context cipher)
"Decrypt a string CIPHER and return the plain text."
- (let ((input-file (make-temp-file "age-input"))
+ (let ((input-file (age-with-dev-shm (make-temp-file "age-input")))
(coding-system-for-write 'binary))
(unwind-protect
(progn
(write-region cipher nil input-file nil 'quiet)
(setf (age-context-output-file context)
- (make-temp-file "age-output"))
+ (age-with-dev-shm (make-temp-file "age-output")))
(age-start-decrypt context (age-make-data-from-file input-file))
(age-wait-for-completion context)
(age--check-error-for-decrypt context)
@@ -678,7 +686,7 @@ If RECIPIENTS is nil, it performs symmetric encryption."
(unwind-protect
(progn
(setf (age-context-output-file context)
- (or cipher (make-temp-file "age-output")))
+ (or cipher (age-with-dev-shm (make-temp-file "age-output"))))
(age-start-encrypt context (age-make-data-from-file plain) recipients)
(age-wait-for-completion context)
(let ((errors (age-context-result-for context 'error)))
@@ -697,12 +705,12 @@ If RECIPIENTS is nil, it performs symmetric encryption."
(let ((input-file
;; XXX: this is always true, but keep the protocol flexibility for now
(when (eq (age-context-protocol context) 'Age)
- (make-temp-file "age-input")))
+ (age-with-dev-shm (make-temp-file "age-input"))))
(coding-system-for-write 'binary))
(unwind-protect
(progn
(setf (age-context-output-file context)
- (make-temp-file "age-output"))
+ (age-with-dev-shm (make-temp-file "age-output")))
(if input-file
(write-region plain nil input-file nil 'quiet))
(age-start-encrypt context