Access permission problems

Hello

I thought I understood access permissions, but a
few oddities have made me question myself.

Here is one to warm up.

ngc@saturn /test > id
uid=106(ngc) gid=100(ngc)
ngc@saturn /test > touch xx
ngc@saturn /test > chmod 0040 xx
ngc@saturn /test > ls -l xx
----r----- 1 ngc ngc 0 Dec 19 11:56 xx
ngc@saturn /test > cat xx
xx: Permission denied
ngc@saturn /test >

Is that right? Since the file has group read permission
and it is my group I would expect to be able to read it.


Here is the related problem I really want help with. The
one above just popped up whilst investigating this.

If I login at root (login mind, not switch users using su)

login: root
Password:

cd /test

touch read-by-group

chmod 0040 read-by-group

chown ngc:ngc read-by-group

su - nobody

$ id
uid=99(nobody) gid=99(nobody)
groups=0(root),1(bin),3(sys),4(adm),5(tty)
$ ls -l /test
total 0
----r----- 1 ngc ngc 0 Dec 19 12:21 read-by-group
$ cat /test/read-by-group
/test/read-by-group: Permission denied

Fair enough. There is no read perission for ‘nobody’

Now login as user ngc (again, login, not su)

login: ngc
Password:
ngc@saturn ~ > id
uid=106(ngc) gid=100(ngc)
ngc@saturn ~ > cat /test/read-by-group
/test/read-by-group: Permission denied
ngc@saturn ~ > l !$
l /test/read-by-group
----r----- 1 ngc ngc 0 Dec 19 12:21 /test/read-by-group
ngc@saturn ~ > su -
password:

su - nobody

$ id
uid=99(nobody) gid=99(nobody)
$ cat /test/read-by-group
$ echo $?
0
$

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

Can anyone explain this? The issue is not related to
reading but exists with writing as well. The scripts
below are what I started off with and demonstrate the
issue further.

Script mkfiles run as root:

#!/bin/sh
touch readonly-all
chmod 0444 readonly-all
touch readonly-user
chmod 0400 readonly-user
touch readonly-group
chmod 0040 readonly-group
touch readonly-other
chmod 0004 readonly-other
touch writeonly-all
chmod 0222 writeonly-all
touch writeonly-user
chmod 0200 writeonly-user
touch writeonly-group
chmod 0020 writeonly-group
touch writeonly-other
chmod 0002 writeonly-other
touch readwrite-all
chmod 0666 readwrite-all
touch readwrite-user
chmod 0600 readwrite-user
touch readwrite-group
chmod 0060 readwrite-group
touch readwrite-other
chmod 0006 readwrite-other

chown ngc:ngc *


Script access-files run as someone else, eg you or
“nobody” after switching users with su:

#!/bin/sh
set readonly-all
readonly-user
readonly-group
readonly-other
writeonly-all
writeonly-user
writeonly-group
writeonly-other
readwrite-all
readwrite-user
readwrite-group
readwrite-other

for f ; do
LSL=ls -l $f
PERM=echo $LSL | awk '{ print $1 }'

if ( cat $f > /dev/null 2>&1 ); then
READ=r
else
READ=.
fi
if ( echo 1 2> /dev/null > $f ); then
WRITE=w
else
WRITE=.
fi
echo $PERM $READ$WRITE $f
done

After makiung the files we get:

ls -l /test

total 4
-r–r–r-- 1 ngc ngc 0 Dec 19 12:31 readonly-all
----r----- 1 ngc ngc 0 Dec 19 12:31 readonly-group
-------r-- 1 ngc ngc 0 Dec 19 12:31 readonly-other
-r-------- 1 ngc ngc 0 Dec 19 12:31 readonly-user
-rw-rw-rw- 1 ngc ngc 0 Dec 19 12:31 readwrite-all
----rw---- 1 ngc ngc 0 Dec 19 12:31 readwrite-group
-------rw- 1 ngc ngc 0 Dec 19 12:31 readwrite-other
-rw------- 1 ngc ngc 0 Dec 19 12:31 readwrite-user
–w–w–w- 1 ngc ngc 0 Dec 19 12:31 writeonly-all
-----w---- 1 ngc ngc 0 Dec 19 12:31 writeonly-group
--------w- 1 ngc ngc 0 Dec 19 12:31 writeonly-other
–w------- 1 ngc ngc 0 Dec 19 12:31 writeonly-user

Logging in as ngc (owner and group of files) and then switching
to root and then to nobody:
$ cd /test
$ /home/wrm/dev/access-files
-r–r–r-- r. readonly-all
-r-------- … readonly-user
----r----- r. readonly-group
-------r-- … readonly-other
–w–w–w- .w writeonly-all
–w------- … writeonly-user
-----w---- .w writeonly-group
--------w- … writeonly-other
-rw-rw-rw- rw readwrite-all
-rw------- … readwrite-user
----rw---- rw readwrite-group
-------rw- … readwrite-other
$

