Stop .git/index from changing its permissions - bash

How can I prevent .git/index from constantly changing its permissions and ownership?
I run ls -al .git/index and see that the file is owned by root.
I change the permissions with sudo chown -R $USER:USER and sudo chmod -R 775 .git
I even tried deleting the lock file with rm -rf .git/index.lock
The permissions update but then a few minutes later they change back to being owned by root and 740 which breaks the git commands I'm attempting.
I set the global git config via Ansible so I'm wondering if that messed something up? Is there a global file I need to modify?

When Git writes the index, the way it does so is to create a new file called .git/index.lock (with O_EXCL), adjusts its permissions according to core.sharedRepository, and then rename it over top. Git does not offer a way to rewrite the file in place.
If this file is being created such that it's being owned by root, then root is creating the file because it's updating the index. That probably means that some process owned by root is modifying the working tree.
If that wasn't your intention, then the best thing to do is find that process and stop it from modifying the working tree. It's not a good idea for multiple users to modify the same working tree, and if your process owned by root is reading files out of the working tree and it's shared with another user, that could lead to a security vulnerability.
If you're certain what you're doing is safe and you want to modify the permissions with which files in the .git directory are created, you can use core.sharedRepository to set them. For example, you could use the value 0664. Note that Git will handle the executable bit automatically, and the index should not be marked executable.
If you want to always use the same group for your repository, you can set the setgid bit on all the directories in the repository and then set their group to the appropriate value. Assuming you also set core.sharedRepository to a value that makes things group writable, you can then modify the repository with any user in that group, and things should work. Note that this may still have security implications if one or more of those users are untrusted or have lower privileges, so you should be careful.

Related

How to change the permission of a directory inside the .tar.gz file? [duplicate]

