Commit Diff


commit - 44401529a2253cbf00583a3680ae01f0cb74693c
commit + 4b88d5fd9833b1c236572e7c557646909ec415eb
blob - c0bee2ba99ea9ee940661b5febaf9a1f56356620
blob + 477e69071019cf11e081ad9eea58dd82abd1efb4
--- src/box/call.c
+++ src/box/call.c
@@ -160,9 +160,8 @@ box_run_on_call(enum iproto_type type, const char *exp
 	trigger_run(&box_on_call, &ctx);
 }
 
-/** Checks if the current user may execute any global Lua function. */
-static int
-access_check_call(const char *name, uint32_t name_len)
+int
+access_check_lua_call(const char *name, uint32_t name_len)
 {
 	struct credentials *cr = effective_user();
 	user_access_t access = PRIV_X | PRIV_U;
@@ -182,7 +181,7 @@ access_check_call(const char *name, uint32_t name_len)
 
 /** Checks if the current user may execute an arbitrary Lua expression. */
 static int
-access_check_eval(void)
+access_check_lua_eval(void)
 {
 	struct credentials *cr = effective_user();
 	user_access_t access = PRIV_X | PRIV_U;
@@ -229,7 +228,7 @@ box_process_call(struct call_request *request, struct 
 			goto cleanup;
 		}
 	} else {
-		if (access_check_call(name, name_len) != 0) {
+		if (access_check_lua_call(name, name_len) != 0) {
 			rc = -1;
 			goto cleanup;
 		}
@@ -249,7 +248,7 @@ box_process_eval(struct call_request *request, struct 
 {
 	rmean_collect(rmean_box, IPROTO_EVAL, 1);
 	/* Check permissions */
-	if (access_check_eval() != 0)
+	if (access_check_lua_eval() != 0)
 		return -1;
 	struct mp_box_ctx ctx;
 	if (mp_box_ctx_create(&ctx, NULL, request->tuple_formats) != 0)
blob - 0f8e31842ce1d5dc660354a45ba43d8b5f9022ce
blob + 911616772b049fa542b3ceee93a22b2dbaffe6bb
--- src/box/call.h
+++ src/box/call.h
@@ -76,6 +76,10 @@ box_process_call(struct call_request *request, struct 
 int
 box_process_eval(struct call_request *request, struct port *port);
 
+/** Checks if the current user may execute a global Lua function. */
+int
+access_check_lua_call(const char *name, uint32_t name_len);
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
blob - ae3f89c75f17f79b2e6022a2368d39110457daf7
blob + 0dfea46254f091301d9ba001f2402a5c3c0a81f3
--- src/box/func.c
+++ src/box/func.c
@@ -31,6 +31,7 @@
 #include "func.h"
 #include "fiber.h"
 #include "assoc.h"
+#include "call.h"
 #include "lua/call.h"
 #include "diag.h"
 #include "port.h"
@@ -567,6 +568,10 @@ func_access_check(struct func *func)
 	if ((func_access & PRIV_U) != 0 ||
 	    (func->def->uid != credentials->uid &&
 	     func_access & ~func->access[credentials->auth_token].effective)) {
+		if (func->def->language == FUNC_LANGUAGE_LUA &&
+		    func->def->body == NULL)
+			return access_check_lua_call(func->def->name,
+						     func->def->name_len);
 		/* Access violation, report error. */
 		struct user *user = user_find(credentials->uid);
 		if (user != NULL) {
blob - 02e1399d1c587e0fa0c0866e8c85a5b5928ce1c9
blob + fbb9a6067465f584c208b3661e4b71172160d015
--- test/box-luatest/gh_8803_exec_priv_test.lua
+++ test/box-luatest/gh_8803_exec_priv_test.lua
@@ -133,6 +133,7 @@ g.before_test('test_lua_call_func', function(cg)
             language = 'LUA',
             body = [[function() return true end]],
         })
+        box.schema.func.create('dostring', {language = 'LUA'})
     end)
 end)
 
@@ -141,19 +142,21 @@ g.after_test('test_lua_call_func', function(cg)
         box.schema.func.drop('c_func')
         box.schema.func.drop('lua_func')
         box.schema.func.drop('stored_lua_func')
+        box.schema.func.drop('dostring')
     end)
 end)
 
--- Checks that execute privilege granted on lua_call does not grant access to
--- Lua functions from _func.
+-- Checks that execute privilege granted on lua_call grants access to
+-- Lua functions registered in _func except for built-ins and persistent
+-- functions.
 g.test_lua_call_func = function(cg)
     local c = cg.conn
     local errfmt = "Execute access to function '%s' is denied for user 'test'"
-    local func_list = {'c_func', 'lua_func', 'stored_lua_func'}
     cg.grant('test', 'execute', 'lua_call')
-    for _, func in ipairs(func_list) do
+    for _, func in ipairs({'c_func', 'stored_lua_func', 'dostring'}) do
         t.assert_error_msg_equals(errfmt:format(func), c.call, c, func)
     end
+    t.assert(c:call('lua_func'))
 end
 
 -- Checks that execute privilege granted on lua_call does not grant access