]> granicus.if.org Git - vim/commitdiff
patch 8.0.1263: others can read the swap file if a user is careless v8.0.1263
authorBram Moolenaar <Bram@vim.org>
Sat, 4 Nov 2017 20:35:01 +0000 (21:35 +0100)
committerBram Moolenaar <Bram@vim.org>
Sat, 4 Nov 2017 20:35:01 +0000 (21:35 +0100)
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.

src/Makefile
src/fileio.c
src/testdir/test_swap.vim
src/version.c

index e55e830ef5f4b1a5eb1659e7b1ed0a136cc22984..48487aad53444252c9bbebeb7e3e4340ace23d34 100644 (file)
@@ -2259,6 +2259,7 @@ test_arglist \
        test_stat \
        test_statusline \
        test_substitute \
+       test_swap \
        test_syn_attr \
        test_syntax \
        test_system \
index 87b85cf38652551a48a84dda7dabe024d1cd6524..34dcdb6b59c288b841216bb8a2b482711b3660fe 100644 (file)
@@ -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
     }
 
index 245e1f18bbdd9060aa82ca5b6d2e4abfe0ab32a6..d11c124d0a5550a815da2f2d58d2db50a5f9de1a 100644 (file)
@@ -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
index b7cb58be4a056b590c38e1f66070605b5f006f14..2a2cefe3d1c802ebb94b41cded2a21261edbe241 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1263,
 /**/
     1262,
 /**/