Merge pull request #11996 from georg3tom/remove_restricted

Removed restricted mode - Fix #11972
This commit is contained in:
Björn Linse 2020-11-11 19:39:08 +01:00 committed by GitHub
commit 4875db2e56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 55 additions and 200 deletions

View File

@ -973,7 +973,7 @@ name). This is included for backwards compatibility with version 3.0, the
Note: Where a file name is expected wildcards expansion is done. On Unix the Note: Where a file name is expected wildcards expansion is done. On Unix the
shell is used for this, unless it can be done internally (for speed). shell is used for this, unless it can be done internally (for speed).
Unless in |restricted-mode|, backticks work also, like in > Backticks work also, like in >
:n `echo *.c` :n `echo *.c`
But expansion is only done if there are any wildcards before expanding the But expansion is only done if there are any wildcards before expanding the
'%', '#', etc.. This avoids expanding wildcards inside a file name. If you '%', '#', etc.. This avoids expanding wildcards inside a file name. If you

View File

@ -20,8 +20,8 @@ additionally sets up for viewing the differences between the arguments. >
nvim -d file1 file2 [file3 [file4]] nvim -d file1 file2 [file3 [file4]]
In addition to the |-d| argument, |-Z| and |-R| may be used for restricted In addition to the |-d| argument, |-R| may be used for readonly mode
mode and readonly mode respectively. respectively.
The second and following arguments may also be a directory name. Vim will The second and following arguments may also be a directory name. Vim will
then append the file name of the first argument to the directory name to find then append the file name of the first argument to the directory name to find

View File

@ -5698,7 +5698,6 @@ libcall({libname}, {funcname}, {argument})
If {argument} is a number, it is passed to the function as an If {argument} is a number, it is passed to the function as an
int; if {argument} is a string, it is passed as a int; if {argument} is a string, it is passed as a
null-terminated string. null-terminated string.
This function will fail in |restricted-mode|.
libcall() allows you to write your own 'plug-in' extensions to libcall() allows you to write your own 'plug-in' extensions to
Vim without having to recompile the program. It is NOT a Vim without having to recompile the program. It is NOT a
@ -8804,7 +8803,6 @@ system({cmd} [, {input}]) *system()* *E677*
{cmd} is a string: 'shell' 'shellcmdflag' {cmd} {cmd} is a string: 'shell' 'shellcmdflag' {cmd}
The resulting error code can be found in |v:shell_error|. The resulting error code can be found in |v:shell_error|.
This function will fail in |restricted-mode|.
Note that any wrong value in the options mentioned above may Note that any wrong value in the options mentioned above may
make the function fail. It has also been reported to fail make the function fail. It has also been reported to fail

View File

@ -185,18 +185,6 @@ argument.
the 'modifiable' and 'write' options can be set to enable the 'modifiable' and 'write' options can be set to enable
changes and writing. changes and writing.
*-Z* *restricted-mode* *E145* *E981*
-Z Restricted mode. All commands that make use of an external
shell are disabled. This includes suspending with CTRL-Z,
":sh", filtering, the system() function, backtick expansion
and libcall().
Also disallowed are delete(), rename(), mkdir(), jobstart(),
etc.
Interfaces, such as Python, Ruby and Lua, are also disabled,
since they could be used to execute shell commands.
Note that the user may still find a loophole to execute a
shell command, it has only been made difficult.
-e *-e* *-E* -e *-e* *-E*
-E Start Nvim in Ex mode |gQ|. -E Start Nvim in Ex mode |gQ|.

View File

@ -7152,7 +7152,7 @@ void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv,
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -10418,7 +10418,7 @@ Channel *find_job(uint64_t id, bool show_error)
void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) void script_host_eval(char *name, typval_T *argvars, typval_T *rettv)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }

View File

