about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-03-07 21:57:11 -0800
committerKartik K. Agaram <vc@akkartik.com>2022-03-07 21:57:11 -0800
commit2b47f763086cba3369a928c8e9d9d9543b844e37 (patch)
treeca95526d9414625640dc8206cb8022485268e3ca
parent2d393bfb80854c8320195b97fecbfe85f62fa9eb (diff)
downloadteliva-2b47f763086cba3369a928c8e9d9d9543b844e37.tar.gz
just always temp files to be created
Implication: os.rename now needs to be sandboxed. Hopefully it's
tractable to treat it as conceptually identical to opening two files.
-rw-r--r--src/file.lua2
-rw-r--r--src/kilo.c4
-rw-r--r--src/liolib.c4
-rw-r--r--src/loslib.c15
-rw-r--r--src/teliva.c8
-rw-r--r--src/teliva.h3
6 files changed, 26 insertions, 10 deletions
diff --git a/src/file.lua b/src/file.lua
index 17e543c..81fe68d 100644
--- a/src/file.lua
+++ b/src/file.lua
@@ -44,7 +44,7 @@ function temporary_filename_in_same_volume(filename)
   -- so that a future rename works
   local i = 1
   while true do
-    temporary_filename = 'teliva_temp_'..filename..'_'..i
+    temporary_filename = 'teliva_tmp_'..filename..'_'..i
     if io.open(temporary_filename) == nil then
       -- file doesn't exist yet; create a placeholder and return it
       local handle = io.open(temporary_filename, 'w')
diff --git a/src/kilo.c b/src/kilo.c
index da58368..0f652cf 100644
--- a/src/kilo.c
+++ b/src/kilo.c
@@ -167,10 +167,6 @@ static int is_separator(int c) {
     return c == '\0' || isspace(c) || strchr(",.()+-/*=~%[];",c) != NULL;
 }
 
-static int starts_with(const char* s, const char* prefix) {
-    return strncmp(prefix, s, strlen(prefix)) == 0;
-}
-
 /* Return true if the specified row last char is part of a multi line comment
  * that starts at this row or at one before, and does not end at the end
  * of the row but spawns to the next row. */
diff --git a/src/liolib.c b/src/liolib.c
index b6cff86..6fb3359 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -132,7 +132,9 @@ static int io_open (lua_State *L) {
   snprintf(buffer, 1020, "io.open(\"%s\", \"%s\")", filename, mode);
   append_to_audit_log(L, buffer);
   FILE **pf = newfile(L);
-  if (file_operation_permitted(filename, mode))
+  if (file_operation_permitted(filename, mode)
+      /* filenames starting with teliva_tmp_ are always ok */
+      || starts_with(filename, "teliva_tmp_"))
     *pf = fopen(filename, mode);
   else {
     snprintf(iolib_errbuf, 1024, "app tried to open file '%s'; adjust its permissions (ctrl-p) if that is expected", filename);
diff --git a/src/loslib.c b/src/loslib.c
index 785447c..09a00c3 100644
--- a/src/loslib.c
+++ b/src/loslib.c
@@ -18,6 +18,7 @@
 
 #include "lauxlib.h"
 #include "lualib.h"
+#include "teliva.h"
 
 
 static int os_pushresult (lua_State *L, int i, const char *filename) {
@@ -41,9 +42,23 @@ static int os_remove (lua_State *L) {
 }
 
 
+static char oslib_errbuf[1024] = {0};
 static int os_rename (lua_State *L) {
   const char *fromname = luaL_checkstring(L, 1);
   const char *toname = luaL_checkstring(L, 2);
+  /* A rename is like reading from one file and writing to another file. */
+  if (!file_operation_permitted(fromname, "r")
+      && !starts_with(fromname, "teliva_tmp_")) {
+    snprintf(oslib_errbuf, 1024, "app tried to open file '%s' for reading; adjust its permissions (ctrl-p) if that is expected", fromname);
+    Previous_message = oslib_errbuf;
+    return os_pushresult(L, 0, fromname);
+  }
+  if (!file_operation_permitted(toname, "w")
+      && !starts_with(fromname, "teliva_tmp_")) {
+    snprintf(oslib_errbuf, 1024, "app tried to open file '%s' for writing; adjust its permissions (ctrl-p) if that is expected", toname);
+    Previous_message = oslib_errbuf;
+    return os_pushresult(L, 0, toname);
+  }
   return os_pushresult(L, rename(fromname, toname) == 0, fromname);
 }
 
diff --git a/src/teliva.c b/src/teliva.c
index 9ae7328..b604524 100644
--- a/src/teliva.c
+++ b/src/teliva.c
@@ -16,6 +16,10 @@
 #include "teliva.h"
 #include "tlv.h"
 
+int starts_with(const char* s, const char* prefix) {
+  return strncmp(s, prefix, strlen(prefix)) == 0;
+}
+
 /*** Standard UI elements */
 
 int menu_column = 0;
@@ -361,10 +365,6 @@ static void clear_caller(lua_State* L) {
   assert(lua_gettop(L) == oldtop);
 }
 
-static int starts_with(const char* s, const char* pre) {
-  return strncmp(pre, s, strlen(pre)) == 0;
-}
-
 /* return true if submitted */
 static int edit_current_definition(lua_State* L);
 static void recent_changes_view(lua_State* L);
diff --git a/src/teliva.h b/src/teliva.h
index f07b761..2e79956 100644
--- a/src/teliva.h
+++ b/src/teliva.h
@@ -190,4 +190,7 @@ extern int report_in_developer_mode(lua_State* L, int status);
 
 extern void render_previous_error(void);
 
+/* Misc */
+extern int starts_with(const char* s, const char* prefix);
+
 #endif