Depurando as permissões do repositório do git no compartilhamento de samba

1

Eu tenho trabalhado com repositórios git clonados no compartilhamento de samba por cerca de um ano e, além de alguns problemas com a configuração, não houve nenhum problema com ele. Recentemente, tentei adicionar alguns arquivos ao repositório existente e fiquei surpreso ao ver erros de "permissão negada".

Agora posso iniciar o repo vazio, mas quando tento executar strace git add test , obtenho:

    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

Estou usando o git 1.8.4.2, samba 4.1.1 no Archlinux de 64 bits (versão do kernel: 3.12.1). Eu não tenho mudado nada na configuração do git nem do samba desde as idades.

O compartilhamento é montado usando o automount do sistema em / 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 aparece como:

//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)

Permissões:

    $ 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 ..

Eu já tentei:

  • definindo permissões diferentes para compartilhamento - mesmo resultado
  • montagem manual - mesma
  • fazendo o downgrade do samba e git para versões anteriores - sem diferença
  • sudo - funciona, mas eu não gostaria de usá-lo a menos que seja absolutamente necessário
  • mercurial (por curiosidade) - clonagem git repo falhar, hg repos são clonados sem quaisquer problemas
  • alterando o proprietário e o grupo depois de usar o sudo - eles parecem permanecer os mesmos antes e depois de emitir o comando

Existe mais alguma coisa que eu possa fazer para depurá-lo? Estou bastante inclinado a ficar com git, mas não sei o que há de errado com as permissões.

Em relação ao 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, "xK21OR0'
    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
//SERVER/DATA  /media/smb  cifs user,noauto,credentials=/etc/samba/creds,\
workgroup=PRV,uid=1000,gid=users,_netdev,comment=systemd.automount 0 0
\t00", 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

Cria os objetos com 0755 de permissões. Sem sudo temporário arquivos de objeto são deixados com 0555 . Parece que o problema está em criando arquivo com 0444 como usuário regular, o que parece ter permissões de gravação para repo todo.

    
por bjauy 27.11.2013 / 09:58

5 respostas

1

Houve um bug na versão do kernel que eu estava executando. Eu fiz downgrade do kernel para 3.11.6 e git add/commit quando o usuário começou a trabalhar novamente.

    
por 29.11.2013 / 07:37
1

É um bug do kernel no 3.12: link

Faça o downgrade conforme mencionado por @bjauy ou atualize para o 3.13.

    
por 05.02.2014 / 05:56
0

O mais provável é que você tenha feito alterações nesse repositório enquanto está no root, provavelmente usando sudo e agora alguns dos arquivos em .git são de propriedade de root. Faça um chown para redefinir a propriedade do arquivo para o usuário que você costuma usar.

    
por 27.11.2013 / 18:17
0

sua pasta smb é vista pelo linux como no grupo "outros". Portanto, suas permissões devem ser algo como xx7, por exemplo, 777 se você quiser que sua www seja gravável por todos os grupos.

Problema, toda vez que o git cria uma nova pasta, arquivo ou qualquer outra coisa, ele irá criá-lo usando suas próprias permissões. A solução é usar umask, então tudo criado no nome do usuário atual usará as permissões especificadas. Nesse caso, pasta compartilhada do Windows, você precisará disso:

umask 000

Assim, qualquer novo arquivo será gravável por todos, incluindo "outros", isto é, sua pasta compartilhada do Windows.

Adicione esta umask no seu .bashrc e solucione o problema.

    
por 18.12.2013 / 11:26
0

Ao meu lado, eu atinjo o problema acima devido a uma violação POSIX em um driver do sistema de arquivos no kernel usado em combinação com o Samba. Como não posso usar sudo nem alterar o kernel, nem alterar a versão do Samba, precisei de outra solução.

Eu não tentei corrigir isso com um git compilado localmente, em vez disso, minha solução foi corrigi-lo via LD_PRELOAD on the fly.

Você pode encontrar a solução completa no link

A parte problemática é que git cria um arquivo para gravação com o modo somente leitura. Isso está correto, mas com uma certa combinação de driver FS defeituoso, isso leva ao syscall falhando assim:

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

Isso faz com que git desista. No entanto, com um modo alterado para 0644 este syscall voltaria com sucesso. Após hack faz isso:

#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)
{
  DP(("open wrappe"));

  ___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);
}

Ele precisa ser compilado da seguinte forma:

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

Depois, git pode ser chamado da seguinte forma:

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

Notas:

  • Eu chamei isso de "git_push_samba" porque queria enviar para um "%" git repo que reside em um compartilhamento do Samba que foi montado localmente em um caminho. No entanto, isso também se aplica ao caso em que você trabalha normalmente com git nesse sistema de arquivos (como git add failing).

  • Pode haver vários outros problemas que parecem os mesmos. Portanto, isso não resolve todas as variantes desse problema, apenas a que decorre de um driver de sistema de arquivos defeituoso (POSIX que viola).

Como determinar o problema que pode ser corrigido desta forma:

git init testdir
cd testdir
date > README
git add README

Se o git add falhar com uma "permissão insuficiente para adicionar um objeto", isso deve resolver isso.

    
por 22.09.2016 / 17:42