@ -205,7 +205,7 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -862,7 +862,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -901,7 +901,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -1480,7 +1480,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -1515,7 +1515,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// dictwatcheradd(dict, key, funcref) function // dictwatcheradd(dict, key, funcref) function
static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -1553,7 +1553,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// dictwatcherdel(dict, key, funcref) function // dictwatcherdel(dict, key, funcref) function
static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -4798,7 +4798,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -4822,7 +4822,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -4855,7 +4855,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -4988,7 +4988,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -5021,7 +5021,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER if (argvars[0].v_type != VAR_LIST || (argvars[1].v_type != VAR_NUMBER
@ -5239,7 +5239,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type)
rettv->vval.v_string = NULL; rettv->vval.v_string = NULL;
} }
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -5942,8 +5942,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr)
int prot = 0755; // -V536 int prot = 0755; // -V536
rettv->vval.v_number = FAIL; rettv->vval.v_number = FAIL;
if (check_restricted() || check_secure()) if (check_secure()) {
return; return;
}
char buf[NUMBUFLEN]; char buf[NUMBUFLEN];
const char *const dir = tv_get_string_buf(&argvars[0], buf); const char *const dir = tv_get_string_buf(&argvars[0], buf);
@ -6832,7 +6833,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/ */
static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
rettv->vval.v_number = -1; rettv->vval.v_number = -1;
} else { } else {
char buf[NUMBUFLEN]; char buf[NUMBUFLEN];
@ -7230,7 +7231,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -7266,7 +7267,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
const int l_provider_call_nesting = provider_call_nesting; const int l_provider_call_nesting = provider_call_nesting;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -7363,7 +7364,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -7429,7 +7430,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_NUMBER; rettv->v_type = VAR_NUMBER;
rettv->vval.v_number = 0; rettv->vval.v_number = 0;
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -7891,7 +7892,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->v_type = VAR_STRING; rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL; // Address of the new server rettv->vval.v_string = NULL; // Address of the new server
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -7933,7 +7934,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr)
/// "serverstop()" function /// "serverstop()" function
static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }
@ -10466,7 +10467,7 @@ static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
// "termopen(cmd[, cwd])" function // "termopen(cmd[, cwd])" function
static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
return; return;
} }

View File

