2

I've been working with git repositories cloned on samba share for about one year and apart from few problems with setting it up there weren't any issues with it. Recently I tried to add some files to existing repository and was surprised to see "permission denied" errors.

Now I'm able to init empty repo, but when I try to run strace git add test, I get:

    open(".git/objects/info/alternates", O_RDONLY|O_NOATIME) = -1 ENOENT (No such file or directory)
    access(".git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", F_OK) = -1 ENOENT (No such file or directory)
    open(".git/objects/e6/tmp_obj_GvIyn7", O_RDWR|O_CREAT|O_EXCL, 0444) = -1 EACCES (Permission denied)
    write(2, "error: insufficient permission f"..., 88error: insufficient permission for adding an object to repository database .git/objects
    ) = 88
    close(4)                                = 0
    write(2, "error: test: failed to insert in"..., 44error: test: failed to insert into database
    ) = 44
    write(2, "error: unable to index file test"..., 33error: unable to index file test
    ) = 33

I'm using git 1.8.4.2, samba 4.1.1 on 64-bit Archlinux (kernel version: 3.12.1). I haven't been changing anything in git nor samba configuration since ages.

Share is mounted using systemd automount in /etc/fstab:

//SERVER/DATA  /media/smb  cifs user,noauto,credentials=/etc/samba/creds,\
workgroup=PRV,uid=1000,gid=users,_netdev,comment=systemd.automount 0 0

mount appears as:

//SERVER/DATA on /media/smb type cifs (rw,nosuid,nodev,noexec,relatime,vers=1.0,
cache=strict,domain=PRV,uid=1000,forceuid,gid=100,forcegid,addr=10.1.1.5,
file_mode=0755,dir_mode=0755,nounix,serverino,rsize=61440,wsize=65536,actimeo=1)

Permissions:

    $ ls -lan .git/objects
    total 0
    drwxr-xr-x 2 1000 100 0 11-27 09:04 .
    drwxr-xr-x 2 1000 100 0 2013-11-27  ..
    drwxr-xr-x 2 1000 100 0 11-27 09:39 e6
    drwxr-xr-x 2 1000 100 0 11-27 09:04 info
    drwxr-xr-x 2 1000 100 0 11-27 09:04 pack

    $ ls -lan .git/objects/pack
    total 0
    drwxr-xr-x 2 1000 100 0 11-27 09:04 .
    drwxr-xr-x 2 1000 100 0 11-27 09:04 ..

I've already tried:

  • setting different permissions for share - same result
  • mounting manually - same
  • downgrading samba and git to earlier versions - no difference
  • sudo - this works but I wouldn't want to use it unless absolutely necessary
  • mercurial (out of curiosity) - cloning git repo fails, hg repos are cloned without any problems
  • changing owner and group after using sudo - they seem to remain the same before and after issuing the command

Is there anything more I can do to debug it? I'm quite inclined to stay with git, but I'm left clueless what is wrong with permissions.

Regarding sudo:

