Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Permission denied" while reading file /proc/<pid>/maps with permissions '-r--r--r--'

9,742 views
Skip to first unread message

Alex Vinokur

unread,
Oct 2, 2012, 10:05:22 AM10/2/12
to
Hi,

Could anybody explain why we have 'Permission denied' here?

Thanks



> uname -a
Linux machine1 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux

> id
uid=75308(user1) gid=100(users) groups=100(users)

> ps -ef | grep 25796
root 25796 15752 0 15:11 pts/30 00:00:00 ssh -l root machine2
user1 26737 13908 0 15:19 pts/23 00:00:00 grep 25796

> ls -ld /proc/25796/maps
-r--r--r-- 1 root root 0 Oct 2 15:12 /proc/25796/maps

> cat /proc/25796/maps
cat: /proc/25796/maps: Permission denied

Richard Kettlewell

unread,
Oct 2, 2012, 10:09:38 AM10/2/12
to
Because there's an extra check built into the kernel to stop you reading
that file without a matching UID or the ptrace capability.

--
http://www.greenend.org.uk/rjk/

Alex Vinokur

unread,
Oct 2, 2012, 10:20:18 AM10/2/12
to
Thanks,

But the file has -r--r--r-- permissions.
So, any process with any effective user may read such a file.

Tauno Voipio

unread,
Oct 2, 2012, 1:14:38 PM10/2/12
to
The 'files' in /proc are no regular files. They are peepholes into the
internals of the kernel. The kernel may impose whatever additional
restrictions it deems fit.

--

Tauno Voipio


Alex Vinokur

unread,
Oct 2, 2012, 1:46:47 PM10/2/12
to
In this case their permissions should be -r-------- or -r--r-----, but not -r--r--r-- (i.e., 0400 or 0440, but not 0444).

Regards,

Alex

Richard Kettlewell

unread,
Oct 2, 2012, 3:08:14 PM10/2/12
to
Alex Vinokur <alex.v...@gmail.com> writes:
> Richard Kettlewell wrote:

>> Because there's an extra check built into the kernel to stop you reading
>> that file without a matching UID or the ptrace capability.
>
> Thanks,
>
> But the file has -r--r--r-- permissions.
> So, any process with any effective user may read such a file.

The permissions aren't the whole story, as stated above.

--
http://www.greenend.org.uk/rjk/

Alan Curry

unread,
Oct 2, 2012, 5:44:28 PM10/2/12
to
In article <874nmcy...@araminta.anjou.terraraq.org.uk>,
The permissions accurately describe who may open the file.