@ -1049,13 +1049,13 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out)
int len; int len;
int scroll_save = msg_scroll; int scroll_save = msg_scroll;
/* //
* Disallow shell commands in restricted mode (-Z) // Disallow shell commands from .exrc and .vimrc in current directory for
* Disallow shell commands from .exrc and .vimrc in current directory for // security reasons.
* security reasons. //
*/ if (check_secure()) {
if (check_restricted() || check_secure())
return; return;
}
if (addr_count == 0) { /* :! */ if (addr_count == 0) { /* :! */
msg_scroll = FALSE; /* don't scroll here */ msg_scroll = FALSE; /* don't scroll here */
@ -1383,10 +1383,9 @@ do_shell(
int flags // may be SHELL_DOOUT when output is redirected int flags // may be SHELL_DOOUT when output is redirected
) )
{ {
// Disallow shell commands in restricted mode (-Z)
// Disallow shell commands from .exrc and .vimrc in current directory for // Disallow shell commands from .exrc and .vimrc in current directory for
// security reasons. // security reasons.
if (check_restricted() || check_secure()) { if (check_secure()) {
msg_end(); msg_end();
return; return;
} }
@ -3030,20 +3029,6 @@ void ex_z(exarg_T *eap)
ex_no_reprint = true; ex_no_reprint = true;
} }
// Check if the restricted flag is set.
// If so, give an error message and return true.
// Otherwise, return false.
bool check_restricted(void)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (restricted) {
EMSG(_("E145: Shell commands and some functionality not allowed"
" in restricted mode"));
return true;
}
return false;
}
/* /*
* Check if the secure flag is set (.exrc or .vimrc in current directory). * Check if the secure flag is set (.exrc or .vimrc in current directory).
* If so, give an error message and return TRUE. * If so, give an error message and return TRUE.

View File

@ -62,7 +62,6 @@
// curbuf_lock is set // curbuf_lock is set
#define MODIFY 0x200000 // forbidden in non-'modifiable' buffer #define MODIFY 0x200000 // forbidden in non-'modifiable' buffer
#define EXFLAGS 0x400000 // allow flags after count in argument #define EXFLAGS 0x400000 // allow flags after count in argument
#define RESTRICT 0x800000L // forbidden in restricted mode
#define FILES (XFILE | EXTRA) // multiple extra files allowed #define FILES (XFILE | EXTRA) // multiple extra files allowed
#define WORD1 (EXTRA | NOSPC) // one extra word allowed #define WORD1 (EXTRA | NOSPC) // one extra word allowed
#define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file #define FILE1 (FILES | NOSPC) // 1 file allowed, defaults to current file

View File

@ -1503,10 +1503,6 @@ static char_u * do_one_cmd(char_u **cmdlinep,
errormsg = (char_u *)_(e_sandbox); errormsg = (char_u *)_(e_sandbox);
goto doend; goto doend;
} }
if (restricted != 0 && (ea.argt & RESTRICT)) {
errormsg = (char_u *)_("E981: Command not allowed in restricted mode");
goto doend;
}
if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY) if (!MODIFIABLE(curbuf) && (ea.argt & MODIFY)
// allow :put in terminals // allow :put in terminals
&& (!curbuf->terminal || ea.cmdidx != CMD_put)) { && (!curbuf->terminal || ea.cmdidx != CMD_put)) {
@ -6624,8 +6620,6 @@ static void ex_hide(exarg_T *eap)
/// ":stop" and ":suspend": Suspend Vim. /// ":stop" and ":suspend": Suspend Vim.
static void ex_stop(exarg_T *eap) static void ex_stop(exarg_T *eap)
{ {
// Disallow suspending in restricted mode (-Z)
if (!check_restricted()) {
if (!eap->forceit) { if (!eap->forceit) {
autowrite_all(); autowrite_all();
} }
@ -6643,7 +6637,6 @@ static void ex_stop(exarg_T *eap)
ui_refresh(); // may have resized window ui_refresh(); // may have resized window
apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL); apply_autocmds(EVENT_VIMRESUME, NULL, NULL, false, NULL);
} }
}
// ":exit", ":xit" and ":wq": Write file and quite the current window. // ":exit", ":xit" and ":wq": Write file and quite the current window.
static void ex_exit(exarg_T *eap) static void ex_exit(exarg_T *eap)

View File

@ -492,9 +492,6 @@ EXTERN int stdout_isatty INIT(= true);
// volatile because it is used in a signal handler. // volatile because it is used in a signal handler.
EXTERN volatile int full_screen INIT(= false); EXTERN volatile int full_screen INIT(= false);
// When started in restricted mode (-Z).
EXTERN int restricted INIT(= false);
/// Non-zero when only "safe" commands are allowed, e.g. when sourcing .exrc or /// Non-zero when only "safe" commands are allowed, e.g. when sourcing .exrc or
/// .vimrc in current directory. /// .vimrc in current directory.
EXTERN int secure INIT(= false); EXTERN int secure INIT(= false);

View File

@ -965,7 +965,7 @@ static void typval_exec_lua(const char *lcmd, size_t lcmd_len, const char *name,
typval_T *const args, int argcount, bool special, typval_T *const args, int argcount, bool special,
typval_T *ret_tv) typval_T *ret_tv)
{ {
if (check_restricted() || check_secure()) { if (check_secure()) {
if (ret_tv) { if (ret_tv) {
ret_tv->v_type = VAR_NUMBER; ret_tv->v_type = VAR_NUMBER;
ret_tv->vval.v_number = 0; ret_tv->vval.v_number = 0;

View File

@ -1012,10 +1012,6 @@ static void command_line_scan(mparm_T *parmp)
want_argument = true; want_argument = true;
break; break;
} }
case 'Z': { // "-Z" restricted mode
restricted = true;
break;
}
case 'c': { // "-c{command}" or "-c {command}" exec command case 'c': { // "-c{command}" or "-c {command}" exec command
if (argv[0][argv_idx] != NUL) { if (argv[0][argv_idx] != NUL) {

View File

@ -1091,8 +1091,9 @@ char_u *get_cmd_output(char_u *cmd, char_u *infile, ShellOpts flags,
{ {
char_u *buffer = NULL; char_u *buffer = NULL;
if (check_restricted() || check_secure()) if (check_secure()) {
return NULL; return NULL;
}
// get a name for the temp file // get a name for the temp file
char_u *tempname = vim_tempname(); char_u *tempname = vim_tempname();

View File

@ -150,11 +150,11 @@ int os_expand_wildcards(int num_pat, char_u **pat, int *num_file,
return FAIL; return FAIL;
} }
// Don't allow the use of backticks in secure and restricted mode. // Don't allow the use of backticks in secure.
if (secure || restricted) { if (secure) {
for (i = 0; i < num_pat; i++) { for (i = 0; i < num_pat; i++) {
if (vim_strchr(pat[i], '`') != NULL if (vim_strchr(pat[i], '`') != NULL
&& (check_restricted() || check_secure())) { && (check_secure())) {
return FAIL; return FAIL;
} }
} }

View File

@ -1,103 +0,0 @@
" Test for "rvim" or "vim -Z"
source shared.vim
"if has('win32') && has('gui')
" " Win32 GUI shows a dialog instead of displaying the error in the last line.
" finish
"endif
func Test_restricted()
call Run_restricted_test('!ls', 'E145:')
endfunc
func Run_restricted_test(ex_cmd, error)
let cmd = GetVimCommand('Xrestricted')
if cmd == ''
return
endif
" Use a VimEnter autocommand to avoid that the error message is displayed in
" a dialog with an OK button.
call writefile([
\ "func Init()",
\ " silent! " . a:ex_cmd,
\ " call writefile([v:errmsg], 'Xrestrout')",
\ " qa!",
\ "endfunc",
\ "au VimEnter * call Init()",
\ ], 'Xrestricted')
call system(cmd . ' -Z')
call assert_match(a:error, join(readfile('Xrestrout')))
call delete('Xrestricted')
call delete('Xrestrout')
endfunc
func Test_restricted_lua()
if !has('lua')
throw 'Skipped: Lua is not supported'
endif
call Run_restricted_test('lua print("Hello, Vim!")', 'E981:')
call Run_restricted_test('luado return "hello"', 'E981:')
call Run_restricted_test('luafile somefile', 'E981:')
call Run_restricted_test('call luaeval("expression")', 'E145:')
endfunc
func Test_restricted_mzscheme()
if !has('mzscheme')
throw 'Skipped: MzScheme is not supported'
endif
call Run_restricted_test('mzscheme statement', 'E981:')
call Run_restricted_test('mzfile somefile', 'E981:')
call Run_restricted_test('call mzeval("expression")', 'E145:')
endfunc
func Test_restricted_perl()
if !has('perl')
throw 'Skipped: Perl is not supported'
endif
" TODO: how to make Safe mode fail?
" call Run_restricted_test('perl system("ls")', 'E981:')
" call Run_restricted_test('perldo system("hello")', 'E981:')
" call Run_restricted_test('perlfile somefile', 'E981:')
" call Run_restricted_test('call perleval("system(\"ls\")")', 'E145:')
endfunc
func Test_restricted_python()
if !has('python')
throw 'Skipped: Python is not supported'
endif
call Run_restricted_test('python print "hello"', 'E981:')
call Run_restricted_test('pydo return "hello"', 'E981:')
call Run_restricted_test('pyfile somefile', 'E981:')
call Run_restricted_test('call pyeval("expression")', 'E145:')
endfunc
func Test_restricted_python3()
if !has('python3')
throw 'Skipped: Python3 is not supported'
endif
call Run_restricted_test('py3 print "hello"', 'E981:')
call Run_restricted_test('py3do return "hello"', 'E981:')
call Run_restricted_test('py3file somefile', 'E981:')
call Run_restricted_test('call py3eval("expression")', 'E145:')
endfunc
func Test_restricted_ruby()
if !has('ruby')
throw 'Skipped: Ruby is not supported'
endif
call Run_restricted_test('ruby print "Hello"', 'E981:')
call Run_restricted_test('rubydo print "Hello"', 'E981:')
call Run_restricted_test('rubyfile somefile', 'E981:')
endfunc
func Test_restricted_tcl()
if !has('tcl')
throw 'Skipped: Tcl is not supported'
endif
call Run_restricted_test('tcl puts "Hello"', 'E981:')
call Run_restricted_test('tcldo puts "Hello"', 'E981:')
call Run_restricted_test('tclfile somefile', 'E981:')
endfunc