65

In various places one can see the "sticky bit" accused of nowadays being a complete misnomer, as its functionality nowadays is to affect the write permissions on directories and act as a restricted deletion flag.

In an AskUbuntu answer the answerer wrote that "a sticky bit usually applies to directories". I observed that indeed modern systems seem in practice to never apply it to files, but that a long time ago the usual case was for it to apply to (executable program image) files rather than to directories. (When it comes to the paucity of modern usage on files, there's a related question at Is the sticky bit not used in current file systems .)

This prompted the question:

What did a sticky bit applied to an executable do? Was it like setuid then?

Note the past tense. This is not How does the sticky bit work? now. It's how it used to work then.

  • 3
    I'd like to point out that "I observed that indeed modern systems seem in practice to never apply it to files" is only true for some systems. Wikipedia's page on sticky bit notes, "Currently, this behavior is only operative in HP-UX and UnixWare." It has a chart showing various implementations: the common thread is operating systems ignoring it, or treating it to identify how memory/swap/etc. should be handled. The details of how that was used do vary between operating systems. e.g., no Linux systems ever used the sticky bit like JdeBP's answer. – TOOGAM Jul 1 '16 at 0:16
91

No, the sticky bit was not like the set-UID or set-GID flags. It didn't effect any changes to process credentials.

What the sticky bit did was make the program text "sticky". It wasn't a misnomer, originally.

background: program image sections and shared text

In essence, without getting too deep into the details of executable file formats (which can, and have, filled books): The parts of program image files that are directly loaded into memory in order to run programs comprise machine code, constants, the startup values of (non-zero-initialized) variables, and (in one form or another) blank spaces for zero-initialized and uninitialized variables.

These are grouped into collections known as "sections" and they have conventional names. The machine code and (sometimes) the constants form what is often known as the "text" section of a program image. The non-zero-initialized variables are, similarly, the "data" section; and the zero-initialized and uninitialized variables are "bss" (a name which itself has a whole folkloric history behind it).

When a process has a program executable image file loaded into it, the various parts — text, data, and bss — are initialized from the contents of the image file.

What's special about the "text" section is that the machine code (and the constants) is almost always not written to. It has the potential to be shared across the virtual memory images of all executing process that had that executable image file loaded into them. The exact scenario in which program text can be shared is out of scope for this answer and involves things such as loader fixup idempotence and address space layout identity. People can and have written books about this subject, too. ☺

Shared text is an optimization employed by the kernel. It removes the need for every instance of a single running program image to have its own individual memory image, consuming precious physical memory with multiple copies of the exact same machine code (and constants).

sticky text

But one can do better still than shared text. Obviously, if there's always at least one process running that is using a particular shared text program image, the kernel gets to simply attach the new processes' virtual memory space to the existing shared text segment when a new instance of the program is run. There's almost always an instance of (say) /bin/login or /bin/sh running somewhere on a mid-sized system, so new instances of the login program or the default shell can simply attach to the loaded copies of their text segments that the kernel has already loaded into memory.

Sticky text extends this idea to program images that no process is currently running. If an executable image file is marked as sticky text, then the kernel keeps its text segment around after the last process to use it exits; in the hope that another instance of the program will execute soon, and can just attach back to the segment.

In early Unices, loaded sticky text segments would be swapped out to swap storage when no process was attached to them. (Later Unices stopped using swap for this.) You might also have heard of this by the name saved text.

Of course, setting the sticky text bit on a program image is something that has to be done with care. What programs benefit from it depend from what the machine is generally used for. And currently unattached text segments take up kernel resources, meaning that there is a practical limit to how many one can have in any system. So it is generally an operation that requires superuser privileges.

desuetude

There is a whole load of assumptions that underlies the operation of sticky text, that just aren't true any more. Reading a pre-made segment from swap storage isn't necessarily faster than simple demand paging in from the actual executable image file. Filesystem formats became better for random (as opposed to sequential) reading patterns. The advent of demand paging itself changes things, as do things like unified caches, non-idempotent external fixups resulting from differences in shared library search, and address space layout randomization.

The days of sticky text bits for executable program images are long gone. An explicit sticky text marker flag for executable program images was considered obsolete by the writers of 4.3BSD in the mid-1980s, for example.

Further reading

  • Maurice J. Bach (1986). The Design of the UNIX Operating System. Prentice-Hall. ISBN 9780132017992.
  • 1
    Very nice answer! Today I learned something. :) – Andreas Wiese Jun 30 '16 at 18:58
  • Me too :) This sounds a lot like what I used to know as a TSR in the DOS days - "terminate and stay resident". However, that was usually for things like device drivers that other processes that run later need to call, and probably obsolete when the world moved to multi-threaded/multi-process OSes. – Steve Jun 30 '16 at 20:57
  • 1
    This is an awesome answer. Where can I read about the genesis of bss? – cat Jun 30 '16 at 23:46
  • 1
    TSRs are not really analogous. For analogues in the IBM+Microsoft world, look to DOS+Windows 3.x in Standard Mode and 16-bit OS/2 version 1.x. The CODE segments (and on OS/2 read-only DATA segments) of EXEs and DLLs are (usually) shared amongst all running programs. There's no real equivalent of "stickiness", in part because 32-bit OS/2 version 2.x and 386 Enhanced Mode replaced segment swapping with demand paged virtual memory, just as the Unix world had several years earlier, in both arenas affecting the need for segmentation stickiness in much the same way. – JdeBP Jul 1 '16 at 12:08
  • 3
    @JdeBP: The question "Was the sticky bit like setuid?" is rather broad and imprecise.  I would argue that the answer is "Well, somewhat; it's complicated" because the low-order nine bits were and are similar: they affect whether certain users may perform certain operations on a file.  And the set-UID, set-GID and sticky bits were similar in that they didn't relate to whether an operation was permitted, but instead moderated some aspect of how it (specifically, the execute operation) was performed. – G-Man Jul 18 '16 at 4:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.