Mercurial > vim
changeset 12771:8984342ab09e v8.0.1263
patch 8.0.1263: others can read the swap file if a user is careless
commit https://github.com/vim/vim/commit/5a73e0ca54c77e067c3b12ea6f35e3e8681e8cf8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 4 21:35:01 2017 +0100
patch 8.0.1263: others can read the swap file if a user is careless
Problem: Others can read the swap file if a user is careless with his
primary group.
Solution: If the group permission allows for reading but the world
permissions doesn't, make sure the group is right.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 04 Nov 2017 21:45:04 +0100 |
parents | 89889fea43e0 |
children | 4fe368f098c1 |
files | src/Makefile src/fileio.c src/testdir/test_swap.vim src/version.c |
diffstat | 4 files changed, 99 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/src/Makefile +++ b/src/Makefile @@ -2259,6 +2259,7 @@ test_arglist \ test_stat \ test_statusline \ test_substitute \ + test_swap \ test_syn_attr \ test_syntax \ test_system \
--- a/src/fileio.c +++ b/src/fileio.c @@ -716,7 +716,29 @@ readfile( /* Set swap file protection bits after creating it. */ if (swap_mode > 0 && curbuf->b_ml.ml_mfp != NULL && curbuf->b_ml.ml_mfp->mf_fname != NULL) - (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode); + { + char_u *swap_fname = curbuf->b_ml.ml_mfp->mf_fname; + + /* + * If the group-read bit is set but not the world-read bit, then + * the group must be equal to the group of the original file. If + * we can't make that happen then reset the group-read bit. This + * avoids making the swap file readable to more users when the + * primary group of the user is too permissive. + */ + if ((swap_mode & 044) == 040) + { + stat_T swap_st; + + if (mch_stat((char *)swap_fname, &swap_st) >= 0 + && st.st_gid != swap_st.st_gid + && fchown(curbuf->b_ml.ml_mfp->mf_fd, -1, st.st_gid) + == -1) + swap_mode &= 0600; + } + + (void)mch_setperm(swap_fname, (long)swap_mode); + } #endif }
--- a/src/testdir/test_swap.vim +++ b/src/testdir/test_swap.vim @@ -1,48 +1,82 @@ " Tests for the swap feature -" Tests for 'directory' option. -func Test_swap_directory() +"" Tests for 'directory' option. +"func Test_swap_directory() +" if !has("unix") +" return +" endif +" let content = ['start of testfile', +" \ 'line 2 Abcdefghij', +" \ 'line 3 Abcdefghij', +" \ 'end of testfile'] +" call writefile(content, 'Xtest1') +" +" " '.', swap file in the same directory as file +" set dir=.,~ +" +" " Verify that the swap file doesn't exist in the current directory +" call assert_equal([], glob(".Xtest1*.swp", 1, 1, 1)) +" edit Xtest1 +" let swfname = split(execute("swapname"))[0] +" call assert_equal([swfname], glob(swfname, 1, 1, 1)) +" +" " './dir', swap file in a directory relative to the file +" set dir=./Xtest2,.,~ +" +" call mkdir("Xtest2") +" edit Xtest1 +" call assert_equal([], glob(swfname, 1, 1, 1)) +" let swfname = "Xtest2/Xtest1.swp" +" call assert_equal(swfname, split(execute("swapname"))[0]) +" call assert_equal([swfname], glob("Xtest2/*", 1, 1, 1)) +" +" " 'dir', swap file in directory relative to the current dir +" set dir=Xtest.je,~ +" +" call mkdir("Xtest.je") +" call writefile(content, 'Xtest2/Xtest3') +" edit Xtest2/Xtest3 +" call assert_equal(["Xtest2/Xtest3"], glob("Xtest2/*", 1, 1, 1)) +" let swfname = "Xtest.je/Xtest3.swp" +" call assert_equal(swfname, split(execute("swapname"))[0]) +" call assert_equal([swfname], glob("Xtest.je/*", 1, 1, 1)) +" +" set dir& +" call delete("Xtest1") +" call delete("Xtest2", "rf") +" call delete("Xtest.je", "rf") +"endfunc + +func Test_swap_group() if !has("unix") return endif - let content = ['start of testfile', - \ 'line 2 Abcdefghij', - \ 'line 3 Abcdefghij', - \ 'end of testfile'] - call writefile(content, 'Xtest1') - - " '.', swap file in the same directory as file - set dir=.,~ - - " Verify that the swap file doesn't exist in the current directory - call assert_equal([], glob(".Xtest1*.swp", 1, 1, 1)) - edit Xtest1 - let swfname = split(execute("swapname"))[0] - call assert_equal([swfname], glob(swfname, 1, 1, 1)) - - " './dir', swap file in a directory relative to the file - set dir=./Xtest2,.,~ + let groups = split(system('groups')) + if len(groups) <= 1 + throw 'Skipped: need at least two groups, got ' . groups + endif - call mkdir("Xtest2") - edit Xtest1 - call assert_equal([], glob(swfname, 1, 1, 1)) - let swfname = "Xtest2/Xtest1.swp" - call assert_equal(swfname, split(execute("swapname"))[0]) - call assert_equal([swfname], glob("Xtest2/*", 1, 1, 1)) - - " 'dir', swap file in directory relative to the current dir - set dir=Xtest.je,~ + call delete('Xtest') + split Xtest + call setline(1, 'just some text') + wq + if system('ls -l Xtest') !~ ' ' . groups[0] . ' \d' + throw 'Skipped: test file does not have the first group' + else + silent !chmod 640 Xtest + call system('chgrp ' . groups[1] . ' Xtest') + if system('ls -l Xtest') !~ ' ' . groups[1] . ' \d' + throw 'Skipped: cannot set second group on test file' + else + split Xtest + let swapname = substitute(execute('swapname'), '[[:space:]]', '', 'g') + call assert_match('Xtest', swapname) + " Group of swapfile must now match original file. + call assert_match(' ' . groups[1] . ' \d', system('ls -l ' . swapname)) - call mkdir("Xtest.je") - call writefile(content, 'Xtest2/Xtest3') - edit Xtest2/Xtest3 - call assert_equal(["Xtest2/Xtest3"], glob("Xtest2/*", 1, 1, 1)) - let swfname = "Xtest.je/Xtest3.swp" - call assert_equal(swfname, split(execute("swapname"))[0]) - call assert_equal([swfname], glob("Xtest.je/*", 1, 1, 1)) + bwipe! + endif + endif - set dir& - call delete("Xtest1") - call delete("Xtest2", "rf") - call delete("Xtest.je", "rf") + call delete('Xtest') endfunc