$ strace cat /proc/1/maps
[...]
open("/proc/1/maps", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(3, 0x212c000, 32768) = -1 EACCES (Permission denied)
[...]

With a regular, non-procfs-magic file, if you don't have read permission, the
open will fail. With some of the files in /proc, the open is allowed but the
read fails.

The difference is irrelevant for the simple case of cat where opening,
reading, and closing and/or exiting are done in quick succession. But the
normal permissions rule (check permission on open, not on read) adds some
flexibility: you can open a file for reading and pass the file descriptor to
another process, and then the other process can read it regardless of whether
it would have been able to do the open itself.

Or a file can be opened, then the process can use setuid() to drop the
privileges it needed for the open, and keep it open for later reading.
Somewhere in the middle there may be a fork() and execve() too; as long as
the fd stays alive, the file can still be read.

Someone must have decided that the normal unix permissions check-on-open
was insufficient for /proc (general paranoia, or because there was a
demonstrated attack method involving a read from an inherited file
descriptor). So it does check-on-read.

I can't explain why they didn't also change the permissions to 400 though. It
doesn't seem useful to allow an open if all uses of the fd are going to fail,
and it doesn't seem likely that you'd ever want to open a file, then *gain*
the necessary privileges, then read it. Why not do your privilege-gaining
operation first?

--
Alan Curry

Alex Vinokur

unread,
Oct 3, 2012, 2:16:29 AM10/3/12
to
On Tuesday, October 2, 2012 11:46:11 PM UTC+2, Alan Curry wrote:
[snipped]

Alan, thank you.

Alex

Richard Kettlewell

unread,
Oct 3, 2012, 4:35:03 AM10/3/12
to
pac...@kosh.dhis.org (Alan Curry) writes:
> I can't explain why they didn't also change the permissions to 400
> though.

Same reason as originally stated:

>>>> Because there's an extra check built into the kernel to stop you
>>>> reading that file without a matching UID or the ptrace capability.
^^^^^^^^^^^^^^^^^^^^^^^^

It’s actually a bit more complicated still: the calling process is
always permitted; the reading process has to have a real UID and GID
matching the real, effective and saved UID/GID of the target; the target
must be dumpable; the ptrace capability overrides all of the above; it’s
possible to plug in further policy.

--
http://www.greenend.org.uk/rjk/

Josef Moellers

unread,
Oct 3, 2012, 6:39:37 AM10/3/12
to
No, they need not.

In general, everyone can open and read *some* *part* of the special file.
After all, there is also a file offset associated with an open file, so
reading from offset 0 may be forbidden, reading from (let's say) offset
0x1000 may be OK (agreed, this will not be the case here).

Sometimes the permissions are set by one kernel component (i.e. the one
which creates the node) while the access is implemented by another
component which has some stricter rules, e.g. due to SELinux.

The actual permissions may even vary with runtime configuration.

Josef

PS Please restrict quoting!

Phil Carmody

unread,
Oct 10, 2012, 6:53:33 PM10/10/12
to
Josef Moellers <josef.m...@invalid.invalid> writes:
> On 10/02/2012 07:46 PM, Alex Vinokur wrote:
> > On Tuesday, October 2, 2012 7:14:38 PM UTC+2, Tauno Voipio wrote:
>
> >> The 'files' in /proc are no regular files. They are peepholes into the
> >> internals of the kernel. The kernel may impose whatever additional
> >> restrictions it deems fit.
> >>
> > In this case their permissions should be -r-------- or -r--r-----, but not -r--r--r-- (i.e., 0400 or 0440, but not 0444).
>
> No, they need not.

You cannot counter "a should be" with a "need not".
Clearly they need not, as it works currently without the more restrictive flags.

Phil
--
Regarding TSA regulations:
How are four small bottles of liquid different from one large bottle?
Because four bottles can hold the components of a binary liquid explosive,
whereas one big bottle can't. -- camperdave responding to MacAndrew on /.

Phil Carmody

unread,
Oct 10, 2012, 6:58:03 PM10/10/12
to
Josef Moellers <josef.m...@invalid.invalid> writes:
> On 10/02/2012 07:46 PM, Alex Vinokur wrote:
> > On Tuesday, October 2, 2012 7:14:38 PM UTC+2, Tauno Voipio wrote:
>
> >> The 'files' in /proc are no regular files. They are peepholes into the
> >> internals of the kernel. The kernel may impose whatever additional
> >> restrictions it deems fit.
> >>
> > In this case their permissions should be -r-------- or -r--r-----, but not -r--r--r-- (i.e., 0400 or 0440, but not 0444).
>
> No, they need not.

a.c.k...@gmail.com

unread,
Jul 14, 2013, 9:08:36 AM7/14/13
to
Regardless of the explanations as to why which were given, the current behaviour breaks shell scripts which try to be careful with permissions like:

! [[ -r /proc/$pid/maps ]] && echo "You don't have permission to read this file"

These scripts will now have to deal with some other process bombing out hard with an error when actually trying to read from the file.
There doesn't seem to be a way to check for permissions without actually provoking an error, which is not the way I like to do things.

Jorgen Grahn

unread,
Jul 14, 2013, 1:08:46 PM7/14/13
to
On Sun, 2013-07-14, a.c.k...@gmail.com wrote:
> On Tuesday, October 2, 2012 4:05:22 PM UTC+2, Alex Vinokur wrote:
>> Hi,
>>
>>
>>
>> Could anybody explain why we have 'Permission denied' here?

[reading /proc/foo may give EPERM even though ls -l says it's world
readable]

> Regardless of the explanations as to why which were given, the
> current behaviour breaks shell scripts which try to be careful with
> permissions like:

> ! [[ -r /proc/$pid/maps ]] && echo "You don't have permission to read this file"

> These scripts will now have to deal with some other process bombing
> out hard with an error when actually trying to read from the file.

> There doesn't seem to be a way to check for permissions without
> actually provoking an error, which is not the way I like to do things.

Why not? It's how I prefer to do it, if at all possible.

Doing it in two discrete steps almost always introduces the potential
for weird situations anyway. Like checking if a file exists before
you try to read it: someone may remove it after you checked but before
you opened it for reading.

And also, fortune -m forgiveness:

"It is often easier to ask for forgiveness than to ask for permission."
-- Grace Murray Hopper

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

crankypuss

unread,
Jul 15, 2013, 4:41:44 AM7/15/13
to
On 07/14/2013 07:08 AM, a.c.k...@gmail.com wrote:
> There doesn't seem to be a way to check for permissions without actually provoking an error,
> which is not the way I like to do things.


man access
man eaccess
man faccessat

If using PHP, see help for posix_access()

You appear to be using bash; good luck with that. If you have the cli
form of PHP installed you could write a brief interface routine
implemented as a command accessible from bash. There might already
exist a module that does the query using the C-level interfaces but I've
not written any C under linux just yet.

Richard Kettlewell

unread,
Jul 15, 2013, 5:05:09 AM7/15/13
to
a.c.k...@gmail.com writes:
> Regardless of the explanations as to why which were given, the current
> behaviour breaks shell scripts which try to be careful with
> permissions like:
>
> ! [[ -r /proc/$pid/maps ]] && echo "You don't have permission to read this file"
>
> These scripts will now have to deal with some other process bombing
> out hard with an error when actually trying to read from the file.
>
> There doesn't seem to be a way to check for permissions without
> actually provoking an error, which is not the way I like to do things.

That is an antipattern.

The way to deal with files being unreadable (or unwritable) is to try
the read (or write) and handle any the error that may occur.

Since the readability of writability of the file may change between the
check and the open, or indeed after the open, you have to do this anyway
- so the up-front check is a waste of effort.

Use ‘set -e’ in shell scripts to automate much of the checking.

--
http://www.greenend.org.uk/rjk/

crankypuss

unread,
Jul 15, 2013, 5:51:35 AM7/15/13
to
It's a matter of philosophy, mostly; two different approaches, for a
given application one or the other might be more appropriate. And its
appropriateness depends on the mechanisms available for error-handling
and the type of user-interface one wants to provide.

One can walk around blind and bounce off doors that are closed, or he
can look first and save some wear and tear on the nose; or look to see
if the door is already open, check to see if the knob turns, and so forth.

If a fellow is satisfied with the level of error handling provided for
shell scripts, easy-peasey, slop it out and let the user handle the
details; if one wants something a little more usable, the game changes.

Jorgen Grahn

unread,
Jul 15, 2013, 6:06:17 AM7/15/13
to
On Mon, 2013-07-15, crankypuss wrote:
> On 07/14/2013 07:08 AM, a.c.k...@gmail.com wrote:
>> There doesn't seem to be a way to check for permissions without actually provoking an error,
> > which is not the way I like to do things.
>
> man access
> man eaccess
> man faccessat

Unless I misunderstand completely, his complaint is that these system
calls give incorrect results in certain situations. 'test -r' uses
access(2).

The warning in the access(2) manual page is instructive though -- and
supports what RK and I wrote about how it's better not to try to
predict if the operation will work.

Richard Kettlewell

unread,
Jul 15, 2013, 6:32:15 AM7/15/13
to
crankypuss <crank...@nomail.invalid> writes:
> On 07/15/2013 03:05 AM, Richard Kettlewell wrote:
>> a.c.k...@gmail.com writes:
>>> Regardless of the explanations as to why which were given, the current
>>> behaviour breaks shell scripts which try to be careful with
>>> permissions like:
>>>
>>> ! [[ -r /proc/$pid/maps ]] && echo "You don't have permission to read this file"
>>>
>>> These scripts will now have to deal with some other process bombing
>>> out hard with an error when actually trying to read from the file.
>>>
>>> There doesn't seem to be a way to check for permissions without
>>> actually provoking an error, which is not the way I like to do things.
>>
>> That is an antipattern.
>>
>> The way to deal with files being unreadable (or unwritable) is to try
>> the read (or write) and handle any the error that may occur.
>>
>> Since the readability of writability of the file may change between the
>> check and the open, or indeed after the open, you have to do this anyway
>> - so the up-front check is a waste of effort.
>>
>> Use ‘set -e’ in shell scripts to automate much of the checking.
>
> It's a matter of philosophy, mostly; two different approaches, for a
> given application one or the other might be more appropriate. And its
> appropriateness depends on the mechanisms available for error-handling
> and the type of user-interface one wants to provide.

If you mean: whether you take the ‘set -e’ approach and just fall over
on error, or handle each error explicitly and report it in some
user-friendly way, sure, there’s a place for both.

If you mean: up-front checks vs handling errors when they occur, then
no, it’s not a matter of philosophy. Up-front checks are simply not
reliable and there is no way round this. You have to detect errors as
they occur and handle them in whatever manner is appropriate to the
application.

If some aspect of this is too hard in shell, there’s no shortage of
alternative languages.

--
http://www.greenend.org.uk/rjk/

crankypuss

unread,
Jul 16, 2013, 5:50:17 AM7/16/13
to
There's a difference between checking and finding that a user is
presumably authorized to do something then not handling errors that
actually occur, and checking and finding out that the user is not
authorized and stopping there. Unless one is satisfied with "permission
denied" as opposed to "directory permission denied" versus "file
permission denied" (for example).

> You have to detect errors as
> they occur and handle them in whatever manner is appropriate to the
> application.

Yes, on that we agree. On the other hand there is sometimes value in
checking beforehand.

> If some aspect of this is too hard in shell, there’s no shortage of
> alternative languages.
>

Languages aside, the notes for access(2) are, as another poster pointed
out, interesting.

"Warning: Using access() to check if a user is authorized to, for
example, open a file before actually doing so using open(2) creates a
security hole, because the user might exploit the short time
interval between checking and opening the file to manipulate it."

I'm not quite seeing how that can create a security hole; if the user is
not authorized to open it, how can he then manipulate it? On the other
hand, if he is authorized he can manipulate it afterward. Can someone
explain this?

"For this reason, the use of this system call should be avoided."

Pardon my attitude, but that is ridiculous. Either the function should
work 100%, it should be fixed, or it should be removed. Granted the
timing issues involved with this kind of thing are legion, but that is
one of the reasons for the concept of locking. I get the idea from
other comments in the documentation that the presence of access in linux
is motivated politically rather than technically, that it's part of the
requirements for a posix certification or something.

Richard Kettlewell

unread,
Jul 16, 2013, 6:29:23 AM7/16/13
to
crankypuss <crank...@nomail.invalid> writes:
> There's a difference between checking and finding that a user is
> presumably authorized to do something then not handling errors that
> actually occur, and checking and finding out that the user is not
> authorized and stopping there. Unless one is satisfied with
> "permission denied" as opposed to "directory permission denied" versus
> "file permission denied" (for example).

Handling the errors as they occur doesn’t prevent you from giving more
detailed error messages, if that’s what you want to do.

[..]
> Languages aside, the notes for access(2) are, as another poster
> pointed out, interesting.
>
> "Warning: Using access() to check if a user is authorized to, for
> example, open a file before actually doing so using open(2) creates a
> security hole, because the user might exploit the short time
> interval between checking and opening the file to manipulate it."
>
> I'm not quite seeing how that can create a security hole; if the user
> is not authorized to open it, how can he then manipulate it?
>
> On the other hand, if he is authorized he can manipulate it afterward.
> Can someone explain this?

link() and symlink() are the usual mechanisms.

> "For this reason, the use of this system call should be avoided."
>
> Pardon my attitude, but that is ridiculous. Either the function
> should work 100%, it should be fixed, or it should be removed.
> Granted the timing issues involved with this kind of thing are legion,
> but that is one of the reasons for the concept of locking. I get the
> idea from other comments in the documentation that the presence of
> access in linux is motivated politically rather than technically, that
> it's part of the requirements for a posix certification or something.

The problem the warning refers to is a privileged program (for instance,
a setuid program) checking the access rights of an unprivileged user to
a path that the unprivileged user can control some element of.

If the checking program isn’t privileged relative to the calling user,
or if it’s checking for access to some path that cannot be controlled by
an unprivileged user, then the warning isn’t really relevant.

--
http://www.greenend.org.uk/rjk/

crankypuss

unread,
Jul 16, 2013, 6:53:00 AM7/16/13
to
If the guy is running as root, all bets are off to begin with.

Rainer Weikusat

unread,
Jul 16, 2013, 8:06:14 AM7/16/13
to
crankypuss <crank...@nomail.invalid> writes:
> On 07/16/2013 04:29 AM, Richard Kettlewell wrote:

[...]

>>> Pardon my attitude, but that is ridiculous. Either the function
>>> should work 100%, it should be fixed, or it should be removed.
>>> Granted the timing issues involved with this kind of thing are legion,
>>> but that is one of the reasons for the concept of locking. I get the
>>> idea from other comments in the documentation that the presence of
>>> access in linux is motivated politically rather than technically, that
>>> it's part of the requirements for a posix certification or something.
>>
>> The problem the warning refers to is a privileged program (for instance,
>> a setuid program) checking the access rights of an unprivileged user to
>> a path that the unprivileged user can control some element of.
>>
>> If the checking program isn’t privileged relative to the calling user,
>> or if it’s checking for access to some path that cannot be controlled by
>> an unprivileged user, then the warning isn’t really relevant.
>
> If the guy is running as root, all bets are off to begin with.

This is supposed to setuid processes which run with an effective user
id (euid) different from their real user id. The permission check
performed by access uses the real uid and this means it seems as if
this was a way the program running with a different euid could check
whether or not the user who invoked it has permission to access a
certain filesystem object. But this doesn't work reliably because the
same path name could refer to a different filesystem object by the
time the actual 'access routine' (usually, open) runs or the
permissions of the checked filesystem object could change in between.

Jorgen Grahn

unread,
Jul 16, 2013, 3:04:27 PM7/16/13
to
On Tue, 2013-07-16, crankypuss wrote:

[access(2)]

> I get the idea from
> other comments in the documentation that the presence of access in linux
> is motivated politically rather than technically, that it's part of the
> requirements for a posix certification or something.

That's one way of putting it, but a bit misleading. The reason it
exists is /practical/: you don't remove a system calls which has
existed since the 1980s, even if you think they are misdesigned.

crankypuss

unread,
Jul 17, 2013, 3:52:35 AM7/17/13
to
I sort of understand, and thank you for the explanation. I'm of the
opinion that there are some basic problems with the linux filesystem
protection mechanisms, mostly because although filesystems are tree
structured, object protection is not hierarchical. It could be that I'm
too new to linux (and unix) to fully grasp something that is flawless,
but maybe not. Thanks again.

crankypuss

unread,
Jul 17, 2013, 4:21:45 AM7/17/13
to
On 07/16/2013 01:04 PM, Jorgen Grahn wrote:
> On Tue, 2013-07-16, crankypuss wrote:
>
> [access(2)]
>
>> I get the idea from
>> other comments in the documentation that the presence of access in linux
>> is motivated politically rather than technically, that it's part of the
>> requirements for a posix certification or something.
>
> That's one way of putting it, but a bit misleading. The reason it
> exists is /practical/: you don't remove a system calls which has
> existed since the 1980s, even if you think they are misdesigned.
>
> /Jorgen
>

Although I definitely understand and fully support the idea that you
don't go around breaking existing code just to make the world tidier, I
also feel that it's a mistake to retain B.A.D. (broken-as-designed)
functionality for the sake of an existing codebase.

I hesitate to mention Microsoft Windows but it is a good example of the
damage that can occur when compatability with existing code becomes more
important than fixing what needs to be fixed. They started out with a
poorly designed single-user monitor, and in order to maintain
compatability with existing code they never really did fix things (at
least up to the point where I walked away in disgust).

It would be sad indeed to see linux go down that same wretched path...
not that it is even in the same ballpark, but it is not yet perfect and
it will never reach that goal if incompatible changes are
philosophically disallowed; nor will it continue to improve if
incompatible changes are allowed to drive people away because they are
excessively disruptive.

Linux picked up a lot of concepts from Unix but imo Unix has never been
quite perfect and ancestor worship is not going to benefit linux in the
long run. It could be that it takes a few decades for the awkward
design characteristics of a system to become obvious and then move past
obviousness to become annoying enough to provoke someone to fix them.
But if, when they reach that point, they are left in place as they were,
that basically amounts to the end of growth and the beginning of old
age's decline.

There are design flaws inherent in the Unix architecture/mechanism that
run very deep and seem to have been picked up by linux either unnoticed,
or noticed and justified by limited resource availability.

Maybe the only way to keep the software arts moving forward is to
collect what we have learned and throw away existing implementations
every few decades, or maybe we are forever doomed to carry along
annoyances from the past, I don't claim to know one way or the other.

It does seem to me that it might be time to build a new abstraction
layer that can become a more consistent intermediary between existing
code and fixed code, but that involves a huge amount of work.
0 new messages