LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   setuid, setgid, sticky bit (https://www.linuxquestions.org/questions/linux-newbie-8/setuid-setgid-sticky-bit-4175530367/)

vincix 01-07-2015 04:18 PM

setuid, setgid, sticky bit
 
There's something really weird happening with permissions on a directory in linux. I have the directory /dir

Code:

ls -ld /dir
drwxrwxrwx. 2 root root 4096 Jan  8 00:06 dir
chmod 2777 /dir [this sets the setgid bit on]
ls -ld /dir
drwxrwsrwx. 2 root root 4096 Jan  8 00:06 /dir

And this is what I expect it to do.
However, when I change it to setid (WITHOUT setgid), it simply doesn't work. Instead of overwriting, it cumulates:
Code:

chmod 4777 /dir [for setting setuid bit on]
drwsrwsrwx. 2 root root 4096 Jan  8 00:06 /dir

As you can see, the setgid bit is still on together with the setuid! However, if I run:
Code:

chmod -s /dir
then the file has a 0777 permission.

And then again, if I change its permission to 4777 (so setuid):
Code:

chmod 4777 /dir
drwsrwxrwx. 2 root root 4096 Jan  8 00:06 /dir

it acts normally. So the same chmod 4777 acts differently in two different contexts.

I really can't understand it. Basically, I cannot get rid of the setuid/setgid through binary permissions. The sticky bit works fine. Changing from 1777 to 0777 adds and removes "t" respectively. What am I to make of all this? This behaviour makes no sense to make especially given that we can change the permissions to 6777 (setuid + setgid).

Miati 01-07-2015 05:07 PM

Interesting

I generally check my permissions with stat
Code:

alias perm="stat -c '%n %U:%G-%a'"
Code:

$ mkdir test
$ perm test
test miati:miati-755
$ chmod 2777 test
$ perm test
test miati:miati-2777
$ chmod 4777 test
$ perm test
test miati:miati-6777
$ chmod 0777 test
$ perm test
test miati:miati-6777
$ sudo chmod 0777 test
[sudo] password for miati:
$ perm test
test miati:miati-6777
$

At least for numeric permissions setting, you can only set by not remove sticky bit settings.
Not sure in what case that should make sense.. but good to know.

Probably what's happening is when you set the sticky bit of 2, then 4, it cannot remove the 2 so it just stacks it on.

vincix 01-08-2015 03:34 AM

Quote:

Originally Posted by Miati (Post 5297333)
Probably what's happening is when you set the sticky bit of 2, then 4, it cannot remove the 2 so it just stacks it on.

It's not only about this particular sequence. If I start with 4 (setuid), it's the same thing.

So if I run chmod 4777 dir, then the chmod 0777 dir has absolutely no effect. The order in which you do it makes no difference and it makes no difference either if you start with 4 and then 2, viceversa or just use 4 and then try to delete it (or 2 and then try to delete it).

The point is, once you've set an even number on special permissions, you just can't get rid of it unless you do it with -s. This is rather discouraging, given the fact that when you learn Linux, you're generally taught to learn the binary versions, because it's a better understanding of what's happening and it's actually much quicker etc etc.

Another problem - which in a way is more important if you want to get something done - is that for me setuid doesn't do what I expected it to do.

So I've got /dir on which bob is the owner.
/dir has 4777.
If I go ahead and create a file with user anna, the owner of that file is going to be anna. I've tested it both in xubuntu and Centos 6.

Why is that happening?

I've done the exact same thing with setGID and it works just fine. Newly created files belong to the group to which the parent directory belongs.

pan64 01-08-2015 04:18 AM

I can only suggest you to read the man page of chmod:
Code:

SETUID AND SETGID BITS
      chmod clears the set-group-ID bit of a regular file if the file's group ID does not match the user's effective group ID or one of the user's sup‐
      plementary  group  IDs,  unless  the user has appropriate privileges.  Additional restrictions may cause the set-user-ID and set-group-ID bits of
      MODE or RFILE to be ignored.  This behavior depends on the policy and functionality of the underlying chmod system call.  When  in  doubt,  check
      the underlying system behavior.

      chmod preserves a directory's set-user-ID and set-group-ID bits unless you explicitly specify otherwise.  You can set or clear the bits with sym‐
      bolic modes like u+s and g-s, and you can set (but not clear) the bits with a numeric mode.


vincix 01-08-2015 08:03 AM

That "but not clear" line is quite amazing, given that it's on man pages. So what I need to understand, basically, is the same conclusion that I've drawn before: that I cannot change special permissions unless I turn to symbolic modes (which is nonsense to me, but whatever).
What is the underlying system behavior? This is not an explanation for anyone who wants to understand what is going on.

And what about the last part of my post regarding the setuid? How can I create a file that has a different owner from the one who creates it? It simply doesn't work.

pan64 01-08-2015 08:09 AM

I would say it is also there: Additional restrictions may cause the set-user-ID and set-group-ID bits of MODE or RFILE to be ignored.
but need to know all the relevant info: permission and user settings...

vincix 01-08-2015 01:50 PM

Quote:

Originally Posted by pan64 (Post 5297636)
I would say it is also there: Additional restrictions may cause the set-user-ID and set-group-ID bits of MODE or RFILE to be ignored.
but need to know all the relevant info: permission and user settings...

Well, your reply is still less than satisfactory, to say the least. What are these permissions or user settings are you talking about exactly? They're DEFAULT! (Centos, Ubuntu, etc.)

jpollard 01-08-2015 05:38 PM

the S/s flags are not permissions, they are simplified capabilities. Setting one does not affect the other.

It just happens to be in the same field in the inode...(along with directory flag, socket flag, fifo flag)

You can look at the manpage for stat ("man 2 stat", to get the system call). It shows:
Code:

      All  of  these system calls return a stat structure, which contains the
      following fields:

          struct stat {
              dev_t    st_dev;    /* ID of device containing file */
              ino_t    st_ino;    /* inode number */
              mode_t    st_mode;    /* protection */
              nlink_t  st_nlink;  /* number of hard links */
  ...

and flag definitions:
Code:

      The following flags are defined for the st_mode field:

          S_IFMT    0170000  bit mask for the file type bit fields
          S_IFSOCK  0140000  socket
          S_IFLNK    0120000  symbolic link
          S_IFREG    0100000  regular file
          S_IFBLK    0060000  block device
          S_IFDIR    0040000  directory
          S_IFCHR    0020000  character device
          S_IFIFO    0010000  FIFO
          S_ISUID    0004000  set UID bit
          S_ISGID    0002000  set-group-ID bit (see below)
          S_ISVTX    0001000  sticky bit (see below)
          S_IRWXU    00700    mask for file owner permissions
          S_IRUSR    00400    owner has read permission
          S_IWUSR    00200    owner has write permission
          S_IXUSR    00100    owner has execute permission
          S_IRWXG    00070    mask for group permissions
          S_IRGRP    00040    group has read permission

          S_IWGRP    00020    group has write permission
          S_IXGRP    00010    group has execute permission
          S_IRWXO    00007    mask for permissions for others (not in group)
          S_IROTH    00004    others have read permission
          S_IWOTH    00002    others have write permission
          S_IXOTH    00001    others have execute permission

The convention (since forever) has been to treat the access permissions separate from the capabilities (only three, setuid, setgid, and sticky) and the file type bits (16, though not all possible bits are used) note - there is some overlap (block device/directory/character device) which is historical (originally this was a 16 bit unsigned field, now it is 32 bits) .

pan64 01-09-2015 12:25 AM

not, they are not default, those are the permissions, access right and other settings configured on your host. for example user id, group id of bob and anna, additional groups, owner of that given dir, access rights of that user .... If selinux was in use..... the type of filesystem, what kind of additional policy was configured (that is how the underlying system was configured) - not to speak about the implementation of chmod kernel related things). I have no any information about them.

vincix 01-09-2015 01:59 AM

Quote:

Originally Posted by pan64 (Post 5298046)
not, they are not default, those are the permissions, access right and other settings configured on your host. for example user id, group id of bob and anna, additional groups, owner of that given dir, access rights of that user .... If selinux was in use..... the type of filesystem, what kind of additional policy was configured (that is how the underlying system was configured) - not to speak about the implementation of chmod kernel related things). I have no any information about them.