Results for group and other are reversed from what I expected.

Sorry this is so long. I hope someone else can reproduce my
results and explain this.
Regards

William Morris
wmorris@uk.waukbearing.com

William Morris <william@bangel.demon.co.uk> wrote:

Hello

I thought I understood access permissions, but a
few oddities have made me question myself.

Here is one to warm up.

ngc@saturn /test > id
uid=106(ngc) gid=100(ngc)
ngc@saturn /test > touch xx
ngc@saturn /test > chmod 0040 xx
ngc@saturn /test > ls -l xx
----r----- 1 ngc ngc 0 Dec 19 11:56 xx
ngc@saturn /test > cat xx
xx: Permission denied
ngc@saturn /test

Is that right? Since the file has group read permission
and it is my group I would expect to be able to read it.

That is right.

If you match by user, it will use the user permissions, and never
check group or other permissions.

If you don’t match by user, but match by group, it will use group
permissions, and never check other.

If you do not match user or group, it will use other permissions.




Here is the related problem I really want help with. The
one above just popped up whilst investigating this.

If I login at root (login mind, not switch users using su)

login: root
Password:

cd /test

touch read-by-group

chmod 0040 read-by-group

chown ngc:ngc read-by-group

su - nobody

$ id
uid=99(nobody) gid=99(nobody)
groups=0(root),1(bin),3(sys),4(adm),5(tty)
$ ls -l /test
total 0
----r----- 1 ngc ngc 0 Dec 19 12:21 read-by-group
$ cat /test/read-by-group
/test/read-by-group: Permission denied

Fair enough. There is no read perission for ‘nobody’

Now login as user ngc (again, login, not su)

login: ngc
Password:
ngc@saturn ~ > id
uid=106(ngc) gid=100(ngc)
ngc@saturn ~ > cat /test/read-by-group
/test/read-by-group: Permission denied
ngc@saturn ~ > l !$
l /test/read-by-group
----r----- 1 ngc ngc 0 Dec 19 12:21 /test/read-by-group
ngc@saturn ~ > su -
password:

su - nobody

$ id
uid=99(nobody) gid=99(nobody)
$ cat /test/read-by-group
$ echo $?
0
$

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

If you login as nobody, rather than su to nobody, then you
will find that nobody can’t read the file. After the su,
you still have some some root perms – which apparently
is being used for validation. I think it is a real/effective
perms thing or something.


Script access-files run as someone else, eg you or
“nobody” after switching users with su:

su doesn’t give you a PURE switch to that new userid. Try the
tests after using login to switch.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs wrote:

Here is one to warm up.

ngc@saturn /test > id
uid=106(ngc) gid=100(ngc)
ngc@saturn /test > touch xx
ngc@saturn /test > chmod 0040 xx
ngc@saturn /test > ls -l xx
----r----- 1 ngc ngc 0 Dec 19 11:56 xx
ngc@saturn /test > cat xx
xx: Permission denied
ngc@saturn /test

Is that right? Since the file has group read permission
and it is my group I would expect to be able to read it.

That is right.

If you match by user, it will use the user permissions, and never
check group or other permissions.

If you don’t match by user, but match by group, it will use group
permissions, and never check other.

If you do not match user or group, it will use other permissions.

Does that mean you agree with me that ngc should be able to read
the file? If so, why can it not?

[ snip ]

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

If you login as nobody, rather than su to nobody, then you
will find that nobody can’t read the file. After the su,
you still have some some root perms – which apparently
is being used for validation. I think it is a real/effective
perms thing or something.

I thought that checks were done against the effective
permissions, not the real ones. What you imply is that,
although user ngc couldn’t read the file (using its valid
group access perm), after su’ing into nobody (via root) we
have gained group access permission.

Script access-files run as someone else, eg you or
“nobody” after switching users with su:

su doesn’t give you a PURE switch to that new userid. Try the
tests after using login to switch.

Mmm. can you tell me what exactly su does? Does it do
a setuid/setgid() or a seteuid/setegid() ?

Thanks for replying
William Morris

William Morris <william@bangel.demon.co.uk> wrote:


David Gibbs wrote:

Here is one to warm up.

ngc@saturn /test > id
uid=106(ngc) gid=100(ngc)
ngc@saturn /test > touch xx
ngc@saturn /test > chmod 0040 xx
ngc@saturn /test > ls -l xx
----r----- 1 ngc ngc 0 Dec 19 11:56 xx
ngc@saturn /test > cat xx
xx: Permission denied
ngc@saturn /test

