File.writable?('/tmp/file') returns true even if it's not writable on Linux 4.19+
Well, on Linux Kernel 4.19+ the fs.protected_regular and fs.protected_fifos sysctls were introduced in order to make some data spoofing attacks harder.
If it's enabled (and it's true by default), then if you:
- cd /tmp
- touch file
- chmod 666 file # Switch to any user, but let's use root for example
- su root
┌┄┄[root::archlinux]┈[/tmp] └──╼⮚ irb irb(main):001:0> File.writable?('ruby.rb') => true irb(main):002:0> File.stat('ruby.rb') => #<File::Stat dev=0x2d, ino=819138, mode=0100644, nlink=1, uid=1000, gid=1000, rdev=0x0, size=0, blksize=4096, blocks=0, atime=2019-07-14 04:44:13 +0530, mtime=2019-07-14 04:44:13 +0530, ctime=2019-07-14 04:44:13 +0530> irb(main):003:0> File.write('ruby.rb', '#!/usr/bin/ruby -w') Traceback (most recent call last): 3: from /root/.irb:351:in `<main>' 2: from (irb):3 1: from (irb):3:in `write' Errno::EACCES (Permission denied @ rb_sysopen - ruby.rb) irb(main):004:0>
Here's a stackoverflow post:
And the same behaviour is seen in editors like nano, vi, atom, geany, code, mousepad editors.
Now as Ruby's File.writable?(str) checks for the permissions, it returns true.
The problem can be solved with
But the issue is that File.writable?('/tmp/file') should return false if fs.protected_regular is 1 and the user is not the owner? of the file if the directory is /tmp/ on Linux.
Updated by akr (Akira Tanaka) 2 months ago
- Status changed from Open to Feedback
eaccess function of OS.
I think such OS-specific features should be implemented in OS.
Ruby cannot support all features of all OS.
For example, eaccess of GNU/Linux seems that support read-only filesystem.
This behavior conflicts the documentation.
So, some documentation update would be considerable.
Updated by znz (Kazuhiro NISHIYAMA) 2 months ago
I think checking permission before writing should be avoided.
It causes https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use.