Project

General

Profile

Actions

Bug #16002

closed

File.writable?('/tmp/file') returns true even if it's not writable on Linux 4.19+

Added by SouravGoswami (Sourav Goswami) over 4 years ago. Updated over 4 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]
[ruby-core:93764]

Description

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.

https://github.com/systemd/systemd/blob/03b6fa0c5b51b0d39334ff6ba183a3391443bcf6/NEWS#L53

If it's enabled (and it's true by default), then if you:

  1. cd /tmp
  2. touch file
  3. chmod 666 file

Switch to any user, but let's use root for example

  1. su root
  2. irb

In irb:

┌┄┄[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> 

Screenshots:
https://imgur.com/tB4T5Jl
https://imgur.com/hzc5s27

Here's a stackoverflow post:
https://stackoverflow.com/a/57030460/11089758

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 sysctl fs.protected_regular=0.

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.

Actions #1

Updated by SouravGoswami (Sourav Goswami) over 4 years ago

  • Description updated (diff)
Actions #2

Updated by SouravGoswami (Sourav Goswami) over 4 years ago

  • ruby -v changed from 2.6.3 to ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

Updated by akr (Akira Tanaka) over 4 years ago

  • Status changed from Open to Feedback

File.writable? uses 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) over 4 years ago

I think checking permission before writing should be avoided.
It causes https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use.

Actions #5

Updated by jeremyevans (Jeremy Evans) over 4 years ago

  • Status changed from Feedback to Closed

Applied in changeset git|978276a7d9249535f855088f866551b6557f321f.


Update documentation for File#{readable,writable,executable}{,_real}? [ci skip]

Some OS-level security features cause these methods to not return
expected results. For example fs.protected_regular sysctl on Linux,
or pledge(2)/unveil(2) on OpenBSD.

Fixes [Bug #16002]

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0