Is that right? Since the file has group read permission
and it is my group I would expect to be able to read it.

That is right.

If you match by user, it will use the user permissions, and never
check group or other permissions.

If you don’t match by user, but match by group, it will use group
permissions, and never check other.

If you do not match user or group, it will use other permissions.

Does that mean you agree with me that ngc should be able to read
the file? If so, why can it not?

You got “permission denied” and asked “Is that right?”. My “That is
right.” was a response to the question of whether or not it is right
to get permission denied.

ngc should NOT be able to read the file.

Permission checking does not give you the most PERMISSIVE possible
access, it gives you the access permitted by the narrowest match of
identity.

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

If you login as nobody, rather than su to nobody, then you
will find that nobody can’t read the file. After the su,
you still have some some root perms – which apparently
is being used for validation. I think it is a real/effective
perms thing or something.

I thought that checks were done against the effective
permissions, not the real ones. What you imply is that,
although user ngc couldn’t read the file (using its valid
group access perm), after su’ing into nobody (via root) we
have gained group access permission.

No. What you have gained is the root ability to access anything.

Login as root.

chmod 00 file

cat file

You will still see the contents – even though the permissions allow
nobody to read the file, root still can. That’s (part of) what being
superuser means.

su doesn’t give you a PURE switch to that new userid. Try the
tests after using login to switch.

Mmm. can you tell me what exactly su does? Does it do
a setuid/setgid() or a seteuid/setegid() ?

It calls setuid() and setgid(). I’m not sure this behaviour is
correct… that is, I’m not sure there should be that latent root
id-ness still hanging around after the su, there.

(After reading that setuid() and setgid() are supposed to change the
real, effective, and saved uid/gid. I will have to do some more
digging to figure out exactly what is going on there.)

But, there are many subtleties in the world of user ids.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs <dagibbs@qnx.com> wrote:

William Morris <> william@bangel.demon.co.uk> > wrote:



David Gibbs wrote:

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

If you login as nobody, rather than su to nobody, then you
will find that nobody can’t read the file. After the su,
you still have some some root perms – which apparently
is being used for validation. I think it is a real/effective
perms thing or something.

I thought that checks were done against the effective
permissions, not the real ones. What you imply is that,
although user ngc couldn’t read the file (using its valid
group access perm), after su’ing into nobody (via root) we
have gained group access permission.

I was wrong there is something going on with the group access
permissions.

I’m betting it has something to do with supplementary groups.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs <dagibbs@qnx.com> wrote:

David Gibbs <> dagibbs@qnx.com> > wrote:
William Morris <> william@bangel.demon.co.uk> > wrote:



David Gibbs wrote:

User ngc cannot read the file, despite being in the
correct group. But user nobody can read it.

If you login as nobody, rather than su to nobody, then you
will find that nobody can’t read the file. After the su,
you still have some some root perms – which apparently
is being used for validation. I think it is a real/effective
perms thing or something.

I thought that checks were done against the effective
permissions, not the real ones. What you imply is that,
although user ngc couldn’t read the file (using its valid
group access perm), after su’ing into nobody (via root) we
have gained group access permission.

I was wrong there is something going on with the group access
permissions.

I’m betting it has something to do with supplementary groups.

Yup, it has to do with supplementary (supplemental) group ids.

When you logged in as ngc, group ngc, QNX also put ngc in your
supplemental groups.

When you su to root, it does a setuid() and setgid() to root – which
do not change your supplemental groups. id incorrectly reports them
as changed. (I will issue a pr against id.)

When you su to nobody, it does setuid() and setgid(), still not
changing your supplemental groups – ngc is still in that list.

Therefor, you can access the file with group permission, because
you do not match users, so user perms don’t match, but a supplemental
group matches the group of the file, so group permissions are checked,
and you do have group permissions to access the file.

The following program correctly displays your supplemental groups:

