]> git.eshelyaron.com Git - emacs.git/commitdiff
Only allow SQLite extensions from an allowlist
authorLars Ingebrigtsen <larsi@gnus.org>
Tue, 14 Dec 2021 08:29:06 +0000 (09:29 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Tue, 14 Dec 2021 08:29:13 +0000 (09:29 +0100)
* src/sqlite.c (Fsqlite_load_extension): Only allow extensions
from an allowlist.

src/sqlite.c
test/src/sqlite-tests.el

index 248ad478d573dde7fdd30c5262cd206f439ab653..428b84b21e7711a3e58622d576460d4656d01884 100644 (file)
@@ -591,16 +591,42 @@ DEFUN ("sqlite-load-extension", Fsqlite_load_extension,
        doc: /* Load an SQlite MODULE into DB.
 MODULE should be the name of an SQlite module's file, a
 shared library in the system-dependent format and having a
-system-dependent file-name extension.  */)
+system-dependent file-name extension.
+
+Only modules on Emacs' list of allowed modules can be loaded.  */)
   (Lisp_Object db, Lisp_Object module)
 {
   check_sqlite (db, false);
   CHECK_STRING (module);
-  Lisp_Object module_encoded = ENCODE_FILE (Fexpand_file_name (module, Qnil));
 
-  sqlite3 *sdb = XSQLITE (db)->db;
-  int result = sqlite3_load_extension (sdb, SSDATA (module_encoded),
-                                      NULL, NULL);
+  /* Add names of useful and free modules here.  */
+  const char *allowlist[3] = { "pcre", "csvtable", NULL };
+  char *name = SSDATA (Ffile_name_nondirectory (module));
+  /* Possibly skip past a common prefix.  */
+  const char *prefix = "libsqlite3_mod_";
+  if (!strncmp (name, prefix, strlen (prefix)))
+    name += strlen (prefix);
+
+  bool do_allow = false;
+  for (const char **allow = allowlist; *allow; allow++)
+    {
+      if (strlen (*allow) < strlen (name)
+         && !strncmp (*allow, name, strlen (*allow))
+         && (!strcmp (name + strlen (*allow), ".so")
+             || !strcmp (name + strlen (*allow), ".DLL")))
+       {
+         do_allow = true;
+         break;
+       }
+    }
+
+  if (!do_allow)
+    xsignal (Qerror, build_string ("Module name not on allowlist"));
+
+  int result = sqlite3_load_extension
+                      (XSQLITE (db)->db,
+                       SSDATA (ENCODE_FILE (Fexpand_file_name (module, Qnil))),
+                       NULL, NULL);
   if (result ==  SQLITE_OK)
     return Qt;
   return Qnil;
index 6a88f0fd6cac21ab26b7b4cc66a56203dd54f39e..d1076e481c49f775a1600c11954555aab009de7c 100644 (file)
     (sqlite-close db)
     (should-error (sqlite-select db "select * from test6"))))
 
+(ert-deftest sqlite-load-extension ()
+  (skip-unless (sqlite-available-p))
+  (let (db)
+    (setq db (sqlite-open))
+    (should-error
+     (sqlite-load-extension db "/usr/lib/sqlite3/notpcre.so"))
+    (should-error
+     (sqlite-load-extension db "/usr/lib/sqlite3/n"))
+    (should-error
+     (sqlite-load-extension db "/usr/lib/sqlite3/"))
+    (should-error
+     (sqlite-load-extension db "/usr/lib/sqlite3"))
+    (should
+     (memq
+      (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
+      '(nil t)))
+
+    (should-error
+     (sqlite-load-extension
+      db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_notcsvtable.so"))
+    (should-error
+     (sqlite-load-extension
+      db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtablen.so"))
+    (should-error
+     (sqlite-load-extension
+      db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
+    (should
+     (memq
+      (sqlite-load-extension
+       db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
+      '(nil t)))))
+
 ;;; sqlite-tests.el ends here