Is there a way to chmod 777 the contents of a tarfile upon creation (or shortly thereafter) before distributing? The write permissions of the directory that's being tar'd is unknown at the time of tar'ing (but typically 555). I would like the unrolled dir to be world writable without the users who are unrolling the tar to have to remember to chmod -R 777 <untarred dir> before proceeding.
The clumsy way would be to make a copy of the directory, and then chmod -R 777 <copydir> but I was wondering if there was a better solution.
I'm on a Solaris 10 machine.
BACKGROUND:
The root directory is in our ClearCase vob with specific file permissions, recursively. A tarfile is created and distributed to multiple "customers" within our org. Most only need the read/execute permissions (and specifically DON'T want them writable), but one group in particular needs their copy to be recursively writable since they may edit these files, or even restore back to a "fresh" copy (i.e., in their original state as I gave them).
This group is somewhat technically challenged. Even though they have instructions on the "how-to's" of the tarfile, they always seem to forget (or get wrong) the setting of the files to be recursively writable once untarred. This leads to phone calls to me to diagnose a variety of problems where the root cause is that they forgot to do (or did incorrectly) the chmod'ing of the unrolled directory.
And before you ask, yes, I wrote them a script to untar/chmod (specific just for them), but... oh never mind.
So, I figured I'd create a separate, recursively-writable version of the tar to distribute just to them. As I said originally, I could always create a copy of the dir, make the copy recursively writable and then tar up the copy dir, but the dir is fairly large, and disk space is sometimes near full (it can vary greatly), so making a copy of the dir will not be feasable 100% of the time.
With GNU tar, use the --mode option when creating the archive, e.g.:
tar cf archive.tar --mode='a+rwX' *
But note that when the archive is extracted, the umask will be applied by default. So unless the user's umask is 000, then the permissions will be updated at that point. However, the umask can be ignored by using the -p (--preserve) option, e.g.:
tar xfp archive.tar
You can easily change the permissions on the files prior to your tar command, although I generally recommend people NEVER use 777 for anything except /tmp on a unix system, it's more productive to use 755 or worst case 775 for directories. That way you're not letting the world write to your directories, which is generally advisable.
Most unix users don't like to set the permissions recursively because it sets the execute bit on files that should not be executable (configuration files for instance) to avoid this they invented a new way to use chmod some time ago, called symbolic mode. Reading the man page on chmod should provide details, but you could try this:
cd $targetdir; chmod -R u+rwX,a+rX .; tar zcvf $destTarFile .
Where your $targetdir is the directory you are tarring up and $destTarFile is the name of the tar file you're creating.
When you untar that tar file, the permissions are attempted to be retained. Certain rules govern that process of course - the uid and gid of the owner will only be retained if root is doing the untaring, but otherwise, they are set to the efective uid and gid of the current process.

make a file removable just by root in mac

i'm trying to make a file removable just by root user In mac 10.10.
i was try this :
chown root <fileName>
but other user can remove it;
any idea?
As an alternative to changing the permissions on the containing directory, you can set the uimmutable flag on the file:
sudo chown root foo
sudo chflags uimmutable foo
Now only root will be able to delete foo. Note, though, that nobody will be able to modify the file, either. Root could remove the uimmutable flag and then modify it, of course, but that opens a window for others to delete it.
The act of removing an entry in a directory modifies the directory, but not the file. (When you remove a file, you are unlinking the name from the file and the link count on the file is decremented. The file itself may not be deleted, but will no longer be accessible by the name that was removed.) In order to ensure that only some process with root privilege can unlink a file, you need to modify the permissions on the directory. So to ensure that no-one but root can delete the file /p/a/t/h/file:
sudo chown root /p/a/t/h # make root the owner of the directory
sudo chmod og-w /p/a/t/h # remove write permissions from other and group
Note that this is less fine grained that you might like and will prevent non-root users from removing or creating any files in /p/a/t/h.

Execute permissions on downloaded file

I have made a script for installing a control panel.
I've uploaded the script to a server so people can wget it to their machines.
The only issue is that you have to chmod it after download. Is there a way to remove this step? How would I go about keeping 755 perms on the downloaded script?
When a user downloads the file, the file will automatically get some default permission. In UNIX, each user will have a default set of permissions which apply to all files created by that user, unless you explicitly set it to something else.
This default is called the umask, after the command used to change it. It is either inherited from the login process, or set in the .shrc or .login file which configures an individual account, or it can be run manually.
Typically the default configuration is equivalent to typing 'umask 22' which produces permissions of:
-rw-r--r-- for regular files, or
drwxr-xr-x for directories.
In other words, user has full access, everyone else (group and other) has read access to files, lookup access to directories. As you see above, the execution access is not default for files.
Hence you need to explicitly change it.

How to change Unix permissions when I don't own the file but do have write permission on the directory?

I'm sharing a git repository with a colleague, and because git does not propagate the full panoply of Unix file permissions, we have a "hook" that runs on update which sets the 'other' permissions as they need to be set. The problem? The hook uses chmod, and it turns out that when my colleague commits a file, he owns it, so I can't run chmod on it, and vice versa. The directories are all group writable, sticky, so I believe that either of us has the right to remove any file and replace it with one of the same name, same contents, but different ownership. Presumably then we could chmod it. But this seems like an awfully big hammer, and I'm a bit leery of screwing it up. So, two questions:
Can anybody think of another way to do it?
If not, what's the best design for a bulletproof shell script that implements "make this file belong to me"? No cross-filesystem moves, etc etc...
For those who may not have realized, write permission does not confer permission to chmod:
% ls -l value.c
-rw-rw---- 1 agallant ta105 133 Feb 10 13:37 value.c
% [ -w value.c ] && echo writeable
writeable
% chmod o+r value.c
chmod: changing permissions of `value.c': Operation not permitted
We are both in the ta105 group.
Notes:
We're using git not only to coordinate changes but to publish the repo as a course web site. Publishing the web site is the primary purpose of the repo. The permissions script runs at every update using a git hook, and it ensures that students do not have permission to read solutions that have not yet been unveiled.
Please do not suggest that I have the wrong umask. Not all files in the repo should have the same permissions, and whatever umask is chosen, permissions on some files will need to be changed. Not to mention that it would be discourteous for me to impose my umask preferences on my colleagues.
UPDATE: I've just learned that in our environment, root is quashed to nobody on all machines we have access to, so that a solution which relies on root privileges won't work.
There is at least one Unix in which I've seen a way to give someone chmod and chown permissions on all files owned by a particular group. This is sometimes called "group superuser" or something similar.
The only Unix I'm positive I've seen this on was the version of Unix that the Encore Multimax ran.
I've searched a bit, and while I remember a few vague references to an ability of this sort in Linux, I have been unable to find them. So this may not be an option. Luckily, it can be simulated, albeit the simulation is a bit dangerous.
The way to simulate this is to make a very specific suid program that will do the chmod as root after checking that you are a member of the same group as owns the file, and your username is listed as having that permission in a special /etc/chmod_group file that must be owned by root and readable and writeable only by root.
The most straightforward way to do this is to make your partner and you members of a new group (let's say "devel"), and have that as the group of the file. That way it can be owned by either of you, and as long as the group is right, you can both work with it.
If that doesn't work with you, "sudo" can be configured such that only those two users can run a chmod command on files in that specific directory as root with no password.
If you set your umask correctly, the files could be created with the correct permissions in the first place:
$ umask 0022
$ touch foo
$ ls -l foo
-rw-r--r-- 1 sarnold sarnold 0 2011-02-20 21:17 foo
$ rm foo
$ umask 0002
$ touch foo
$ ls -l foo
-rw-rw-r-- 1 sarnold sarnold 0 2011-02-20 21:17 foo
I'm taking a step back. Let me know if I'm violating some restriction in your system I haven't read.
From your question, I assume you're trying to share a git repository using file:// URLs and relying on the UNIX filesystem permissions to take care of authorisation etc. Why don't you consider another way to share your repositories that doesn't involve this hassle?
I can think of two ways.
You can create bare repository on either of your machines, add that as a remote to your working repos and use it to collaborate. Serving it can be done using the inbuilt git daemon command. Detais are here. This will however not give you any access control.
You can install gitosis locally and use that to serve your repository. This allows a simple access control system so that you can restrict/allow certain users.
There was a related question that came up a while ago that might be relevant. git daemon worked for him - Administrating a git repo without root permissions
I also found something on server fault that might be relevant to your problem - https://serverfault.com/questions/21126/git-daemon-and-access-control-for-multiple-repos
Probably not the most elegant way, but it seems to work
$ umask 0002
$ mv value.c value.c.tmp
$ cat value.c.tmp > value.c
$ rm value.c.tmp
one could argue that it could be made bulletproof, but then someone brings along a RPG...
If both of you need to chmod, I can not think of another way - if it is OK that YOU can chmod but no the other guy, you can chmod 6770 . or chmod g+s,u+s . in the directory (e.g. set SUID and GUID bits) so the one that owns the directory will always be the owner of the files. Unfortunately some (if not most), namely EXT2/3/4 ignore the SUID bit.
Of course, setting the umask to 0002 will solve the problem by not making it mandatory.
Assuming that your publishing hook actually deploy files, rather than just setting permissions in the working copy, you could deploy to a temporary location then use rsync to ensure that the file contents and permissions are correct.
Slightly nicer, but requiring some infrastructure which I'm guessing isn't in place, would be to ensure that the deploy script only runs under one user. You could do this using sudo, if your sysadmins allow, or by setting up a git server service, like gerrit, or even by having a cron job run every five minutes which checks for updates and deploys if necessary.
This might work:
touch $name.tmp
chmod 660 $name.tmp
cp $name $name.tmp
if cmp $name $name.tmp 2>/dev/null; then
rm $name && \
cp $name.tmp $name && \
rm $name.tmp
fi
It's just a variation of your original idea
Ok, a mixture of things that build on previous answers:
you can set the umask of a folder if you mount it at fstab. If you could agree with people to work on that mount, you could enforce g+w
If you set the group-id bit of that folder (g+s) all files will belong to the group the folder belongs to, so the group ownership of the file propagates
Is that doable? Of course enforcing that mount point is no easy task. Any better ideas around that one anyone?

How do you set a directory to have persistent group permissions?

We have two users:
user1
user2
They both belong to the group 'admin'.
We have a directory that has been set to 775. The directory's group has been changed to 'admin'. Each user has full access to write into that directory, though when a user writes a new file to the directory, the group permissions of the folder are not persisted to the file that was written.
How should we make it so that files inherit the directory's group permissions?
Clarification: when a new file or directory is written, it uses the users' group as the group of the new file, rather than that of the directory, which makes sense - but how do I not make that happen?
You can propagate group permissions by setting the directory's setgid bit (chmod g+s). This may not be portable across all *nixes and all file systems.
http://en.wikipedia.org/wiki/Setuid#setgid_on_directories
http://www.gnu.org/software/coreutils/manual/html_node/Directory-Setuid-and-Setgid.html
If you are using ext3 or ReiserFS, this page about creating a Linux file server may help. Specifically step 7 suggests the following command.
setfacl -d -m g:sales:rw /groups/sales
I think you should look here.
As the site says, "Unix doesn't support the idea of inherited permissions."
However, there is a section on ACLs (Access Control Lists), which I think is what you are looking for. By setting up an ACL, you can have your files inherit the same ACL from the directory, which I think is what you are asking for. setfacl is the shell command that will be what you need to look into.
Hope that helps!

Resources