Ah, ok. I thought you did and didn't want to tell me about them :)

The thing is, I haven't changed anything in my linux distro (Centos, or Ubuntu), it's exactly the way it was when I first installed it. The only changes that I've made were on THOSE particular files. There are NO additional groups, it's about users newly created just for the sake of this test (so they belong to an omonymous group), and I've already talked about the owner and the group to which that directory belongs and I've been doing it with root (but I also changed the owner and the group to a regular user just to see if something changes). If root doesn't have enough access rights, I don't know who does, really.

And yes, SeLinux is default (enforcing), it's about ext4, there's NO additional policy configured (It's basic default Centos 6.6). I'm just saying all these in case someone else helps me understand what is going on exactly, because I think this is a very basic problem in Linux that anyone should understand, really. And there doesn't seem to be any explanation on the internet about it.

vincix 01-09-2015 02:07 AM

Quote:

Originally Posted by vincix (Post 5298083)
Ah, ok. I thought you did and didn't want to tell me about them :)

The thing is, I haven't changed anything in my linux distro (Centos, or Ubuntu), it's exactly the way it was when I first installed it. The only changes that I've made were on THOSE particular files. There are NO additional groups, it's about users newly created just for the sake of this test (so they belong to an omonymous group), and I've already talked about the owner and the group to which that directory belongs and I've been doing it with root (but I also changed the owner and the group to a regular user just to see if something changes). If root doesn't have enough access rights, I don't know who does, really.

And yes, SeLinux is default (enforcing), it's about ext4, there's NO additional policy configured (It's basic default Centos 6.6). I'm just saying all these in case someone else helps me understand what is going on exactly, because I think this is a very basic problem in Linux that anyone should understand, really. And there doesn't seem to be any explanation on the internet about it.

@jpollard
Only now did I see your post.

Then how come you can add special permissions with chmod binary? I still don't get really. I feel that your explanations keep eluding me. Maybe I'm simply not smart enough really (not ironical), but I feel that most of the answers (except the first one) simply didn't deal exactly with what I was trying to understand.

So the question remains: WHY can I add those "permissions" (whatever you want to call them, they're still known as special permissions) with binary but delete them ONLY with symbolic mode? It still doesn't make any sense to me.

And the second question which was never addressed: why doesn't setuid work on a directory? Why do newly created files under a certain directory are created with the owner of the one who created them, and not the owner of the main directory (which is not root, but some other user)? But it DOES work with setgid. So the group changes, but the owner not!

Makes no sense to me, but obviously I must have been doing something wrong, because we're talking about things that have been like this of decades and I know they're solid.

jpollard 01-09-2015 06:41 AM

Quote:

Originally Posted by vincix (Post 5298084)
@jpollard
Only now did I see your post.

Then how come you can add special permissions with chmod binary? I still don't get really. I feel that your explanations keep eluding me. Maybe I'm simply not smart enough really (not ironical), but I feel that most of the answers (except the first one) simply didn't deal exactly with what I was trying to understand.

So the question remains: WHY can I add those "permissions" (whatever you want to call them, they're still known as special permissions) with binary but delete them ONLY with symbolic mode? It still doesn't make any sense to me.

From the man page on chmod:
Code:

      A numeric mode is from one to  four  octal  digits  (0-7),  derived  by
      adding up the bits with values 4, 2, and 1.  Omitted digits are assumed
      to be leading zeros.  The first digit selects the set user ID  (4)  and
      set group ID (2) and restricted deletion or sticky (1) attributes.  The
      second digit selects permissions for the user who owns the  file:  read
      (4),  write  (2),  and  execute  (1); the third selects permissions for
      other users in the file's group, with the same values; and  the  fourth
      for other users not in the file's group, with the same values.

Omitted flags are treated as leading zeros. Thus it becomes easy to set, but more difficult to unset.
Quote:

And the second question which was never addressed: why doesn't setuid work on a directory? Why do newly created files under a certain directory are created with the owner of the one who created them, and not the owner of the main directory (which is not root, but some other user)? But it DOES work with setgid. So the group changes, but the owner not!
That is deliberate.

Part of the problem is security - you don't want another user to give you a setuid executable that then gives away access to your account. Normally this is blocked by the chown system call, as it would remove the setuid/setgid flags to start with.

The rest is that you don't want a user to give you a large file that uses up your disk quota... You would be able to delete the file, but it can still be a pain to find the right file first. There are also ways to hide it (if the directory is writable allowing a user to delete entries, then the user creates the file - which you then own, and have the quota of - but then removes the file while it is still open (or does an "mv" to a directory the other user owns). The file name is no longer accessible, but your quota is gone AND you can't find the file.

Now it is entirely possible for the system manager to disable both setuid and setgid files on a filesystem at the time the filesystem is mounted (the option on mount is "nosuid", on some UNIX systems they distinguish the difference in use by "nosuid,nosgid"). This is usually done to satisfy site security policy requirements.
Quote:


Makes no sense to me, but obviously I must have been doing something wrong, because we're talking about things that have been like this of decades and I know they're solid.
Naa, it is just some quirks in the way it works. With numbers the bit is either a 1 or a 0. If it is a 0, do you unset it, or is it a leading 0 indicating that what follows is a number? If what follows is a number, how do you specify it should be set to a 0?... Personally, I would have preferred using something like a "chmod +04000 file", but I wasn't working there to suggest it, but then the "+" is nonintuitive (as would be meaning "remove"), and "-" is already used to identify options (hmm maybe a "~" or "^" to indicate removal? it certainly could be "compliment", but that also makes removing the flags more complicated - the compliment of 5 is 2, of 6 is 1, of 3 is 4).

I think that was the impetus to add the symbolic form. The numeric form more closely reflects the system call (man 2 chmod) (the system call doesn't have the oddness of the setuid/gid/sticky bits).

One psychological note about numbers, it is harder to get them right the longer the number is. My usual problem is one too many (or few) digits to get the flag in the right place, and then mess up the other flags. Three digits (four if you count the leading 0) isn't too bad. But 6 starts to cause issues - it is harder to just "see" that there are 6, and people tend to stop and have to count.

The use of octal is because the read/write/execute are the same position in a digit - 7 = rwx, 6 = rw, 5 = rx, 4 = r, 3 = wx, 2 = w, 1=x, "" = not used. I also think the use of the letters "rwx" was deliberate - it puts the bits in alphabetical order, and matches the order needed for the numeric.

It also happens that the system the original developers worked on was a PDP-11 (http://en.wikipedia.org/wiki/PDP-11), which used octal for everything in assembler, so they were very used to it.

vincix 01-09-2015 07:56 AM

Thank you for your explanation. Things have become considerably clearer. But still, why should sticky bit be different to setuid/setgid?

If I type
# chmod 1777 dir
and then
# chmod 0777 dir
Then it works. There's not going to be any sticky bit. Is sticky bit less of a security problem? (it shouldn't be, right? It would mean that users can start deleting others' files).

What about in real life? Are these capabilities used in storage sharing (nfs, samba, whatever) or any other context? If setuid on a directory is basically deactivated because it represents a security problem, then is it somehow obsolete? How does all this translate when you want it to apply it in real-life contexts?

[Later Edit] By the way, this restriction I've been talking about seems only to apply to directories. Binary chmod works just fine on files (adding or removing).

Sticky bit on files is completely obsolete, isn't it?

Miati 01-09-2015 11:09 AM

Quote:

Originally Posted by vincix (Post 5298175)
Sticky bit on files is completely obsolete, isn't it?

Well, referencing wikipedia it appears the sticky bit for files appeared in 1974. So that would make it 40 years old. It appears to have never actually been implemented in linux.

Quote:

Originally Posted by wikipedia (Post 253)
The sticky bit was introduced in the Fifth Edition of Unix (in 1974) for use with pure executable files. When set, it instructed the operating system to retain the text segment of the program in swap space after the process exited. This speeds up subsequent executions by allowing the kernel to make a single operation of moving the program from swap to real memory. Thus, frequently-used programs like editors would load noticeably faster. One notable problem with "sticked" programs was replacing the executable (for instance, during patching); to do so required removing the sticky bit from the executable, executing the program and exiting to flush the cache, replacing the binary executable, and then restoring the sticky bit.

Currently, this behavior is only operative in HP-UX and UnixWare. Solaris appears to have abandoned this in 2005.[citation needed] The 4.4-Lite release of BSD retained the old sticky bit behavior, but it has been subsequently dropped from OpenBSD (as of release 3.7) and FreeBSD (as of release 2.2.1). No version of Linux has ever supported this traditional behavior.


jpollard 01-09-2015 04:02 PM

Quote:

Originally Posted by Miati (Post 5298258)
Well, referencing wikipedia it appears the sticky bit for files appeared in 1974. So that would make it 40 years old. It appears to have never actually been implemented in linux.

Originally, the sticky bit was used totally differently. In 1974 it was only used on executable binary files. There was a totally different method needed to start processes.

1. conversion of the a.out file format into a more complete image - fixing address offsets and libraries. This step put the executable into a workspace for the final form of the process - it also allocated swap space (which was where the workspace was).

2. copy the resulting image into memory (a swap in).

3. run the process.

What the sticky bit meant (and where the "sticky" name came from) was that it took a bit of time to build that memory format on the PDP-11. The "sticky" bit flagged executables that were used frequently, so the swap version of the file would be kept - it became "sticky". The next time the image was needed, no prelinking or address resolution was needed, it came directly from the swap.

Of course this also meant that the swap partition (though it wasn't actually a partition) had to be bigger.

The way swap was handled was interesting. Disks available at the time were 5MB (the kernel only needed about 16k). So when a filesystem was created on a disk the specific size would be 5MB - the amount of swap desired. This allowed mounts to identify available swap space which would also be spread among multiple disks (allowing parallel loading too). It also allowed the available swap space to be larger than a single disk...

Later systems had larger disks, and faster CPUs (and more memory - I believe some of the first UNIX systems only had 60K of memory, later ones (with a MMU) up to 252K memory (missing 4k for I/O), so the use of swap as a workspace dropped, and the system was fast enough that rebuilding wasn't a visible delay.

So the bit got reused, but the name stuck (sorry - it is too good a pun to miss).

Around the time the BSD based systems started appearing, it was used to improve the security on /tmp so that one user couldn't delete a file from another user. Before that, /tmp was always created with mode 777 only, and used by only a few utilities such as the assembler, program linker, and C compiler.

This could cause problems for multiple users, so sometimes somebody would clean up /tmp... and delete the working files for others.

I don't know if it was a BSD use or if Bell Labs used it first. It is a bit difficult to tell because AT&T wasn't allowed to sell anything outside the phone service (it was a monopoly). So Bell Labs would distribute UNIX with only a copying charge (mostly just the tape expense, and mailing fees). So there was a lot of back and forth with patches, improvements, and updates to the system between Bell Labs and the various universities that were using UNIX.

But Linux has had the sticky bit used for /tmp since real close to day 1 (at least as a working system with its own filesystem).


All times are GMT -5. The time now is 02:29 AM.