summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-11-04 21:35:01 +0100
committerBram Moolenaar <Bram@vim.org>2017-11-04 21:35:01 +0100
commit5a73e0ca54c77e067c3b12ea6f35e3e8681e8cf8 (patch)
tree2e87eb6ea3c404fa035e2aebb00b4fedaeef7263
parent7dd88c5133feda7e9ccfedcb38b6dfdba459d507 (diff)
downloadvim-git-5a73e0ca54c77e067c3b12ea6f35e3e8681e8cf8.tar.gz
patch 8.0.1263: others can read the swap file if a user is carelessv8.0.1263
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.
-rw-r--r--src/Makefile1
-rw-r--r--src/fileio.c24
-rw-r--r--src/testdir/test_swap.vim112
-rw-r--r--src/version.c2
4 files changed, 99 insertions, 40 deletions
diff --git a/src/Makefile b/src/Makefile
index e55e830ef..48487aad5 100644
--- 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 \
diff --git a/src/fileio.c b/src/fileio.c
index 87b85cf38..34dcdb6b5 100644
--- 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
}
diff --git a/src/testdir/test_swap.vim b/src/testdir/test_swap.vim
index 245e1f18b..d11c124d0 100644
--- 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,.,~
-
- 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))
+ let groups = split(system('groups'))
+ if len(groups) <= 1
+ throw 'Skipped: need at least two groups, got ' . groups
+ endif
- " '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
diff --git a/src/version.c b/src/version.c
index b7cb58be4..2a2cefe3d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -762,6 +762,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1263,
+/**/
1262,
/**/
1261,