Does chmod modify permissions of FILE... arguments in the order specified? - unix

Given an invocation of chmod with multiple FILE arguments,
$ chmod 0xxx FILE-1 FILE-2 FILE-3 ...
is there a predictable order of prcessing them? This may matter when FILE-k and FILE-j are related, e.g. when one is a subdirectory of the other. Say, FILE-1 being some directory d1 and FILE-2 subdirectory d1/d2, i.e., the second argument names a subdirectory of the first argument:
$ chmod 0000 d1 d1/d2
chmod: cannot access `d1/d2': Permission denied
O.K., this is what I had expected, i.e., reading from left to right reflects the order of processing FILE... arguments, d1's permissions are cleared first and, therefore, chmod connot then gain access to d1/d2. So, the following invocation also works as expected:
$ chmod 0000 d1/d2 d1
This clears permissions of either directory. But is this order dependence guaranteed, and more generally, does POSIX say something about the matter? Does option -R affect the reasoning in some way or other, as regards predictability across Unix systems?

It doesn't seem to be specified anywhere.
However, the Application Usage section of the Manual Page for CHMOD does specify recursive behaviour of the command.
After several experimentation, I obtained the same result as yours on my x86_64 GNU/Linux running Ubuntu 14.04.5 LTS.
It seems to work out the permissions from left to right and stops when it cannot change permission.
If you are trying to revoke permissions, then it is better to have the parent directory last. (i.e. leaf to root in the file hierarchy)
If you are trying to grant permissions, then it is better to have the parent directory first. (i.e. root to leaf in the file hierarchy)

While not specified, all implementations behave naturally like you experienced, but there is no guarantee, beware POSIX (IEEE Std 1003.1-2008, 2016 Edition) says in chmod command manual - Application Usage:
Some implementations of the chmod utility change the mode of a
directory before the files in the directory when performing a
recursive (-R option) change; others change the directory mode after
the files in the directory. If an application tries to remove read or
search permission for a file hierarchy, the removal attempt fails if
the directory is changed first; on the other hand, trying to re-enable
permissions to a restricted hierarchy fails if directories are changed
last. Users should not try to make a hierarchy inaccessible to
themselves.
Thus any order on the arguments can be applied, you need to use separate commands to ensure the order.

Related

Rsync copy "unsafe" symlinks but don't update modification time on the symlink targets

Is it possible to have rsync copy "unsafe" symlinks (that is, those that refer to files/dirs outside of the copied tree, see docs here) but not update the times on them?
I'm using rsync -a --delete --omit-dir-times to copy a bunch of files from /home/somebody/foo/bar to a destination machine, but running into the following error: rsync: failed to set times on "/home/somebody/foo/bar/symlink": Operation not permitted (1), where /home/somebody/foo/bar/smylink refers to something in /usr/lib/ owned by root at the destination and lacking proper permission for the rsync user to update it.
Essentially rsync tries to update the time on the symlink like all other files it copies, but gets blocked by permissions because it's not root at the destination.
What I'd like to do is copy the link, but not touch the symlink target at all during the copy. I just want the link. I could change permissions on the target file, but I'd like to avoid that.
Is this achievable? Is this a terrible idea and I'd be abusing rsync? Suggestions for alternative approaches in the latter case?
There is another option for rsync --omit-link-times which will probably do what you are looking for. See man page at:
http://manpages.ubuntu.com/manpages/bionic/man1/rsync.1.html

Unix-Changing Permissions-Files turned green

I used this command on my folder in unix:
chmod -R go-rwx *
in order to change permissions for group and others.
Doing this, many files turned green coloured, even simple data files.
Why did this happened?What does it mean?
Is it going to affect my files in a bad way?
They seem to work right now, but I'm concerned about their general functionality.
Thanks!
It is very unlikely that the command you mentioned would cause ls to print your files in green. When ls colors are enabled, executable files are printed in light green by default. Since chmod +R go-rwx only removes permissions, it cannot have caused any files to be marked as executable, and hence won't have made ls print them in green.
Instead, I believe the cause of this is a different command you must have entered, which accidentally marked all those files as executable. This is actually pretty common. Here is the typical scenario: You want to make a directory and all subdirectories readable and possible to enter for all users. So you do chmod -R a+rx top_directory. This works, but as a side effect you have also set the executable flag for all the normal files in all those directories too. This will make ls print them in green if colors are enabled, and it has happened to me several times. You can avoid this by doing chmod -R a+rX top_directory instead, which will only set the executable bit for directories.
To make your files stop being green, you must clear those executable bits. If none of the files in these directories are actually supposed to be executable, this is simple:
$ chmod -R a-x top_directory
$ chmod -R u+X top_directory
This will remove the executable flag for all files and directories, and then add it back for directories only (for the current user). But if some of the files are actually supposed to be executable, you will have to go through them and fix things manually, which can be tedious.
Having some files incorrectly marked as being executable is not a big problem. They will still function normally. It's just a bit messy, and they may show up in command tab completion if the current directory (.) is in your $PATH. So you can safely ignore this issue.
That is an ls functionality:
--color[=WHEN]
colorize the output. WHEN defaults to 'always' or can be 'never' or 'auto'. More info below
Using color to distinguish file types is disabled both by default and with --color=never. With --color=auto, ls emits color codes only when standard output is connected to a terminal. The LS_COLORS environment variable can change the settings. Use the dircolors command to set it.
You can try with ls --color=never and you won't see the colors anymore.
You can see your color configuration with dircolors -p.
This is the line where the executables files configuration resides:
# This is for files with execute permission:
EXEC 01;32
That's just to help you identify file types, so it's not affecting your files in any bad way.

mkdir's "-p" option

So this doesn't seem like a terribly complicated question I have, but it's one I can't find the answer to. I'm confused about what the -p option does in Unix. I used it for a lab assignment while creating a subdirectory and then another subdirectory within that one. It looked like this:
mkdir -p cmps012m/lab1
This is in a private directory with normal rights (rlidwka). Oh, and would someone mind giving a little explanation of what rlidwka means? I'm not a total noob to Unix, but I'm not really familiar with what this means. Hopefully that's not too vague of a question.
The man pages is the best source of information you can find... and is at your fingertips: man mkdir yields this about -p switch:
-p, --parents
no error if existing, make parent directories as needed
Use case example: Assume I want to create directories hello/goodbye but none exist:
$mkdir hello/goodbye
mkdir:cannot create directory 'hello/goodbye': No such file or directory
$mkdir -p hello/goodbye
$
-p created both, hello and goodbye
This means that the command will create all the directories necessaries to fulfill your request, not returning any error in case that directory exists.
About rlidwka, Google has a very good memory for acronyms :). My search returned this for example: http://www.cs.cmu.edu/~help/afs/afs_acls.html
Directory permissions
l (lookup)
Allows one to list the contents of a directory. It does not allow the reading of files.
i (insert)
Allows one to create new files in a directory or copy new files to a directory.
d (delete)
Allows one to remove files and sub-directories from a directory.
a (administer)
Allows one to change a directory's ACL. The owner of a directory can always change the ACL of a directory that s/he owns, along with the ACLs of any subdirectories in that directory.
File permissions
r (read)
Allows one to read the contents of file in the directory.
w (write)
Allows one to modify the contents of files in a directory and use chmod on them.
k (lock)
Allows programs to lock files in a directory.
Hence rlidwka means: All permissions on.
It's worth mentioning, as #KeithThompson pointed out in the comments, that not all Unix systems support ACL. So probably the rlidwka concept doesn't apply here.
-p|--parent will be used if you are trying to create a directory with top-down approach. That will create the parent directory then child and so on iff none exists.
-p, --parents
no error if existing, make parent directories as needed
About rlidwka it means giving full or administrative access. Found it here https://itservices.stanford.edu/service/afs/intro/permissions/unix.
mkdir [-switch] foldername
-p is a switch, which is optional. It will create a subfolder and a parent folder as well, even if parent folder doesn't exist.
From the man page:
-p, --parents no error if existing, make parent directories as needed
Example:
mkdir -p storage/framework/{sessions,views,cache}
This will create subfolder sessions,views,cache inside framework folder irrespective of whether 'framework' was available earlier or not.
PATH: Answered long ago, however, it maybe more helpful to think of -p as "Path" (easier to remember), as in this causes mkdir to create every part of the path that isn't already there.
mkdir -p /usr/bin/comm/diff/er/fence
if /usr/bin/comm already exists, it acts like:
mkdir /usr/bin/comm/diff
mkdir /usr/bin/comm/diff/er
mkdir /usr/bin/comm/diff/er/fence
As you can see, it saves you a bit of typing, and thinking, since you don't have to figure out what's already there and what isn't.
Note that -p is an argument to the mkdir command specifically, not the whole of Unix. Every command can have whatever arguments it needs.
In this case it means "parents", meaning mkdir will create a directory and any parents that don't already exist.

rsync error: failed to set times on "/foo/bar": Operation not permitted

I'm getting a confusing error from rsync and the initial things I'm finding from web searches (as well as all the usual chmod'ing) are not solving it:
rsync: failed to set times on "/foo/bar": Operation not permitted (1)
rsync error: some files could not be transferred (code 23)
at /SourceCache/rsync/rsync-35.2/rsync/main.c(992) [sender=2.6.9]
It seems to be working despite that error, but it would be nice to get rid of that.
If /foo/bar is on NFS (or possibly some FUSE filesystem), that might be the problem.
Either way, adding -O / --omit-dir-times to your command line will avoid it trying to set modification times on directories.
The issue is probably due to /foo/bar not being owned by the writing process on a remote darwin (OS X) system.
A solution to the issue is to set adequate owner on the remote site.
Since this answer has been voted, and therefore has been hopefully useful to someone, I'm extending it to make it clearer.
The reason why this happens is that rsync is probably trying to set an arbitrary modification time (mtime) when copying files.
In order to do this darwin's system utime() function requires that the writing process effective uid is either the same as the file uid or super user's one, see opengroup utime's page.
Check this discussion on rsync mailing list as reference.
As #racl101 has commented on an answer, this problem might be related to the folder owner. The rsync command should be done by the same user as the folder owner's one. If it's not the same, you can change it.
chown -R userCorrect /remote/path/to/foo/bar
I had the same problem. For me the solution is to delete the remote file and let rsync create again.
The problem in my case was that the "receiver mountpoint" was incorrectly mounted. It was in read-only mode (for some extrange reason).
It looked like rsync was copying the files, but it was not.
I checked my fstab file and changed mount options to default, re-mount file system and execute rsync again. All fine then.
I've seen that problem when I'm writing to a filesystem which doesn't (properly) handle times -- I think SMB shares or FAT or something.
What is your target filesystem?
This happened to me on a partition of type xfs (rw,relatime,seclabel,attr2,inode64,noquota), where the directories where owned by another user in a group we were both members of. The group membership was already established before login, and the whole directory structure was group-writeable. I had manually run sudo chown -R otheruser.group directory and sudo chmod -R g+rw directory to confirm this.
I still have no idea why it didn't work originally, but taking ownership with sudo chown -R myuser.group directory fixed it. Perhaps SELinux-related?
I came across this problem as well and the issue I was having was a permissions issue with the root folder that contained the files I was trying to send over. I don't care about that root folder being included with rsync I just care what's in it. The error was coming from my command where I need to specify an additional / at the end. If you do not have that trailing slash rsync will attempt to set times the folder.
Example:
This will attempt to set times on html
rsync /var/www/html/ ubuntu#xxx.xxx.xxx.xxx:html
This will not
rsync /var/www/html/ ubuntu#xxx.xxx.xxx.xxx:html/
This error might also pop-up if you run the rsync process for files that are not recently modified in the source or destination...because it cant set the time for the recently modified files.
I ran into this error trying to fix timestamps on a new MacOS Monterey, after the Migration Assistant decided to set all of them to the time the copy operation occurred, instead of the original file's.
anddam's answer did not help me, as the remote user used in the rsync command did match the directories and files owner.
After further research, I realised that I had no access to the Mac's Documents directory over SSH (error ls: Documents: Operation not permitted).
I managed to fix the problem by opening System Preferences on the Mac, then selecting Security & Privacy, go to Privacy tab select Full Disk Access and check the box next to sshd-keygen-wrapper.
It could be that you don't have privileges to some of the files. From an administrator account, try "sudo rsync -av " Alternately, enable the root account and sign in as root. That should allow you to completely hose your system and brute force your rsync! ;-) I'm not sure if the above mentioned --extended-attributes will help, but I threw it in too, just for good measure.

When could or should I use chmod g+s on a file or directory?

In deploying to a new (Solaris 9) environment recently, one of the steps was to copy a set of files and directories to their new location and then to apply the group UID bit (using "chmod -R g+s") to all files in the directory tree giving a mode of -rwxr-s--- to everything. The result was that none of our shell scripts would execute unless they were individually opened and re-saved. I should add that we had earlier set g+s on the target parent folder prior to copying files; this had set the initial mode on all the new directories to drwxr-s--- but the files had a mode of -rwxr-x---
Having eventually discovered which step caused the problem, we were able to cut out that step and proceed.
I would like, however, to understand what the "s" bit means when applied to directories and files, in the hope that this will explain why we had the problem in the first place.
Setting directories g+s makes all new files created in said directory have their group set to the directory's group.
This can actually be really handy for collaborative purposes if you have the umask set so that files have group write by default.
Note: This is the way it works in Linux, it could work completely differently in Solaris.
For executable files, this means that when the file is executed, it is executed as the group that owns the file, not the group of the user executing the file.
This is useful if you want users to be able to assume the permissions of a particular group just for running one command.
However, it is also a security risk as it is allowing users to elevate their permissions. You have to know that the scripts with this bit set aren't going to do anything that would let users abuse these extra permissions.
Here is very handy explanation of SGID (chmod g+s): http://www.linuxnix.com/sgid-set-sgid-linuxunix/
SGID (Set Group ID up on execution) is a special type of file
permissions given to a file/folder. Normally in Linux/Unix when a
program runs, it inherits access permissions from the logged in user.
SGID is defined as giving temporary permissions to a user to run a
program/file with the permissions of the file group permissions to
become member of that group to execute the file. In simple words users
will get file Group’s permissions when executing a
Folder/file/program/command.
For a executable, g+s overrides the group id that the executable will run as (it is usually inherited from the parent).
$ cp `which id` id-test
$ ./id-test
uid=1001(user1) gid=1001(group1) groups=1001(group1),2001(project1)
$ chgrp project1 id-test
$ chmod g+s id-test
$ ./id-test
uid=1001(user1) gid=1001(group1) egid=2001(project1) groups=1001(group1),2001(project1)
(egid is "effective group id" -- usually the same as gid, "group id", but here different.)
For a directory, g+s overrides the group id that new files and directories will have (it is usually inherited from the creator).
$ mkdir project
$ chgrp project1 file1
$ umask
0022
$ touch project/file1
$ ls -l project/file1
-rw-r--r-- 1 user1 group1 0 file1
$ chmod g+s project
$ touch project/file2
$ ls -l project/file2
-rw-r--r-- 1 user1 project1 0 file2
You may still need to fiddle with umask for best results; something at least as permissive as 0007 is required for shared writing, and something at least as permissive as 0027 is required for shared reading.
$ umask 0077
$ touch project/file3
$ ls -l project/file3
-rw------- 1 user1 project1 0 file3
$ umask 0027
$ touch project/file4
$ ls -l project/file4
-rw-r----- 1 user1 project1 0 file4
$ umask 0007
$ touch project1/file5
$ ls -l project1/file5
-rw-rw---- 1 user1 project1 0 file5
For files it means that the file is executed as the group that owns the file, not the group user that executes the file belongs to. It is usable when you want to allow user to do something which for which he does not have the privilege. For example, for one DBMS I use, it is common to allow everybody to backup databases. Although only the 'dbms' group has read/write access to database file, the backup program has g+s set to allow anyone to access the database through it, but not directly.
For directories, it means that newly created directories will be owned by the group that owns the directory, not the group user that created the file belongs to. A good example for this is web space of sourceforge.net project. Imagine 3 developers maintaining the project website. Now, if one of them creates a file, only he can write to it (by default). To work around this, all users on the same project are in the same group as well, and directory has rws privilege for that group, so whoever creates the file, it gets created as readable and writable to the group.
More information about setuid and setgid here
To expand on your specific problem a little, it has already been noted that sgid executables can cause problems by granting users permissions they don't normally have. While this is an issue for any executable, it creates a potentially-exploitable race condition in the case of scripts (specifically meaning "files which execute by means of an external interpreter identified by a #! at the beginning of the file") which can be used to execute any arbitrary code with the script's permissions.
Unix deriviatives have implemented a number of schemes over the years which are aimed at mitigating or eliminating this vulnerability, most of which have included some form of prohibiting the execution of suid or sgid scripts entirely or requiring you to jump through a few hoops to enable it (usually on a script-by-script basis). One such scheme would be the cause of your inability to run the scripts after turning on their sgid flag.
When you need to use it: Fix SVN file ownership issue when you use svn+ssh. Somebody told me it only happens on BDB, but I had such issue in FSFS storage too. Basically when you want to keep the ownership of child files inside a directory consistent when there are other users writing stuff on it, you would have to use u+s/g+s.

Resources