Automatically assign permissions to any file copied into directory - linux

I have a directory and I'd like for any file added to that directory to automatically have chmod performed with a specific set of permissions.
Is there a way to do this?

Reacting to filesystem events (in linux) can be done using inotify.
There are many tools built on inotify which allow you to call commands in reaction to file system events. One such tool is incron. You might like it since it can be configured in a way similar to the familiar cron daemon.
Files moved into a monitored directory generate an IN_MOVED_TO event.
So the incrontab file would contain an entry like
/path/to/watch IN_MOVED_TO /bin/chmod 0644 $#

You can create a cron that checks/chmods files in that directory.
Something like this will work:
find /path/to/directory -type f -print0 | xargs -0 chmod 0644
(Of course you have to edit the path and set the permissions you need)

The question is too unspecified and it is dangerous to give any answer as it is.
Who (/what) creates files in aforementioned directory? What rights do you want to set and why do you think this is needed? Why whatever creates them cannot put expected rights on its own?
For instance, all these "find | chmod" or inotify watchers and other tools mentioned in other comments are a huge security hole if this is a directory everyone can put files to and such a chmoding command would be run with root privs, as it can be tricked into a following a symlink and chmoding stuff like /etc/shadow.
This /can/ be implemented securely of course, but chances are the actual problem does not require any of this.

Related

Execute a bash script without typing ./ [duplicate]

I feel like I'm missing something very basic so apologies if this question is obtuse. I've been struggling with this problem for as long as I've been using the bash shell.
Say I have a structure like this:
├──bin
├──command (executable)
This will execute:
$ bin/command
then I symlink bin/command to the project root
$ ln -s bin/command c
like so
├──c (symlink to bin/command)
├──bin
├──command (executable)
I can't do the following (errors with -bash: c: command not found)
$ c
I must do?
$ ./c
What's going on here? — is it possible to execute a command from the current directory without preceding it with ./ and also without using a system wide alias? It would be very convenient for distributed executables and utility scripts to give them one letter folder specific shortcuts on a per project basis.
It's not a matter of bash not allowing execution from the current directory, but rather, you haven't added the current directory to your list of directories to execute from.
export PATH=".:$PATH"
$ c
$
This can be a security risk, however, because if the directory contains files which you don't trust or know where they came from, a file existing in the currently directory could be confused with a system command.
For example, say the current directory is called "foo" and your colleague asks you to go into "foo" and set the permissions of "bar" to 755. As root, you run "chmod foo 755"
You assume chmod really is chmod, but if there is a file named chmod in the current directory and your colleague put it there, chmod is really a program he wrote and you are running it as root. Perhaps "chmod" resets the root password on the box or something else dangerous.
Therefore, the standard is to limit command executions which don't specify a directory to a set of explicitly trusted directories.
Beware that the accepted answer introduces a serious vulnerability!
You might add the current directory to your PATH but not at the beginning of it. That would be a very risky setting.
There are still possible vulnerabilities when the current directory is at the end but far less so this is what I would suggest:
PATH="$PATH":.
Here, the current directory is only searched after every directory already present in the PATH is explored so the risk to have an existing command overloaded by an hostile one is no more present. There is still a risk for an uninstalled command or a typo to be exploited, but it is much lower. Just make sure the dot is always at the end of the PATH when you add new directories in it.
You could add . to your PATH. (See kamituel's answer for details)
Also there is ~/.local/bin for user specific binaries on many distros.
What you can do is add the current dir (.) to the $PATH:
export PATH=.:$PATH
But this can pose a security issue, so be aware of that. See this ServerFault answer on why it's not so good idea, especially for the root account.

chmod/chown always writing updates even if not required

Whenever I do a "zfs diff" on certain zfs file systems, the output is cluttered by "modified" user files that get "changed" by running chmod over them (in a cron, to ensure some security aspects).
Question: is there an easy way that I missed to force (POSIX) permissions and ownership on file hierarchies without chmod/chown touching them when the permissions are already as I want them to be?
You could do something like
find dir/ -type f -perm /0111 -exec chmod a-x {} +
instead of an unconditional chmod to remove the permissions. (all the x permissions here.)
The fact aside that security by cron sounds like a bad idea the simple answer is "No". Neither chmod nor chown have a flag to do a modify a file/directory only when your desired state doesn't match.
You have two options:
write a patch for the tools
write a wrapper, as larsks suggested in the comments above
Depending on the size of your filesystem / directory structure that may increases the runtime of your cron job quite dramatically, though.

Is it possible to change directory mode so that no one can create new files in it?

Say that I have the folder /dir. Is there a command in bash that I can use so that after performing it, no one could create new files in /dir?
Edit: important to mention that after performing the command, there will be same permissions to the directory files as they were before. For example, if I have folder /dir with file a.txt in it - so after I use my desired command I cant create new files, but I can modify/delete a.txt if I want.
you could change the permission with chmod to only let people read the folders content.
chmod a-w /dir
Will remove all write permissions of all (ugo), but keep x (execute) and r (read) permissions intact.
Yes, it's pretty simple. Just chmod to read only. Here is a sample
chmod -R 0444 /path/to/your/dir/
Where the last 3 4's mean User-readonly, Group-readonly and others-readonly respectively.

Linux folder change auto notification

Is there a way that I can programmatically figure out whether a particular file with certain characteristics is being added into say the linux /tmp folder. All I need to create, is a small script that is automatically called every time a new file is added in the tmp folder.
These links might be helpful: Inotify and Inotify-tools.
You can use entr tool to do that in the following way:
while true; do find /tmp/ | entr -d ./temp_changed.sh; done
A directory watch option (-d) reacts to events when a new file is added to a directory.

share directory with different users on a workstation on linux/bsd

I'm setting up a development workstation that used to have only one shared account to have an account for each developer that may be using it.
We commonly switch workstations. I would like to have certain directories "shared" by all users in a transparent manner.
I created /usr/local/share/workspace and /usr/local/share/rvm directories, which are symlinked to ~/workspace and ~/.rvm.
Subdirectories/files that are created within the directory should also be writable by all developers by default (without having to use sudo). I also would prefer not to set the directory to be world writable, since ruby gives me a warning because the rvm directory is on the path (I don't care about the security implications however).
How do I do this? Are there any resources that outline good practices?
If you want to share the directory on a single workstation, put all relevant users in a group (see man addgroup, and /etc/group), then run "chgrp -R yourgroup yourdir" on your directory trees. To give write permissions, run "chmod -R g+w yourdir".
If you want to share it between different computers, you can use NFS. See for instance this HOWTO.
I'm assuming that /usr/local/share/workspace and all contained files/directories are owned by a group that all of the users are in. If that's true, then all you need to do is apply the setgid and group execute bits to every directory, and also set the group write bit on every file and directory:
find /usr/local/share/workspace -type d -exec chmod +s {} \;
chmod -R g+wX /usr/local/share/workspace
The setgid bit, when applied to directories, means that:
All files and directories created in the directory will have their group ownership defaulted to the owner of the directory.
All directories created in the directory will also have their setgid bit set, so that this is effective for new directories as well. (In other words, this bit gets applied recursively to new directories automatically.)
Users will also need to supply a umask that permits write access to other group members. So they should put something like umask 002 in their ~/.profile. If they don't, then any files or directories that they create may not be writable by other group members.

Resources