File.readable? and /proc

root@nail:/projects/proc_fs# uname -a
Linux lian 2.6.32-44-generic #98-Ubuntu SMP Mon Sep 24 17:27:10 UTC 2012
x86_64 GNU/Linux

root@nail:/projects/proc_fs# ruby -v
ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-linux]

root@nail:/projects/proc_fs# ls -al /proc/sys/fs/binfmt_misc/register
–w------- 1 root root 0 2012-10-28 08:24
/proc/sys/fs/binfmt_misc/register

root@nail:/projects/proc_fs# irb

irb(main):001:0> File.readable? ‘/proc/sys/fs/binfmt_misc/register’
=> true

!?!?!?

Jeff M. wrote in post #1081705:

root@nail:/projects/proc_fs# irb

irb(main):001:0> File.readable? ‘/proc/sys/fs/binfmt_misc/register’
=> true

!?!?!?

You are loggeg in as ‘root’! Ruby is obviously aware of your superuser
privileges. Run irb as regular user and, you’ll see false!

Cheers, igor

Normally proc files are either read-only or read-write. I had to look
this up since I have not had to use this before.

register is owned by root on my system
–w------- 1 root root 0 Oct 24 14:49 register

found this in kernel doc’s
“To actually register a new binary type, you have to set up a string
looking like
:name:type:offset:magic:mask:interpreter:flags (where you can choose
the ‘:’ upon
your needs) and echo it to /proc/sys/fs/binfmt_misc/register.”

echo
‘:i386:M::\x7fELF\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff’

/proc/sys/fs/binfmt_misc/register

So it makes sense that you can write or read to it as root.
Do you get a different result as a non-root user?

take care,
Brad

Igor P. wrote in post #1081710:

Jeff M. wrote in post #1081705:

root@nail:/projects/proc_fs# irb

irb(main):001:0> File.readable? ‘/proc/sys/fs/binfmt_misc/register’
=> true

!?!?!?

You are loggeg in as ‘root’! Ruby is obviously aware of your superuser
privileges. Run irb as regular user and, you’ll see false!

Cheers, igor

It’s the inconsistency with:

root@nail:/projects/proc_fs# ls -al /proc/sys/fs/binfmt_misc/register
–w------- 1 root root 0 2012-10-28 08:24
/proc/sys/fs/binfmt_misc/register

that I find mostly surprising.

Brad Smith wrote in post #1081711:

So it makes sense that you can write or read to it as root.
Do you get a different result as a non-root user?

take care,
Brad

As I mentioned to Igor, the inconsistency between File.readable? and the
output of ‘ls -al’ when they are both executed as root that I find
surprising.

When executing as non-root, this file (and several others) are
unreadable (as expected). That doesn’t concern me.

Jeff M. wrote in post #1081712:

It’s the inconsistency with:

root@nail:/projects/proc_fs# ls -al /proc/sys/fs/binfmt_misc/register
–w------- 1 root root 0 2012-10-28 08:24
/proc/sys/fs/binfmt_misc/register

that I find mostly surprising.

Well, that’s how Unix works. I have two objections:

(1) You should not be using superuser account for regular work!
(2) You have no business running irb in /proc filesystem!

If you do either of these things, you better not be surprised, ever!

Igor P. wrote in post #1081714:

Jeff M. wrote in post #1081712:

It’s the inconsistency with:

root@nail:/projects/proc_fs# ls -al /proc/sys/fs/binfmt_misc/register
–w------- 1 root root 0 2012-10-28 08:24
/proc/sys/fs/binfmt_misc/register

that I find mostly surprising.

Well, that’s how Unix works. I have two objections:

(1) You should not be using superuser account for regular work!
(2) You have no business running irb in /proc filesystem!

If you do either of these things, you better not be surprised, ever!

And if you ‘regular work’ involves interrogating the /proc file system,
then what?

Igor P. wrote in post #1081717:

Jeff M. wrote in post #1081715:

And if you ‘regular work’ involves interrogating the /proc file system,
then what?

Then you better are not surprised when such things happen, or go first
to your $HOME/tmp or similar and acquaint yourself with the way your
brand of OS works, before you show up as ‘root’ in protected system
environments such as /proc

Regards

  1. None of this was run ‘in /proc filesystem’. Note the prompts.

  2. I don’t give fig for you or your objections. I’m looking for
    an explanation of the behavior. It’s clear you can offer nothing
    constructive so silence would be an obvious choice.

  3. Anyone else have some insight?

Jeff M. wrote in post #1081719:

  1. None of this was run ‘in /proc filesystem’. Note the prompts.

Clearly, you do not understand that running the following as root:

irb(main):001:0> File.readable? ‘/proc/sys/fs/binfmt_misc/register’

is the same, as being in /proc as root.

I don’t know what’s your problem beside your surprise! I also don’t give
a rats ass, how you are treating your systems. You asked a question, got
an answer and continue to be surprised with the facts!

