For testing purposes I set the setuid to my vim binary. Now when I open for example /etc/passwd, modify the file and execute :w, then I get the E45: 'readonly' option is set (add ! to override) error message. However, the :w! saves the changes, i.e it is not a file-system restriction. Based on what rules vim considers certain files as read-only?

  • Do you have write permissions for the file?
    – D. Ben Knoble
    Jun 18, 2019 at 11:52
  • I'm running vim as user root and with :w! I'm able to write the file.
    – Martin
    Jun 18, 2019 at 12:19
  • Ok, well, does root have write permission?
    – D. Ben Knoble
    Jun 18, 2019 at 13:19
  • Yes. And as I wrote, with :w! I'm able to save my changes to the file, i.e file system permissions allow root user to change the file.
    – Martin
    Jun 18, 2019 at 13:30

1 Answer 1


Based on a quick experiment:

# touch readonly
# chmod a-w readonly

Now, vim readonly will start in readonly mode, because the current user does not have write permission. But, as root or as a regular user (file owner only? untested with other regular users), w! can bypass this.

Also, from the help, vim will start with 'readonly' set if

  • vim starts with the -R flag
  • the executable is named view

When using ":w!" the 'readonly' option is reset for the current buffer, unless the 'Z' flag is in 'cpoptions'. When using the ":view" command the 'readonly' option is set for the newly edited buffer. (:h 'readonly')

  • 1
    That's odd, because /etc/passwd has w for user root: -rw-r--r-- 1 root root 1571 May 8 13:19 /etc/passwd. I guess it has nothing to do with vim, but rather how Linux executes the setuid binaries.
    – Martin
    Jun 19, 2019 at 11:01
  • 2
    @Martin a setuid binary will execute with an EUID ("effective" UID) of root (or the user that owns the binary), but still an UID ("real" UID) of your user. Functions to explicitly check for access (access(2)) typically use the real UID. A setuid process that wants to actually run as root will typically execute setreuid(geteuid()): to reset the real UID appropriately. Hope that helps!
    – filbranden
    Jun 19, 2019 at 23:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.