patch 9.0.1669: Crash syncing swapfile in new buffer when using sodium crypt
Problem: Crash syncing swapfile in new buffer when using sodium crypt.
(James McCoy)
Solution: Add checks for sodium encryption. (Christian Brabandt,
closes #12591, closes #12585)
diff --git a/src/memline.c b/src/memline.c
index 3483f09..cf2dc8c 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -425,6 +425,24 @@
#if defined(FEAT_CRYPT) || defined(PROTO)
/*
+ * Swapfile encryption is not supported by XChaCha20. If this crypt method is
+ * used then disable the swapfile, to avoid plain text being written to disk,
+ * and return TRUE.
+ * Otherwise return FALSE.
+ */
+ static int
+crypt_may_close_swapfile(buf_T *buf, char_u *key, int method)
+{
+ if (crypt_method_is_sodium(method) && *key != NUL)
+ {
+ mf_close_file(buf, TRUE);
+ buf->b_p_swf = FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
* Prepare encryption for "buf" for the current key and method.
*/
static void
@@ -440,11 +458,10 @@
// Generate a seed and store it in the memfile.
sha2_seed(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN, NULL, 0);
}
-#ifdef FEAT_SODIUM
+# ifdef FEAT_SODIUM
else if (crypt_method_is_sodium(method_nr))
- crypt_sodium_randombytes_buf(buf->b_ml.ml_mfp->mf_seed,
- MF_SEED_LEN);
-#endif
+ crypt_sodium_randombytes_buf(buf->b_ml.ml_mfp->mf_seed, MF_SEED_LEN);
+# endif
}
/*
@@ -501,16 +518,10 @@
return; // no memfile yet, nothing to do
old_method = crypt_method_nr_from_name(old_cm);
- // Swapfile encryption is not supported by XChaCha20, therefore disable the
- // swapfile to avoid plain text being written to disk.
- if (crypt_method_is_sodium(crypt_get_method_nr(buf))
- && *buf->b_p_key != NUL)
- {
- // close the swapfile
- mf_close_file(buf, TRUE);
- buf->b_p_swf = FALSE;
+#ifdef FEAT_CRYPT
+ if (crypt_may_close_swapfile(buf, buf->b_p_key, crypt_get_method_nr(buf)))
return;
- }
+#endif
// First make sure the swapfile is in a consistent state, using the old
// key and method.
@@ -2494,6 +2505,12 @@
|| buf->b_ml.ml_mfp->mf_fd < 0)
continue; // no file
+#ifdef FEAT_CRYPT
+ if (crypt_may_close_swapfile(buf, buf->b_p_key,
+ crypt_get_method_nr(buf)))
+ continue;
+#endif
+
ml_flush_line(buf); // flush buffered line
// flush locked block
(void)ml_find_line(buf, (linenr_T)0, ML_FLUSH);
@@ -2551,6 +2568,10 @@
emsg(_(e_cannot_preserve_there_is_no_swap_file));
return;
}
+#ifdef FEAT_CRYPT
+ if (crypt_may_close_swapfile(buf, buf->b_p_key, crypt_get_method_nr(buf)))
+ return;
+#endif
// We only want to stop when interrupted here, not when interrupted
// before.
@@ -5571,6 +5592,9 @@
if (*key == NUL)
return NULL;
+ if (crypt_may_close_swapfile(buf, key, method_nr))
+ return NULL;
+
if (method_nr == CRYPT_M_ZIP)
{
// For PKzip: Append the offset to the key, so that we use a different