/*

  • Print the supplementary group IDs of
  • the calling process.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>

int main( void )
{
int gidsize;
gid_t *grouplist;
int i;

gidsize = getgroups( 0, NULL );
grouplist = malloc( gidsize * sizeof( gid_t ) );
getgroups( gidsize, grouplist );
for( i = 0; i < gidsize; i++ )
printf( “%d\n”, ( int ) grouplist _);
return EXIT_SUCCESS;
}

I’m still not sure whether your initial group id should also be
in your supplemental group ids, and therefor inherrited. That will
require more reading in the (somewhat dense and tricky) Posix specs
to figure out.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions._

David Gibbs <dagibbs@qnx.com> wrote:

I’m still not sure whether your initial group id should also be
in your supplemental group ids, and therefor inherrited. That will
require more reading in the (somewhat dense and tricky) Posix specs
to figure out.

This gets curioser and curioser. I’m beginning to think that
id is, mostly, ok, But that QNX’s implementation of supplementary
groups is broken, and that id is hacked to mask that, leaving it
slightly broken in another situation.

What, exactly, is broken gets down to the subtlety of Posix definitions,
in a place where the historical practice, and the Posix standards are
inconsistent, and two different behaviours/choice seem to have been
allowed.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs <dagibbs@qnx.com> wrote:

What, exactly, is broken gets down to the subtlety of Posix definitions,
in a place where the historical practice, and the Posix standards are
inconsistent, and two different behaviours/choice seem to have been

In 1003.1, definition 2.2.2.123, it says that “whether a process’s
effective group ID is included in or omitted from its list of
supplementary group IDs is unspecified”; in the corresponding
rationale B.4.2.3 it also adds “the history of a process and its
parents could affect the details of result” … :wink: I think the
QNX6 implementation was changed recently (from not including to
including - although POSIX does hint that the utilities need to
be aware of this detail so they can manipulate the supplementary
group list appropriately, so perhaps something was missed in the
change?), so you may want to compare your tests on an older and a
headbranch version … ?!?

David Gibbs <dagibbs@qnx.com> wrote:

You got “permission denied” and asked “Is that right?”. My “That is
right.” was a response to the question of whether or not it is right
to get permission denied.

ngc should NOT be able to read the file.

Permission checking does not give you the most PERMISSIVE possible
access, it gives you the access permitted by the narrowest match of
identity.

Sorry, I missed/misunderstood the point that if the uid matches
the group is not even checked. So now I understand. Stevens says
the same and I had missed in there too.

As I originally indicated, I didn’t understand permissions as well
as I had previously thought. It does seem a little counter-intuitive
that one can give a group, of which you are a member, permission to
read your own files and exclude yourself. I wonder where that is of
use.

Thanks
William

John Garvey <jgarvey@qnx.com> wrote:

David Gibbs <> dagibbs@qnx.com> > wrote:
What, exactly, is broken gets down to the subtlety of Posix definitions,
in a place where the historical practice, and the Posix standards are
inconsistent, and two different behaviours/choice seem to have been

In 1003.1, definition 2.2.2.123, it says that “whether a process’s
effective group ID is included in or omitted from its list of
supplementary group IDs is unspecified”; in the corresponding
rationale B.4.2.3 it also adds “the history of a process and its
parents could affect the details of result” … > :wink: > I think the
QNX6 implementation was changed recently (from not including to
including - although POSIX does hint that the utilities need to
be aware of this detail so they can manipulate the supplementary
group list appropriately, so perhaps something was missed in the
change?), so you may want to compare your tests on an older and a
headbranch version … ?!?

There are other bits that say if they egid is included in the supplementary
groups, and you do a setegid(), you must mung the supplementary groups to
match.

QNX6 (6.2.0) is not doing this. I haven’t tested against 6.2.1, but
did issue a PR, and Adam is looking at it.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

wrm@bangel.demon.co.uk wrote:

David Gibbs <> dagibbs@qnx.com> > wrote:

Sorry, I missed/misunderstood the point that if the uid matches
the group is not even checked. So now I understand. Stevens says
the same and I had missed in there too.

Yeah, I like Stevens to. I did have APUE open a couple times while
going through this – though more for the supplemental groups thing.
(I knew the user/group checking rule already. Yes it does seem
anti-intuitive.)

As I originally indicated, I didn’t understand permissions as well
as I had previously thought. It does seem a little counter-intuitive
that one can give a group, of which you are a member, permission to
read your own files and exclude yourself. I wonder where that is of
use.

I can come up with some contrived examples with execute permission,
but in general, mostly it doesn’t make much sense.

But, by doing it this way, you do get more flexibility – you CAN
do such a setup. And, if you have your perms properly configured,
that is, anytime you give group r/w/x you also give user r/w/x,
then it doesn’t cost you either. (And, if you own the file, you
can change the perms.)

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs <dagibbs@qnx.com> wrote:

There are other bits that say if they egid is included in the supplementary
groups, and you do a setegid(), you must mung the supplementary groups to
match.

QNX6 (6.2.0) is not doing this. I haven’t tested against 6.2.1, but
did issue a PR, and Adam is looking at it.

Thanks for the help with this. I figure that my test program (which
caused me to delve into this when it gave unexpected results) needs
modifying to set the supplementary groups using initgroups() and all
will be well.

I wonder whether I am the only one who didn’t know that su doesn’t
quite switch users. The Linux man pages I have looked at say
explicitly that supplemental groups are set by su. But then I
suppose Linux isn’t Posix.

Thanks again

William Morris
william@bangel.demon.co.uk