$ touch test
$ sudo strace git add test
open(".git/objects/info/alternates", O_RDONLY|O_NOATIME) = -1 ENOENT (No such file or directory)
access(".git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, ".git/objects/pack", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
getdents(5, /* 2 entries */, 32768)     = 48
getdents(5, /* 0 entries */, 32768)     = 0
close(5)                                = 0
open(".git/objects/e6/tmp_obj_i4e0C8", O_RDWR|O_CREAT|O_EXCL, 0444) = 5
brk(0xd5a000)                           = 0xd5a000
write(5, "x\1K\312\311OR0`\0\0\t\260\1\360", 15) = 15
brk(0xd4a000)                           = 0xd4a000
brk(0xd3a000)                           = 0xd3a000
close(5)                                = 0
link(".git/objects/e6/tmp_obj_i4e0C8", ".git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391") = 0
unlink(".git/objects/e6/tmp_obj_i4e0C8") = 0
lstat(".git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391", {st_mode=S_IFREG|0755, st_size=15, ...}) = 0
close(4)   

$ ls -lan .git/objects/e6
total 1
drwxr-xr-x 2 1000 100  0 11-28 10:11 .
drwxr-xr-x 2 1000 100  0 11-28 10:10 ..
-rwxr-xr-x 1 1000 100 15 11-28 10:11 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
-r-xr-xr-x 1 1000 100  0 11-28 10:11 tmp_obj_9Z8UgU
-r-xr-xr-x 1 1000 100  0 11-28 10:10 tmp_obj_d0yhDJ

It creates the objects with 0755 permissions. Without sudo temporary object files are left with 0555. Looks like the problem is in creating file with 0444 as regular user, which seems to have write permissions to whole repo.

5 Answers 5

1

Most likely, you made changes to this repo while root, probably from using sudo, and now some of the files in .git are owned by root. Do a chown to reset file ownership to the user you usually use.

2
  • I tried initializing few empty repos one after another, always as regular user. I used sudo git add or sudo git commit only in part of them - I'll try to chown those when I get back to work. Apart from that, I doubt that repos where I haven't issued sudo git would be owned as root.
    – bjauy
    Commented Nov 27, 2013 at 22:00
  • 1
    Unfortunately, chown doesn't change anything. All files and directories are still being shown as owned by 1000:100 - before and after the operation. I'll update the question.
    – bjauy
    Commented Nov 28, 2013 at 8:42
1

It is a kernel bug in 3.12: https://bugzilla.kernel.org/show_bug.cgi?id=66251

Downgrade as mentioned by @bjauy or upgrade to 3.13.

1

There was a bug in the kernel version that I was running. I've downgraded kernel to 3.11.6 and git add/commit as user started working again.

1

At my side I hit the above problem due to a POSIX violation on a filesystem driver in the kernel used in combination with Samba. As I neither can use sudo nor change the kernel, nor change the Samba-Version, I needed another solution.

I did not try to fix this with a locally compiled git, instead my solution was to fix it via LD_PRELOAD on the fly.

You can find the full workaround at https://github.com/hilbix/misc/tree/master/git_push_samba

The problematic part is that git creates a file for writing with readonly mode. This is correct (POSIX allows the creator to write to a readonly file until the handle is closed, hence the O_RDWR), but with a certain combination of faulty FS driver, this leads to the syscall failing like this:

open("./objects/98/tmp_obj_vVR5gb", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0444) = -1 EACCES (Permission denied)

This makes git give up. However with a changed mode to 0644 this syscall would come back successfully. Following hack does this:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#define open    ignorethisopen
#define open64  ignorethisopen64
#include <fcntl.h>
#undef open
#undef open64
#include <dlfcn.h>

static int (*___open)(const char *, int, mode_t);
static int (*___open64)(const char *, int, mode_t);

static void *
dlwrap(const char *fn)
{
  const char *err;

  void *p = dlsym(RTLD_NEXT, fn);
  if ((err=dlerror())!=0)
    fprintf(stderr, "dlsym(RTLD_NEXT,'%s'): %s\r\n", fn, err);
  return p;
}

void
_init(void)
{
  ___open       = dlwrap("open");
  ___open64     = dlwrap("open64");
}

int
open64(const char *file, int flags, mode_t mode)
{
  if (flags && O_CREAT)
    return ___open64(file, flags, mode|0200);
  return ___open64(file, flags, mode);
}

int
open(const char *file, int flags, mode_t mode)
{
  if (flags && O_CREAT)
    return ___open(file, flags, mode|0200);
  return ___open(file, flags, mode);
}

It needs to be compiled as follows:

cc -Wall -O3 -D_GNU_SOURCE -fPIC -c -o git_push_samba.o git_push_samba.c
gcc -o git_push_samba.so -nostartfiles -shared git_push_samba.o -ldl

Afterwards git can be called as follows:

LD_PRELOAD=path/to/git_push_samba.so git ...

Notes:

  • I called this "git_push_samba" because I wanted to push to a "bare" git repo which resides on a Samba share which was locally mounted to a path. However this even applies to the case that you work normally with git on such a filesystem (like git add failing).

  • There can be several other problems which look the same. So this does not solve all variants of this problem, only the one, where it stems from a faulty (POSIX violating) filesystem driver.

How to determine the problem exists which can be fixed this way:

git init testdir
cd testdir
date > README
git add README

If the git add fails with a "insuffient permission for adding an object", this here should solve this.

2
  • Wow. Yes. Exactly this: Opens file read-only and then complains about not being able to write. Except I got WSL (Windows Subsystem Linux) and it is 2020! Linux BADWLRZ-CW67977 4.4.0-18362-Microsoft #476-Microsoft Fri Nov 01 16:53:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux
    – Chris
    Commented Feb 24, 2020 at 13:40
  • 1
    @Chris The DP macro (from your edit attempt) was an oversight, it's not needed, so I removed it. Thanks for noting.
    – Tino
    Commented Feb 25, 2020 at 19:34
0

your smb folder is seen by linux as in "others" group. So, your permissions should be something like xx7, for example, 777 if you want your www to be writable by all groups.

Problem, everytime git creates a new folder, file or whatever, it will create it using its own permissions. The solution is to use umask, so everything created in the name of the current user will use the permissions specified. In that case, windows shared folder, you will need this:

umask 000

so any new file will be writable by everyone, including "others" gruop, that's it, your shared windows folder.

Add this umask in your .bashrc, and problem solved.

4
  • I've tried umask earlier as well. It didn't help. There's bug report opened on kernel's bugzilla and there are other people who were affected by the upgrade.
    – bjauy
    Commented Dec 19, 2013 at 8:01
  • does this bug affect git, linux or win$? Commented Dec 20, 2013 at 11:30
  • I don't recall mentioning Windows anywhere here. Accepted answer tells exactly what does the bug affect.
    – bjauy
    Commented Dec 22, 2013 at 1:39
  • umask 0000 does not work under WSL either.
    – Chris
    Commented Feb 24, 2020 at 13:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .