Reputation: 79
We have a Solaris server in our campus where every student and staff has an account on. I want to host a bare Git repo and have it only accessible to certain users.
Now, because I do not administrate the server, I cannot mess around with the groups and user accounts. I know I can use Giotlite and create public keys for my users but it seems silly since they already have their own user accounts on the server. So what I am doing is to use FACL to give access to specific users.
Here is what I did to set up the repo using cs101
account on its home directory (it's the course account):
mkdir cs101.git
Set the FACL permissions using to give access to my user account
setfacl -m d:u::rwx,d:g::---,d:o:---,d:m:rwx cs101.git
setfacl -m d:u:cs101:rwx,u:cs101:rwx,d:u:welcomb:rwx,u:welcomb:rwx cs101.git
Then finally initialize Git
cd cs101.git
git init --bare --shared
The directory listing shows
total 88
drwx--S---+ 7 cs101 cs101 4096 Aug 3 14:33 .
drwx-----x 6 cs101 cs101 4096 Aug 5 15:02 ..
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 branches
-rw-rw----+ 1 cs101 cs101 126 Aug 3 14:33 config
-rw-rw----+ 1 cs101 cs101 73 Aug 3 14:33 description
-rw-rw----+ 1 cs101 cs101 23 Aug 3 14:33 HEAD
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 hooks
drwxrws---+ 2 cs101 cs101 4096 Aug 3 14:33 info
drwxrws---+ 33 cs101 cs101 4096 Aug 5 15:10 objects
drwxrws---+ 4 cs101 cs101 4096 Aug 3 14:33 refs
Permission for the directories seems correct
# file: hooks/
# owner: cs101
# group: cs101
user::rwx
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rwx #effective:rwx
mask:rwx
other:---
default:user::rwx
default:user:cs101:rwx
default:user:welcomb:rwx
default:group::---
default:mask:rwx
default:other:---
Still using the course account cs101
, I push some files into the repo.
Now, I logout of the course account and login using my own user account and I am able to clone the repo welcomb@solaris$ git clone ~cs101/cs101.git
So far so good, everything appears fine.
Now the problem is that I am unable to push new commits back to the repo using my own user account:
welcomb@solaris$ GIT_TRACE=1 git push
trace: built-in: git 'push'
trace: run_command: 'git-receive-pack '\''/home/course/cs101'\'''
trace: exec: '/bin/bash' '-c' 'git-receive-pack '\''/home/course/cs101'\''' 'git-receive-pack '\''/home/course/cs101'\'''
trace: built-in: git 'receive-pack' '/home/course/cs101'
trace: run_command: 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: exec: 'git' 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: built-in: git 'pack-objects' '--all-progress-implied' '--revs' '--stdout' '--thin' '--delta-base-offset' '-q'
trace: run_command: 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: exec: 'git' 'unpack-objects' '--pack_header=2,3' '-q'
remote: trace: built-in: git 'unpack-objects' '--pack_header=2,3' '-q'
trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'
trace: run_command: 'hooks/update' 'refs/heads/master' '629b5b1f0122de95bd4e7b50a7968e64aaef6e65' 'b2072da84ee7d3fde6c6daf2cae61dbae6b0a5d9'
fatal: cannot exec 'hooks/update': Permission denied
remote: error: hook declined to update refs/heads/master
trace: run_command: 'gc' '--auto' '--quiet'
trace: exec: 'git' 'gc' '--auto' '--quiet'
trace: built-in: git 'gc' '--auto' '--quiet'
To /home/course/cs101
! [remote rejected] master -> master (hook declined)
error: failed to push some refs to '/home/course/cs101'
It seems it is unable to execute hooks/update
.
fatal: cannot exec 'hooks/update': Permission denied
But hooks/update
exec bit is
not even set, which mean Git should ignore running it.
/home/course/cs101/cs101.git/hooks$ getfacl update
# file: update
# owner: cs101
# group: cs101
user::rw-
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
group::rw- #effective:rw-
mask:rwx
other:---
/home/course/cs101/cs101.git/hooks$ ls -al update
-rw-rw---- 1 cs101 cs101 2910 Aug 4 10:50 update
I can access the files in the directories and even execute update.sample
using my account
/home/course/cs101/cs101.git/hooks$ ./update.sample
Don't run this script from the command line.
(if you want, you could supply GIT_DIR then run
./update.sample <ref> <oldrev> <newrev>)
So I can't figure out why Git push is failing to update the repo.
Upvotes: 0
Views: 1876
Reputation: 489628
The getfacl
output includes the lines:
user:cs101:rwx #effective:rwx
user:welcomb:rwx #effective:rwx
which means that the C library access(path, X_OK)
function is likely to claim that the file can be executed (run via an execve
system call or similar), at least for users cs101
and welcomb
. This is how Git determines whether a hook is executable.
(Note that any other user calling access
will get the answer: no, this file is not executable. This is part of what makes ACLs so complicated.)
When the OS actually tries to execute it, however, something else goes wrong. It's not entirely clear precisely what goes wrong, but the execve
system call fails with a "permission denied" error. Git then decides to that hook failed, rather than that the hook was not actually executable (Git assumes that access
will say no rather than yes for these cases).
Given the tiny size of the file (2910 bytes, from the ls -al update
output) it seems unlikely that the update
hook is anything other than a shell script. If it is a shell script, it needs a correct #!
interpreter line to be executable, and that interpreter line must point to a file that itself has execute permissions.
If you do want the hook to run, you will have to trace down the source of the actual failure. If you don't want the hook to run, and don't want Git to think the hook should run, remove the execute bits from the various elements of the ACL, or remove the ACL entirely (ACLs and "Unix style" permissions are often separate entities in the underlying system, though ZFS is different here).
Upvotes: 2