Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vim can't edit non-group-writable on GVFS SSH mounts #5237

Open
interfect opened this issue Nov 17, 2019 · 10 comments
Open

vim can't edit non-group-writable on GVFS SSH mounts #5237

interfect opened this issue Nov 17, 2019 · 10 comments

Comments

@interfect
Copy link

interfect commented Nov 17, 2019

Describe the bug
Somewhere between Vim 7.4 and Vim 8 (or at least the Vim 8 that Ubuntu ships), the ability to write to files created by Nautilus in directories mounted over Gnome's Virtual File System (GVFS) was lost.

See this Ubuntu bug from a few months ago that nobody noticed:

https://bugs.launchpad.net/ubuntu/+source/vim/+bug/1813679

And see also this Ubuntu bug I went to report again today, having forgotten about the first bug
because nobody ever responded to it:

https://bugs.launchpad.net/ubuntu/+source/vim/+bug/1852927

To Reproduce
Detailed steps to reproduce the behavior:

  1. Open Nautilus, hit Ctrl+L to get the URL bar, and type in "ssh://your.server", and hit enter.
  2. Navigate to a directory.
  3. Create a file through Nautilus (Right-click -> New Document -> New Text Document). (You may need to touch ~/Templates/New\ Text\ Document.txt if you don't have one.
  4. Open the document with gvim.
  5. Edit it.
  6. Try to save it.

Expected behavior
The document should save.

Screenshots
Instead I get an error like this:

"/run/user/1000/gvfs/sftp:host=your.server/path/to/your/file.txt: E212: Can't open file for writing"

Environment (please complete the following information):

  • Vim version:
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jun 06 2019 17:31:41)
Included patches: 1-1453
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by pkg-vim-maintainers@lists.alioth.debian.org
Huge version with GTK2 GUI.  Features included (+) or not (-):
+acl               +farsi             +mouse_sgr         -tag_any_white
+arabic            +file_in_path      -mouse_sysmouse    +tcl
+autocmd           +find_in_path      +mouse_urxvt       +termguicolors
-autoservername    +float             +mouse_xterm       +terminal
+balloon_eval      +folding           +multi_byte        +terminfo
+balloon_eval_term -footer            +multi_lang        +termresponse
+browse            +fork()            -mzscheme          +textobjects
++builtin_terms    +gettext           +netbeans_intg     +timers
+byte_offset       -hangul_input      +num64             +title
+channel           +iconv             +packages          +toolbar
+cindent           +insert_expand     +path_extra        +user_commands
+clientserver      +job               +perl              +vertsplit
+clipboard         +jumplist          +persistent_undo   +virtualedit
+cmdline_compl     +keymap            +postscript        +visual
+cmdline_hist      +lambda            +printer           +visualextra
+cmdline_info      +langmap           +profile           +viminfo
+comments          +libcall           -python            +vreplace
+conceal           +linebreak         +python3           +wildignore
+cryptv            +lispindent        +quickfix          +wildmenu
+cscope            +listcmds          +reltime           +windows
+cursorbind        +localmap          +rightleft         +writebackup
+cursorshape       +lua               +ruby              +X11
+dialog_con_gui    +menu              +scrollbind        -xfontset
+diff              +mksession         +signs             +xim
+digraphs          +modify_fname      +smartindent       +xpm
+dnd               +mouse             +startuptime       +xsmp_interact
-ebcdic            +mouseshape        +statusline        +xterm_clipboard
+emacs_tags        +mouse_dec         -sun_workshop      -xterm_save
+eval              +mouse_gpm         +syntax            
+ex_extra          -mouse_jsbterm     +tag_binary        
+extra_search      +mouse_netterm     +tag_old_static    
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "$VIM/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK  -pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/freetype2 -I/usr/include/libpng16 -Wdate-time  -g -O2 -fdebug-prefix-map=/build/vim-8l5tlu/vim-8.0.1453=. -fstack-protector-strong -Wformat -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fstack-protector -rdynamic -Wl,-export-dynamic -Wl,-E  -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim   -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype -lSM -lICE -lXpm -lXt -lX11 -lXdmcp -lSM -lICE  -lm -ltinfo -lnsl  -lselinux  -lacl -lattr -lgpm -ldl  -L/usr/lib -llua5.2 -Wl,-E  -fstack-protector-strong -L/usr/local/lib  -L/usr/lib/x86_64-linux-gnu/perl/5.26/CORE -lperl -ldl -lm -lpthread -lcrypt  -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -lpython3.6m -lpthread -ldl -lutil -lm -L/usr/lib/x86_64-linux-gnu -ltcl8.6 -ldl -lz -lpthread -lm -lruby-2.5 -lpthread -lgmp -ldl -lcrypt -lm     
  • OS: Ubuntu 18.04
  • Terminal: GUI

Additional context
Weirdly, this only seems to affect files created by Nautilus. Files creaded by opening a terminsl, cd-ing into /run/user/1000/gvfs/sftp:host=your.server/path/to/your/ and touch-ing file2.txt don't have this problem.

This also only seems to affect Vim 8+. My build of 7.4.1689 doesn't have this problem. nano does not have this problem.

This affects both CLI vim and GUI gvim.

@chrisbra
Copy link
Member

chrisbra commented Nov 17, 2019 via email

