-9

I understand that in GNU/Linux, file permissions are also called a file's mode and that the term "umask" can mean at least these different meanings:

  1. The umask shell builtin command (the usual meaning).
  2. The builtin-command's corresponding system call.
  3. A shell process-value also referred to as file creation mask, as well as bitmask or just mask.
  4. A user-specific file creation mask effecting processes unique to that user (then it called a user mask - a user's file creation mask).

By executing the umask command with a proper argument we set the mask for our current shell process tree; either for all users in the current shell process tree, or for our own user solely. Yet, generally, any such changes will be inherited to new processes, possibly of another shell).

Mathematical logic includes the operation of conjunction A.K.A "anding" () occuring when "The and of a set of operands is true if and only if all of its operands are true". There's an identically named bitwise operation based on that logic. Anding is different than addition of numbers (x + y → z) or concatenation of strings (x alongside y → xy).

I understand that one can "mask a mode" this way:

  OCTAL  BINARY       HUMAN-READABLE
  0666   0110110110  -rw-rw-rw-
∧ 0555   0101101101  -r-xr-xr-x
  0444   0100100100  -r--r--r-- 

My question

What is the meaning "masking a mode" and how come 0666 ∧ 0555 → 0444?

closed as unclear what you're asking by muru, Thomas, Isaac, G-Man, Mikel Nov 26 '18 at 3:54

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

locked by terdon Dec 3 '18 at 19:48

This post has been locked while disputes about its content are being resolved. For more info visit meta.

Read more about locked posts here.

11
+150

umask, the shell command, and umask, the function, both set the file creation mask, which is also known as the umask.

You’ve rephrased this as

A umask means both a shell builtin command and a shell function that bases that command and contains a variable commonly referred to as file creation mask with a value referred to as bitmask or just mask.

which is incorrect on a number of counts:

  • the umask function isn’t a shell function; see the link above;
  • the function doesn’t contain a variable; it sets the current process’s file creation mask;
  • the value acted upon isn’t just commonly referred to as “file creation mask”, it is the file creation mask (and its value isn’t referred to as “bitmask” or “mask”).

A mask effects some utilities in the current process tree including other shells where it can be changed (hence shell Y won't necessarily have the mask of shell X).

A mask doesn’t affect anything in general. The file creation mask affects the current process and is inherited by all newly created child processes. Child processes are free to change it themselves again.

This file creation mask acts on the permissions of newly created files. File permissions, also known as the file mode, are a set of twelve bits encoding the access rights of the file’s owner, group, and other users; see this canonical answer for details. They are typically represented as a four- or three-digit octal value. They aren’t a stream of bits.

The permissions of newly created files are either specified by the program which is creating a given file, or specified by default (i.e. specified by the function they use to create files). Examples of the former include programs which create files (or directories) using open or creat or mkdir, which have to explicitly specify the mode they want. Examples of the latter include programs which use fopen, where files end up with the default 0666 mode. The current umask value masks this mode.

You rephrased this as

  1. Some utilities like mkdir creates a file with a standalone mode (the mask is ignored).
  2. Some utilities use the fopen() function, where files are first created with the default 0666 mode but umask changes their mode as to that of the mask right after their creation.

which is incorrect on a number of counts:

  • the mask is applied to the requested mode before the file is created, not afterwards;
  • mkdir (which is a function here, not a utility, but the same applies to the utility of the same name) most certainly does not ignore the file creation mask.

When umask is taken into account, the resulting mode is the result of applying umask as a bitmask to the requested mode: each bit set in the requested mode is checked against the corresponding bit in umask, and preserved only if the latter isn’t set. In terms of binary operations, the requested mode is bitwise-anded with the complement of the umask. Thus a umask of 0022 with a mode of 0666 results in 0644; not by subtraction, but because 0666 & 0755 (0022’s complement) is 0644. Likewise, a umask of 0011 with a mode of 0666 results in 0666.

Let’s look at the calculation in more detail. It’s often represented as a subtraction, including in the answer you linked to, but it’s important to understand that it isn’t; umask is applied as a mask. A value of 0022 is applied thus:

       Octal Binary
Mode   0666  000110110110
Mask   0022  000000010010  Bits set here mask bits above
Result 0044  000110100100

       Octal Binary
Mode   0644  000110100100
Mask   0022  000000010010
Result 0644  000110100100

This is usually calculated by bitwise-anding the mode with the mask’s complement:

       Octal Binary
Mask   0022  000000010010
Compl. 7755  111111101101
Mode   0666  000110110110
Result 0644  000110100100

chmod applies the mode specified on its command-line without taking umask into account. Other tools do this too, even when creating files; thus cp and tar, when instructed to preserve permissions, will copy permissions or restore permissions without taking umask into account.

This answer goes into more detail.

Your final questions are

Is my understanding accurate enough and how come 0666 ∧ 0555 → 0444?

The answer to the first is apparently not. The answer to the second is because that’s how bitwise and works. Rewrite the operands in binary:

Octal  Binary
0666   000110110110
0555   000101101101

Now perform a bitwise and on each bit position. This means taking each vertically-aligned pair of bits, and and them (in the above example, 0 ∧ 0 three times, then 1 ∧ 1, 1 ∧ 0, 0 ∧ 1, 1 ∧ 1 etc.):

       000100100100

(0 ∧ 0 is 0, 0 ∧ 1 is 0, 1 ∧ 0 is 0, 1 ∧ 1 is 1). Convert the above back to octal, and you end up with 0444.

8

What the mode is

The term “mode of a file” refers to the standard file permissions available on Linux systems (not considering access control lists, which are a different breed ).

A file's mode is made up of 12 bits, each representing one permission which may be given or not (so a bit is enough to indicate that).
E.g., the permission “File may be read by group members” is the 6th bit from the right.

For ease of use, these 12 bits are partitioned into 4 groups of 3 bits each. A 3-bit binary number can take on 8 different values, which is exactly the same amount of values an octal digit (0–7) can represent.
So the twelve permissions can be represented as a 4-digit octal number in the range 0–7777.
To make it slightly more confusing, it is common to indicate an octal number with an additional leading zero (just as hex numbers are prefixed with 0x by convention), so the modes are 0–07777.

To make it easier: In most cases you'll be interested in the low nine bits only, so I'll focus on 0–0777 from here on.

Why is it written in octal

Why use the octal system? It makes it easier to read the mode!

The lowest nine bits of the mode represent the following permission bits, in that order. Instead of the binary representation, I'll show the value of the respective bit in octal (copied from chmod(2)):

00400 read by owner
00200 write by owner
00100 execute/search by owner
00040 read by group
00020 write by group
00010 execute/search by group
00004 read by others
00002 write by others
00001 execute/search by others

See the pattern? 1 always represents execute/search, 2 is always write, and 4 is always read. If read and execute are allowed, but not write, it's always the digit 5, all 3 permissions read/write/execute together is always 7. For a comparison, have a look at the decimal values:

Allow read/execute for others:          0005, decimal   5.
Allow read/execute for group:           0050, decimal  40.
Allow read/execute for owner:           0500, decimal 320.
Allow read/execute for owner and group: 0550, decimal 360.
Allow read/execute for all, write
only for owner:                         0755, decimal 493.

So octal makes it a bit more consistent: The position of the digit is owner/group/others, and the digit tells you all about the three read/write/execute bits.

What the umask is

The umask is a property of a process (i.e., a running program, e.g., your shell) and each process has one. It determines the permissions not to be set when that process creates a new file. The shell command umask sets the mask of the shell. When this shell launches another program, then that inherits the umask from the calling shell. So setting a umask in one shell will not affect other programs, unless they are descendants of the first shell and were created after setting the umask. That's why the umask should be set by a script very early in your session.

No matter what other people say, use 077 ;-)

When a new file is created, the by a program, the program passes the desired permissions to the open(2) system call. The OS removes the bits set in the umask, and the result is used to create the file. You can use the following C program for testing this:

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include <stdio.h>

int main(int argc, char **argv) {

    // check for enough command line arguments
    if (argc < 3)
        errx(1, "Usage: %s <filename> <octalmode>", argv[0]);

    // parse 2nd argument as octal integer
    char *endptr = NULL;
    int mode = (int)strtol(argv[2], &endptr, 8);
    if (!*argv[2] || *endptr || mode < 0)
        errx(2, "Not an octal mode: %s", argv[2]);

    // create new file with given mode
    int fd = open(
        argv[1],
        O_WRONLY|O_CREAT|O_EXCL,
        mode
    );
    if (fd < 0)
        err(1, "Failed to create file %s", argv[1]);

    printf("open(\"%s\", ..., 0%03o) successful\n", argv[1], mode);

    close(fd);

    return 0;
}

Compile:

$ gcc -o mkfile mkfile.c

Follow along this example:

$ umask 77   # set umask to 0077
$ umask      # check umask
0077
$ rm -f foo           # delete old to make sure a new file will be created
$ ./mkfile foo 660    # create file `foo` with mode 0660
open("foo", ..., 0660) successful
$ ls -l foo
-rw------- 1 sk users 0 Nov  6 12:09 foo

Note how the program requested permissions rw-rw----, i.e., mode 0660, but the group's permissions were entirely stripped by the umask.

umask:                              0077    000 000 111 111
umask bitwise negated:             07700    111 111 000 000
open's argument:                    0660    000 110 110 000

(open's argument) AND (NEG umask)   0600    000 110 000 000

In general, a program should suggest what permissions it deems useful in the most permissive case, and leave the stripping of permissions to the OS's umask. So use 0777 when creating a directory with mkdir(2), use 0666 when creating a plain file with open(2). Deviate only when this makes sense, e.g., an encryption tool may use open with 0600 to store its private key, and a compiler may use 0755 for the executable binary it creates. In all these cases, the umask will strip unwanted permissions from the file when it is actually created.

Here's an example of the compiler trying to create a file with that is readable and executable by everybody, but writeable only by the user (mode 0755) in a setting with umask 077:

$ rm -f foo
$ umask 77
$ ./mkfile foo 0755
open("foo", ..., 0755) successful
$ ls -l foo
-rwx------ 1 sk users 0 Nov  6 12:15 foo

And in a setting with umask 0 (allow all bits requested by the program):

$ rm -f foo
$ umask 0
$ ./mkfile foo 0755
open("foo", ..., 0755) successful
$ ls -l foo
-rwxr-xr-x 1 sk users 0 Nov  6 12:16 foo

Actually, the gcc will even request mode 0777:

$ umask 0
$ rm -f mkfile
$ gcc -o mkfile mkfile.c
$ ls -l mkfile
-rwxrwxrwx 1 sk users 17k Nov  6 12:19 mkfile

So do not use umask 0.

2

In Linux the default file permission is 0644, default directory permission is 0755 and default umask is 0022.

Now, as the full permission of a file is 0666, the default permission came from (0666 - 0022 = 0644) and for directory it is (0777 - 0022 = 0755).

You can set the mask using #umask 0000, and it will create files and directories with full 666/777 permission (which is very insecure though).

0

I'm having trouble understanding what is umask in GNU/Linux

Ok.

as well as calculating it with anding.

I have given you the formula:

mode=$(printf "%04o\n" "$(( (8#$default) & (~(8#$umask)) ))")

with default=0666 and umask=0022 you get:

$ printf "%04o\n" "$(( (8#0666) & (~(8#0022)) ))"
0644

In Linux, umask means both a shell builtin command and a kernel function that changes a system value usually named file creation mask A.K.A bitmask or just mask, called by the builtin with an argument.

Should be written as:

In linux, umask is the name of a shell builtin, the name of a kernel function and the name of a process value. Both the builtin and the function could change the process value.

  • It is not a system value. Each process has one umask which is copied to its childs.
  • The process value is not usually named file creation mask, it is the file creation mask.
  • It is not called bitmask or mask.

The mask effects some sub-processes in the current process tree including other shells where it can be changed (hence shell Y won't necessarily have the mask of shell X).

The umask affects the process were it is defined, and the childs that are started from it.

  • each child can change its own umask.

File permissions, also known as a file's mode, are a set of twelve binary bits encoding the access rights of the file’s user, group, and other users, for that file (ugo → a stream of say bbbbbbbbbbbb).

File mode is a number (12 binary digits or 4 octal digits or 3 hexadecimal digits)

$ bc <<<'ibase=8; mask=1644; obase=2; mask; obase=8; mask; obase=16; mask'
1110100100
1644
4A8

Yet file permissions are typically represented as a four-to-three digit octal value instead (for example - 0644 or 644).

Mode is a number with three or four digits.
Like 123 and 0123 is the same decimal number.

Mathematical logic includes the operation of conjunction A.K.A "anding" (∧) which takes place when "The and of a set of operands is true if and only if all of its operands are true". There's an identically named bitwise operation based on that logic.

Ok.

Anding is different than addition of numbers (x + y → z) or concatenation of strings (x alongside y → xy).

Ok.

Setting modes without or with umask (by its mask)

Mode is always set using the umask.

Some utilities like mkdir creates a file with a standalone mode, without utilizing umask (hence the mode of these files isn't masked).

No, umask is always in effect.

Some other utilities create files with some "masked" permissions (that is, the permissions are resulted by the mask). For example, utilities creating files using the fopen() function where mask is first recognized and then the file is created with permissions that are based on it.

The mode is the result of:

mode=$(printf "%04o\n" "$(( (8#$default) & (~(8#$umask)) ))")

Masking a mode is done by bitwise-anding and results as follows:

Mode is the result of anding the default with the negated umask.

             OCTAL  BINARY        HUMAN-READABLE
umask        0222   000010010010  --w--w--w-
not-umask    7555   111101101101  N/A
default    ∧ 0666   000110110110  -rw-rw-rw-
result       0444   000100100100  -r--r--r-- 

Is my understanding accurate enough and how come 0666 ∧ 0555 → 0444?

There are several issues to improve, and only the anding (without negation) is:

0666 → 0 011 011 011
0555 → 0 101 101 101

If you match vertically those binary digits, follow this rules: - if they are equal, write another equal digit below - if they are different, write a zero below.

0666 → 0 110 110 110
0555 → 0 101 101 101
       0 100 100 100
       0  4   4   4
0444 → 0 100 100 100
0

The umask is the “file mode creation mask”: umask ≡ “file mode creation mask” It is a process value. Each process has their own value, but inherits from its parent. The umask value is stored in the kernel, and survives across fork and some forms of exec.

umask is a type of bitmask: set of umasks ⊂ set of bitmasks

There are many types of bitmask.

  • mask: something that covers something else, so that only parts can be seen. E.G. in painting a shaped mask can be used, to allow a person to spray a pattern, cut into the mask.
  • bit mask: a set of bits that are used to mask another set of bits. A bit mask will clear or set the bits that are covered. To do this you can use bitwise and or or.

To say another way.

File mode creation mask is the same as a umask, but Not the same as a mask. In the same way that a black cat is not the same as a cat. They are both cats, but not both black cats. There are many cats, in many colours. There are many bitmasks, used for many things.

Logical masking

0666 ∧ 0555 = 
110110110 ^ 010010010 =
0444

^ means “and”, it works on bits. So first you have to convert the octal to binary. Then you have to apply the operation on each bit in turn.

0 ^ 0 = 0
0 ^ 1 = 0
1 ^ 0 = 0
1 ^ 1 = 0

Copied on request of OP, from duplicate question (OP to remove duplicate).

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