Shell Command that Combines chmod and chgrp - linux

Is there a combine variant for chmod and chgrp that sets both permissions and groups in one single system call for each file?

There is no such a variant because the two operations chmod(2) and chown(2) are implemented by distinct system calls.
Getting away with chmod and chown
You might be looking for such a variant of chmod and chown because of security issues. If this is the case, you can use the following strategy:
Strip mode flags to a very conservative set (possibly empty) on the target file.
Change owner and group of the target file.
Give the target file the desired mode flags.
This way you avoid potential security issues associated to successive calls to chmod and chown or to chown and chmod.
The install/open trick
The only system call setting mode flags and ownership information at the same time might be open(2). So, you could use a process impersonating the target owner opening the file with the appropriate mode. This is probably what install does, so if this is an option:
Rename the old file.
Copy the old file to the new file with the desired ownership and access mode information using the install command.
Delete the old file.
Doing this will break hard links, however. The solution based on chown and chmod does not have that issue.

AFAIK, no.
Furthermore, since the file access mode and owner / group information are set using different syscalls (see man 2 chmod and man 2 chown), I don't think it would be possible to implement such a command ... at least on a mainstream Unix-like system.
(Obviously, one could modify a GNU/Linux kernel to add a combined system call, but then the hypothetical command that used the syscall wouldn't be portable.)

Related

Linux Permissions - setuid, setgid, sticky bit - remove all with one command

I'm currently doing a course on Linux Essentials, and recently I came across the setuid, setgid and sticky bit permissions.
I tried to make a practical example and run the commands to apply them on a file and a directory that I created.
I noticed that the numeric command to remove them is 'chmod 0775 ', and I thought, if all three are applied, what happens if I run the numeric command to remove them. I supposed that it would remove them sequentially but in the case of the file, it removed all of them at once.
Then I tried on the directory. The result was different there. Only the last applied permission (which was the Sticky Bit) was removed. I run the command once more and didn't do anything. None of the remaining permissions (setuid, setgid) was removed.
Why is this happening?
Thanks!
Sticky bits for files and directories are slightly different...
For example, to remove the stick bits from a directory called "Testy" you would type:
sudo chmod g-s Testy/
Note that typing the following WOULD NOT WORK:
sudo chmod 777 Testy.
This below tutorial gives good worked examples and explanations, my advice would be to practice some of these examples a good few times and then it will all eventually make sense. The key thing to understand (in my opinion anyway) is the Octal system involved here in setting the permissions/bits etc, once you understand that it all falls into place.
Here is the Tutorial Link: Access Control / Sticky Bit Tutorial
A quick search in man chmod revealed that you need to append an extra 0 or = in front. For instance like this:
chmod 00775 target
or like this:
chmod =775 target
If you want to remove setuid, setgid and sticky permissions for all files recursively you can use this command:
chmod -R 00775 {.,.*}

How to set folders permissions in linux?

I am supposed to give write/edit permission to my directory in /var/lib/mysql/dbname via Linux.
I am unaware of backend UI and i know i just enetered the text "sudu so" # centos machine which displays :
[root#ip-10-0-0-61 centos]#
Can anyone tell how to proceed further as I have always been using WinScp which restricts me to write database files due to present set permissions.
Any user interface file manager that could do this would be really helpful too.
Thanks in advance
You can change files/folders permission with the chmod command. There's a man page here. The full command line to type depends on which permission you exactly need. A basic usage of the command is
chmod [ugoa][+-=][rwx] file
Where
[ugoa] allow you to choose whose permission you want to modify: the owner of the file (u), users member of the group of the file (g), any other users (o) and all users (a)
[+-=] allow you to tell the command if you want to add (+) the selected permissions, remove them (-) or set them as the only permissions of the file(=).
[rwx] allow you to choose the permission : read (r), write (w) or execute (x). There exist other type of permissions explained in the man.
To change the permission of a folder recursively, you can add the option -R to the command.
Very simple just execute the command
chmod 777 -R ./
This will do the trick for you.
There are two things to look at, setting permissions, and ownership.
To do this for an entire directory (be careful with this)
chmod -R {permissions} {directory}
If you're unsure what permissions to use check this guide
To set ownership, use
chown {user:group} {directory} -R
Again be careful with these settings. It's not often you'll want an entire directory full of files to all have the same permissions, and you could be opening yourself up to risks if you do so. Always be explicit and give each file the minimum permissions needed to get the job done.

Prevent a Unix domain socket file in the filesystem from being deleted while socket is bound

Is it possible on Linux or MacOSX to prevent a Unix domain socket file (e.g. in /tmp) that is currently bound from being deleted? I want a mode 0777 socket that users can connect to but that users cannot delete while the daemon is running.
Right now a normal user can 'rm' the socket, preventing anyone else from accessing it until the daemon is restarted. Seems like it should be 'busy' if it's bound.
You could make a new subdirectory and set read only permissions on the directory after you make the socket:
mkdir /tmp/blah
cd /tmp/blah
# do stuff to create /tmp/blah/socket
chmod 555 /tmp/blah
rm /tmp/blah/socket
rm: cannot remove /tmp/blah/socket: Permission denied
(or the equivalent to that from C / your language of choice)
It depends entirely on the directory that contains the socket. /tmp is somewhat special in that it has the "sticky bit" set on the directory (if you execute ls -ld /tmp you will see the permissions field is usually: drwxrwxrwt or, more usefully, mode 1777. That sticky bit (the t at the end) is important when set on a directory. Quoting man chmod:
The restricted deletion flag or sticky bit is a single bit, whose interpretation depends on the file type. For directories, it prevents
unprivileged users from removing or renaming a file in the directory unless they own the file or the directory; this is called the re‐
stricted deletion flag for the directory, and is commonly found on world-writable directories like /tmp. For regular files on some older
systems, the bit saves the program's text image on the swap device so it will load more quickly when run; this is called the sticky bit.
This is exactly what you want - file-system level protection against a user removing the file. It is also 100% portable to all modern UNIX-like environments.
So, if you are creating your endpoint in /tmp you already have the protections you want. If you want to create the endpoint elsewhere, for example /opt/sockets, simply chmod 1777 /opt/sockets. The last part of the "trick" to getting the protections you want is to ensure that the root user is the actual owner of the endpoint. If the endpoint is owned by user fred then fred will always be able to delete the endpoint, which may well be a desirable thing. But if not, simply chown root:root /path/to/endpoint.

Symbolic links to folders whose parent directory has no execute permission

I am trying to do a soft link from one directory to another, the directory I am trying to access I have read and execute. However, its parent directory I do NOT have execute permissions.
Is there a way to do a soft link, to my desired directory without giving me execute permission to the parent directory?
Below is the code I used:
ln -s /home/dir1/dir2/desired_directory symbolic_link_name
the link just comes up as red with grey background.
Thank you.
Although this is not possible with symlinks, you could do it with mount --bind. Note that if the whole point is to circumvent security, then this is probably a very bad idea.
Your command would be
mount --bind /home/dir1/dir2/desired_directory mount_dir
There are a few issues to be aware of:
The target directory mount_dir must exist before (same as any mount point)
Root access is required to execute the mount commmand
The created "link" will not persist after a reboot unless a corresponding line is added to /etc/fstab
If the origin directory contains mounted file systems, these will not be transferred to the target. The mount points will appear as empty directories.
Using mount --bind may be considered bad practice because most programs are not aware that the "link" is not a standard directory. For instance it allows the creation of loops in the directory tree which make any tree parsing application (think "ls -R") enter a possibly infinite loop.
It may be hazardous when combined with recursive delete operations. See for instance Yet another warning about mount --bind and rm -rf.
Symbolic links are not a way to circumvent permissions set on their targets. No, there is no way to do what you want. If it was possible it would be a serious security issue.

Setting default permissions for newly created files and sub-directories under a directory in Linux?

I have a bunch of long-running scripts and applications that are storing output results in a directory shared amongst a few users. I would like a way to make sure that every file and directory created under this shared directory automatically had u=rwxg=rwxo=r permissions.
I know that I could use umask 006 at the head off my various scripts, but I don't like that approach as many users write their own scripts and may forget to set the umask themselves.
I really just want the filesystem to set newly created files and directories with a certain permission if it is in a certain folder. Is this at all possible?
Update: I think it can be done with POSIX ACLs, using the Default ACL functionality, but it's all a bit over my head at the moment. If anybody can explain how to use Default ACLs it would probably answer this question nicely.
To get the right ownership, you can set the group setuid bit on the directory with
chmod g+rwxs dirname
This will ensure that files created in the directory are owned by the group. You should then make sure everyone runs with umask 002 or 007 or something of that nature---this is why Debian and many other linux systems are configured with per-user groups by default.
I don't know of a way to force the permissions you want if the user's umask is too strong.
Here's how to do it using default ACLs, at least under Linux.
First, you might need to enable ACL support on your filesystem. If you are using ext4 then it is already enabled. Other filesystems (e.g., ext3) need to be mounted with the acl option. In that case, add the option to your /etc/fstab. For example, if the directory is located on your root filesystem:
/dev/mapper/qz-root / ext3 errors=remount-ro,acl 0 1
Then remount it:
mount -oremount /
Now, use the following command to set the default ACL:
setfacl -dm u::rwx,g::rwx,o::r /shared/directory
All new files in /shared/directory should now get the desired permissions. Of course, it also depends on the application creating the file. For example, most files won't be executable by anyone from the start (depending on the mode argument to the open(2) or creat(2) call), just like when using umask. Some utilities like cp, tar, and rsync will try to preserve the permissions of the source file(s) which will mask out your default ACL if the source file was not group-writable.
Hope this helps!
It's ugly, but you can use the setfacl command to achieve exactly what you want.
On a Solaris machine, I have a file that contains the acls for users and groups. Unfortunately, you have to list all of the users (at least I couldn't find a way to make this work otherwise):
user::rwx
user:user_a:rwx
user:user_b:rwx
...
group::rwx
mask:rwx
other:r-x
default:user:user_a:rwx
default:user:user_b:rwx
....
default:group::rwx
default:user::rwx
default:mask:rwx
default:other:r-x
Name the file acl.lst and fill in your real user names instead of user_X.
You can now set those acls on your directory by issuing the following command:
setfacl -f acl.lst /your/dir/here
in your shell script (or .bashrc) you may use somthing like:
umask 022
umask is a command that determines the settings of a mask that controls how file permissions are set for newly created files.
I don't think this will do entirely what you want, but I just wanted to throw it out there since I hadn't seen it in the other answers.
I know you can create directories with permissions in a one-liner using the -m option:
mkdir -m755 mydir
and you can also use the install command:
sudo install -C -m 755 -o owner -g group /src_dir/src_file /dst_file

Resources