@interfect
Copy link
Author

OK, I think I have the commit, and I have a much easier way to reproduce the problem.

My Nautilus's text document template has 644 permissions (not group writable), while my regular umask has me creating files with 664 permissions (group writable). When Vim tries to save a file that is not group writable over a GVFS SSH mount, it fails, even if the file is owned and writable by the user you are doing the SSH mount as.

I ran a bisect and it looks like cd142e3 is the offending commit:

commit cd142e3369db8888163a511dbe9907bcd138829c
Author: Bram Moolenaar <Bram@vim.org>
Date:   Thu Nov 16 17:03:45 2017 +0100

    patch 8.0.1300: file permissions may end up wrong when writing
    
    Problem:    File permissions may end up wrong when writing.
    Solution:   Use fchmod() instead of chmod() when possible.  Don't truncate
                until we know we can change the file.

:040000 040000 f35da0fa4253b2bc17eacf9a918f309ca4550632 11b204f3188c1046c35d52661a8853d2298fc99a M	src

@interfect interfect changed the title vim can't edit files created by Nautilus on GVFS SSH mounts vim can't edit non-group-writable on GVFS SSH mounts Nov 19, 2019
@interfect
Copy link
Author

The only thing I can think of is that that commit adds some calls to umask, which isn't respected for files in GVFS SSH mounts. The remote machine's umask is always used instead.

@brammool
Copy link
Contributor

brammool commented Nov 19, 2019 via email

@interfect
Copy link
Author

I can't tell if the write is really failing, or why it is failing, or if the code is bailing out for some other reason. Is there something I can put in there instead of printfs to trace things?

My user umask on the local machine is 0022, and on the remote machine it's 0002. The offending commit adds some calls to umask which I don't quite understand what they're for, but if any logic depends on the set umask actually taking effect, it won't work, because the local/process umask isn't respected when making files on a GVFS SSH mount.

@kuraga
Copy link

kuraga commented Dec 4, 2019

Seems like the same issue (#5309) if file has eXecute chmod enabled. And sometimes else, so I'm even not sure...

@interfect
Copy link
Author

I think #5309 is indeed a dupe of this. The workaround of set backupcopy=no allows me to save properly when I couldn't before.

Is that a clue for how to fix this? What part of cd142e3 is bypassed by that setting?

@kuraga
Copy link

kuraga commented May 18, 2020

Any news on this?

@interfect
Copy link
Author

I'm still tooling along with the set backupcopy=no workaround in my .vimrc. I'm pretty sure cd142e3 caused the problem, but I don't understand how, so I'm not sure how to construct a fix that isn't just a revert of cd142e3, which would reintroduce the bug it fixed.

@kro-cat
Copy link

kro-cat commented Dec 27, 2022

Messing around with the code, seems like the removal of O_TRUNC ( line 4406 in src/fileio.c of cd142e3 ) causes this issue on FUSE GVFS.

Without actually diving into it, I can only say that I think this has something to do with the way open() interacts with FUSE in the kernel - it only works when we have either O_TRUNC or O_APPEND set. I'm pretty confident this isn't an issue with the commit itself, just that it exposed some weirdness in the kernel.

Changing line 4390 in src/fileio.c of this specific commit actually resolves the issue for me:

#ifdef HAVE_FTRUNCATE
- # define TRUNC_ON_OPEN 0
+ # define TRUNC_ON_OPEN O_APPEND
#else
# define TRUNC_ON_OPEN O_TRUNC
#endif

No guarantees on the legitimacy or security of that, though.

--
Edit Dec. 28, 2022:

I've been getting into the weeds on this. I've ruled out the Linux Kernel (open() syscall), FUSE, and GVFS / GIO. I've only verified this issue on Thunar/Nautilus-mounted GVFS so far. My running suspicion is how those programs actually set up the mount. Setting up a mount manually (via the gio program) seems to not have this issue.

I'm pretty positive this isn't a vim issue, but it's definitely interesting that we can work around it.

For now, I'll just set up the sftp mounts manually b/c that's a better solution for me.

--
Edit Dec. 29, 2022:

I found the following issues in gvfs, whose solutions resolve this issue:

NixOS/nixpkgs#50254

https://gitlab.gnome.org/GNOME/gvfs/-/issues/370

I get that these issues aren't exactly describing the behavior here, but restarting/stopping the gvfs-daemon in userspace suddenly had things working again (for a little bit).

Judging by this issue:

https://gitlab.gnome.org/GNOME/gvfs/-/issues/249

It appears the correct workaround is to open with O_TRUNC or O_APPEND until the O_WRONLY and O_RDWR operations are fully supported.

I'm not going to spend much more time on this, but I hope this helps anyone who stumbles upon this like I have.

kro-cat added a commit to kro-cat/vim that referenced this issue Dec 29, 2022
Problem: open() may fail with EOPNOTSUPP in linux if opening a file
in a gvfs-fuse mount with O_WRONLY or O_RDWR when neither O_TRUNC nor
O_APPEND is set;
This is a known issue:
[GNOME/gvfs#249](https://gitlab.gnome.org/GNOME/gvfs/-/issues/249)

Solution: Open a file with O_APPEND when not specifically overwriting or
truncating. Memfile functions may still be affected by this bug, sorry.

Closes: vim#5237
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants