I need to have a file with 666 permission. So, I tried the following with umask and ended up with different permission.
umask(111);
int fd = open(".sample", O_CREAT | O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
-rw--w---- Sep 2 13:19 .sample
I was expecting 666.
Did I use umask in a wrong way? Can someone please help me.
Related
I stumbled upon this construction:
((($(stat -c '0%#a' "$FILE_PATH") & $(stat -c '0%#a' "${FILE_PATH%/*}") & 0007) == 0))
I understand that first parenthesis part returns file permission bits in octal, and second path returns file's folder (everything in Linux is a file) permissions. But what is the last bitwise operation for? Is it check for some vulnerability?
I see that first stat -c "0%#a" file returns 00640 and stat -c "0%#a" file_path returns 00640, with 0007 the whole expression 00640 & 00640 & 0007 = 0, but what does it mean concerning to Linux file permissions?
stat -c '0%#a' "$FILE_PATH" gets the permissions of your file itself, with a leading 0 to ensure that they're interpreted in octal.
stat -c '0%#a' "${FILE_PATH%/*}" gets the permission of the directory that contains that file.
ORing together the above results us tells us which permissions either of the above have, whereas ANDing them tells us which permissions both have. The above logic does a bitwise AND, but it would be safer / more secure if it did a bitwise OR.
0007 looks only at "other" permissions: Whether users who are neither the owner nor in the group have any read, write or execute. ANDing with this set tells us if the result of the above operation includes any permissions applicable to users who neither own or share a group with the file or directory.
As currently written, by ANDing together the directory and file permissions, and then ANDing that with 0007, we check if both the file and directory are readable, writable, or executable by users who don't have any ownership interest; but we miss cases where the directory is readable/writable/executable but not the file, or the file but not the directory.
If this were fixed, by ORing together the file and directory permissions and then ANDing the result with 0007, the net effect is to check whether the file or its containing directory can be read, written, or executed (for the directory, cd'd into) by users who neither own nor are in the group that owns that filesystem object.
What do these file permissions mean? I am unable to understand them i tried looking at the 0-7 meanings but im unsure when they are together.
-r-------x
----rw----
-rwx--x--x
File permissions
Linux uses the same permissions scheme as Unix. Each file and directory on your system is assigned access rights for the owner of the file, the members of a group of related users, and everybody else. Rights can be assigned to read a file, to write a file, and to execute a file (i.e., run the file as a program).
To see the permission settings for a file, we can use the ls command as follows:
[me#linuxbox me]$ ls -l /bin/bash
-rwxr-xr-x 1 root root 316848 Feb 27 2000 /bin/bash
CHMOD
The chmod command is used to change the permissions of a file or directory. To use it, you specify the desired permission settings and the file or files that you wish to modify. There are two ways to specify the permissions, but I am only going to teach one way.
It is easy to think of the permission settings as a series of bits (which is how the computer thinks about them). Here's how it works:
rwx rwx rwx = 111 111 111
rw- rw- rw- = 110 110 110
rwx --- --- = 111 000 000
and so on...
rwx = 111 in binary = 7
rw- = 110 in binary = 6
r-x = 101 in binary = 5
r-- = 100 in binary = 4
Here is a table of numbers that covers all the common settings. The ones beginning with "7" are used with programs (since they enable execution) and the rest are for other kinds of files.
Directory permissions
The chmod command can also be used to control the access permissions for directories. In most ways, the permissions scheme for directories works the same way as they do with files. However, the execution permission is used in a different way. It provides control for access to file listing and other things. Here are some useful settings for directories:
Permissions as numbers are 3 octal numbers. 555, for example, when converted to 3 binary numbers is 101 101 101 which would correspond to r-x r-x r-x. The first set is owner, second set is group, third set is everyone else.
r = read
w = write
x = execute
If any of those are missing (-), then that set does not have those permissions.
From left to right, linux filesystem permissions are flags grouped in 3s
User (owner), Group, All
rwx------ = User can Read, Write, Execute
---rwx--- = Group can Read, Write, Execute
------rwx = All can Read Write, Execute
(I did not mention the flags for directory or setuid, on purpose)
etc
Next, you do not need to memorize numeric values for doing the setting
Use chmod with mnemonics
chmod a+r set the file such that All can Read
chmod g+r set the file such that Group can Read
chmod u+x set the file such that User can Execute
It's also
owner|group|all
-r-------x
owner can read, group can do nothing, others can excecute
----rw----
owner can do nothing, group can read and write, others can do nothing
-rwx--x--x
owner has full permission, group can execute, others can execute.
the first - is for special permissions such as sticky bit.
Here's a site that may help you.
I just changed my file permissions using $ sudo chmod g+s filename and my file permissions turned from drwxr-xr-x to drwxr-sr-x. How do I remove it?
Change the + for adding a permission into a - to remove it:
sudo chmod g-s filename
If you want to do this programatically, you’ll need to use some bitwise operators. Normally it’s
mode_without_suid = bitwise_and(existing_mode, bitwise_not(S_ISUID))
where S_ISUID is 0o4000, a constant that uses mode bits above the typical rwx ones of something like 0644.
For example, in python
import os
import stat
def mode_details(m):
return f"mode={oct(m)} = {stat.filemode(m)}"
mode = os.stat('foo').st_mode
print("old mode", mode_details(mode))
new_mode = mode & ~stat.S_ISUID
os.chmod('foo', new_mode)
print("new mode", mode_details(new_mode))
which prints
old mode mode=0o104654 = -rwSr-xr--
new mode mode=0o100654 = -rw-r-xr--
To remove setgid the numerical way the command is
sudo chmod 0664 $filename
The assumption here is the permission on file is 664 and we are not changing it. The left most bit in the above command represents setuid(4),setgid(2) and sticky(1). Now to represent these symbolically setuid is u+s, setgid is g+s and sticky is o+t
Example 1:-chmod u+s filename
This will setuid for the filename mentioned that is rwsr_xr_x
Example 2: chmod 2770 directory
This will set gid for the directory mentioned that is rwxr_sr_x
Regarding: "you can set (but not clear) the bits with a numeric mode"
On RHEL 7 chmod 0644 $filename did not remove the setuid(4),setgid(2) or sticky(1).
However precedeing with an extra 0 did the trick:
chmod 00644 $filename
Well would just like to add few points to clarify the approach of working with the numerical way for both files and directories.
Adding individual special permissions for either user/group/others.
chmod "X"755 file
Where X is the specific octal numeric mode for special permissions.
If you want to add multiple special permissions at a time, e.g. for both suid(4) and sgid(2) i.e. 4+2=6.
chmod "6"755 file
for suid(4), sgid(2) and sticky bit(1), i.e. 4+2+1=7
chmod "7"755 file
Deleting all special permissions (only applicable for a file)
chmod 00"0"755 file
Well, the trailing zeros before 4 digits doesn't add any values while changing the permission for a file but it does add values while changing permission for a directory.
The above numeric code will change the permission to 755 from 7755 only for a file but if you do the same for a directory it will be 6755 as it will only remove the sticky bit for others.
To remove all the special permissions for a directory.
chmod "000"755 file
Similarly, to remove suid permission and having sgid(2) and sticky bit(1) i.e. 2+1=3.
chmod 00"3"755 file
And solution using letters(r,w,x,X,s,,t) and operators(+/-) were already discussed and approved in the earlier answers.
sgid with number
#chmod 2(permission) (directory name) = for adding
#chmod 0(permission) (directory name) = for removing
sgid with word
#chmod g+s directory name = for adding
#chmod g-s directory name = for removing
I want to check whether a file on Linux has permission 555, but the file has a 755 permission instead.
So I do a boolean AND in my program:
if ((perm_of_file && perm_required) == 555)
i.e. (755 && 555 == 555)
Should this evaluate to true?
I know this is not intuitive from a programming prospective and the real background question is:
Is 755 considered as a "member" of the 555 permission group?
What I tried:
I use find -perm 555 on Linux and it doesn't list those files who has 755 permission, so I am guessing the answer to the question is NO?
If somebody can help me answer or rephrase this question, that would be very helpful.
Thanks in advance!
((file_mode && some_bits) == some_bits) # is logical and, you need bitwise and
((file_mode & some_bits) == some_bits) # is bitwise and
file modes are (still) expressed in octal notation, in most C-like languages you'll need to add a leading zero to indicate octal mode
command-line programs (such as chmod or find) don't need the leading zero, they expect the numerical mode-string to be octal
find . -mode xxx # finds files with exactly the mode xxx
find . -mode -xxx # finds files with at least the mode bits xxx set
The answer is no.
Because in 755 the owner of the file has write permission and in 555 owner has no write permission. (Although owner can change it with chmod because he's the owner!).
As I see you want to check whether one permission is inclusive in another one. If you somehow have the permissions of the files, then simply check:
if (perm_of_file >= perm_required)
How can I check the umask of a program which is currently running?
[update: another process, not the current process.]
You can attach gdb to a running process and then call umask in the debugger:
(gdb) attach <your pid>
...
(gdb) call umask(0)
[Switching to Thread -1217489200 (LWP 11037)]
$1 = 18 # this is the umask
(gdb) call umask(18) # reset umask
$2 = 0
(gdb)
(note: 18 corresponds to a umask of O22 in this example)
This suggests that there may be a really ugly way to get the umask using ptrace.
Beginning with Linux kernel 4.7, the umask is available in /proc/<pid>/status.
From the GNU C Library manual:
Here is an example showing how to read the mask with umask
without changing it permanently:
mode_t
read_umask (void)
{
mode_t mask = umask (0);
umask (mask);
return mask;
}
However, it is better to use getumask if you just want to read
the mask value, because it is reentrant (at least if you use the
GNU operating system).
getumask is glibc-specific, though. So if you value portability, then the non-reentrant solution is the only one there is.
Edit: I've just grepped for ->umask all through the Linux source code. There is nowhere that will get you the umask of a different process. Also, there is no getumask; apparently that's a Hurd-only thing.
If you're the current process, you can write a file to /tmp and check its setting. A better solution is to call umask(3) passing zero - the function returns the setting prior to the call - and then reset it back by passing that value back into umask.
The umask for another process doesn't seem to be exposed.
A colleague just showed me this command line pattern for this. I always have emacs running, so that's in the example below. The perl is my contribution:
sudo gdb --pid=$(pgrep emacs) --batch -ex 'call/o umask(0)' -ex 'call umask($1)' 2> /dev/null | perl -ne 'print("$1\n")if(/^\$1 = (\d+)$/)'