So long,
igor

On 10/29/2012 09:18 AM, Jeff M. wrote:

Well, that’s how Unix works. I have two objections:

(1) You should not be using superuser account for regular work!
(2) You have no business running irb in /proc filesystem!

If you do either of these things, you better not be surprised, ever!
And if you ‘regular work’ involves interrogating the /proc file system,
then what?

You could use something like this? You’d need to flesh out some error/
input handling, and these constants (sadly not exposed by ruby that I
can find) will be platform specific. I think the ‘problem’ is that root
can do pretty much anything it wants (make a file owned root:root, chmod
000, and enjoy echo’ing stuff into it). The stdlib seems to use
‘eaccess( path, R_OK )’ which I guess gives a 0 for euid 0.

require ‘etc’
S_IFMT = 0170000
S_IFLNK 0120000
S_IRUSR = 00400
S_IRGRP = 00040
S_IROTH = 00004

def readable?( path, follow=false )
st = File.lstat( path )
if follow && ( S_IFLNK == ( st.mode & S_IFMT ) )
st = File.stat( path )
end
uid = Process.euid
if ( st.mode & S_IROTH ) > 0
print ‘Other read’
true
elsif( ( ( st.mode & S_IRUSR ) > 0 ) && ( st.uid == uid ) )
print ‘Owner read’
true
elsif ( st.mode & S_IRGRP ) > 0
username = Etc.getpwuid( uid ).name
if Etc.getgrgid( st.gid ).mem.include?( username )
print ‘Group read’
true
else
false
end
else
false
end
end

Sam

Jeff M. wrote in post #1081715:

And if you ‘regular work’ involves interrogating the /proc file system,
then what?

Then you better are not surprised when such things happen, or go first
to your $HOME/tmp or similar and acquaint yourself with the way your
brand of OS works, before you show up as ‘root’ in protected system
environments such as /proc

Regards

On Oct 28, 2012, at 13:00 , Jeff M. [email protected] wrote:

It’s the inconsistency with:

root@nail:/projects/proc_fs# ls -al /proc/sys/fs/binfmt_misc/register
–w------- 1 root root 0 2012-10-28 08:24
/proc/sys/fs/binfmt_misc/register

that I find mostly surprising.

Yeah. But that’s just how root works and is both a blessing and a curse.

10000 % sudo bash
9999 % echo “blah” > blah.txt
10000 % chmod 000 blah.txt
10001 % ll blah.txt
---------- 1 root staff 5 Oct 28 14:54 blah.txt
10002 % cat blah.txt
blah
10003 % ruby -e ‘p File.readable? “blah.txt”’
true
10004 % exit
10001 % ruby -e ‘p File.readable? “blah.txt”’
false

So, while ls tells you the attributes on the file, root overrides all.
If you made something that root couldn’t get to / change / rm / read
then you’d wind up with a really wonky system. For example, instant DOS:

while true ; do
F=$$.$(date +%s)
dd if=/dev/zero of=$F bs=1g count=1
chmod 0 $F
done

Sam D. wrote in post #1081722:

On 10/29/2012 09:18 AM, Jeff M. wrote:

Well, that’s how Unix works. I have two objections:

(1) You should not be using superuser account for regular work!
(2) You have no business running irb in /proc filesystem!

If you do either of these things, you better not be surprised, ever!
And if you ‘regular work’ involves interrogating the /proc file system,
then what?

You could use something like this? You’d need to flesh out some error/
input handling, and these constants (sadly not exposed by ruby that I
can find) will be platform specific. I think the ‘problem’ is that root
can do pretty much anything it wants (make a file owned root:root, chmod
000, and enjoy echo’ing stuff into it). The stdlib seems to use
‘eaccess( path, R_OK )’ which I guess gives a 0 for euid 0.

require ‘etc’
S_IFMT = 0170000
S_IFLNK 0120000
S_IRUSR = 00400
S_IRGRP = 00040
S_IROTH = 00004

def readable?( path, follow=false )
st = File.lstat( path )
if follow && ( S_IFLNK == ( st.mode & S_IFMT ) )
st = File.stat( path )
end
uid = Process.euid
if ( st.mode & S_IROTH ) > 0
print ‘Other read’
true
elsif( ( ( st.mode & S_IRUSR ) > 0 ) && ( st.uid == uid ) )
print ‘Owner read’
true
elsif ( st.mode & S_IRGRP ) > 0
username = Etc.getpwuid( uid ).name
if Etc.getgrgid( st.gid ).mem.include?( username )
print ‘Group read’
true
else
false
end
else
false
end
end

Sam

Sam, Thanks for this.

It wasn’t exactly what I expected but it focused on all the right issues
and that has lead to a conclusion.

As you pointed out, eaccess is the key.

If the stdlib implements eaccess with the same behavior as the
implementation in file.c (line 1034), root is simply granted
read and write permission without ever hitting stat.

‘ls -al’, on the other hand, relies on stat.