Reputation: 517
I'm trying to get Git working on my System, but I always get the error
error: insufficient permission for adding an object to repository database ....../.git/objects
I'm working on a Surface Pro 5 in Windows Subsystem for Linux with Ubuntu.
Everything is working fine if I'm working on the internal drive.
The problem starts when I want to work on my micro SD Card.
First it wasn't mounted automatically.
I fixed that by editing the /etc/fstab
file:
E: /mnt/e drvfs defaults,metadata,rw,exec,uid=nico,gid=nico 0 0
and ls -alR
shows that permissions should be rw for all users and all files.
I tried git add
on an existing repository on this SD Card and it didn't work.
Somehow it created a tmp file in '.git/objects/54/' which had no write permissions every time I tried it.
Then I tried to clone a Test Repository but it created the folder for a splitsec and gave me the same error. It is working though on my normal drive C: but not on my SD Card.
nico@DESKTOP-639MEJ9:/mnt/e$ git clone https://github.com/NicoJG/TestGit.git
Cloning into 'TestGit'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
error: insufficient permission for adding an object to repository database /mnt/e/TestGit/.git/objects
fatal: failed to write object
fatal: unpack-objects failed
nico@DESKTOP-639MEJ9:/mnt/e$ sudo git clone https://github.com/NicoJG/TestGit.git
[sudo] password for nico:
Cloning into 'TestGit'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
error: insufficient permission for adding an object to repository database /mnt/e/TestGit/.git/objects
fatal: failed to write object
fatal: unpack-objects failed
nico@DESKTOP-639MEJ9:/mnt/e$
Somehow git isn't working properly with the permissions in the WSL. I already tried:
sudo chmod -R ug+rw *
sudo chwn -R nico:nico *
Has anyone any idea how to fix it?
Edit: As requested from bk2204 here is the output of mount
:
nico@DESKTOP-639MEJ9:/mnt/e$ mount
rootfs on / type lxfs (rw,noatime)
none on /dev type tmpfs (rw,noatime,mode=755)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,noatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,noatime)
devpts on /dev/pts type devpts (rw,nosuid,noexec,noatime,gid=5,mode=620)
none on /run type tmpfs (rw,nosuid,noexec,noatime,mode=755)
none on /run/lock type tmpfs (rw,nosuid,nodev,noexec,noatime)
none on /run/shm type tmpfs (rw,nosuid,nodev,noatime)
none on /run/user type tmpfs (rw,nosuid,nodev,noexec,noatime,mode=755)
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,relatime)
cgroup on /sys/fs/cgroup type tmpfs (rw,relatime,mode=755)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,relatime,devices)
E: on /mnt/e type drvfs (rw,relatime,uid=1000,gid=1000,case=off)
C:\ on /windir/c type drvfs (rw,noatime,uid=1000,gid=1000,umask=22,fmask=11,metadata,case=off)
I only know what C: (my main drive) and E: (my SD Card) are. The rest seems to be WSL specific I think.
Upvotes: 4
Views: 924
Reputation: 478
I had the exact same problem.
Background
In the latest Windows builds there are some changes in WSL regarding how it interacts with your file system. One problem is the fact that previously, the incompatibility between Windows and Linux file-systems meant most files effectively had permissions ‘777’ on external storage, so any user could read/write/execute anything. This isn’t really ideal for Linux, as you can’t store private keys etc. Microsoft have changed that behaviour now so files can have both Windows (NTFS) and Linux permissions, through extension attributes. On a normal drive it’s fine to overcome, you can mount the drive with metadata using the following command:
umount /mnt/c;
mount -t drvfs C:\\ /mnt/c/ -o metadata
Unfortunately they seem to have rolled that change out to network and external filesystems too (like exFAT
), which doesn’t have extensible attributes and gets in a bit of a mess, making external drives unusable. For example, if the file is read-only in Windows then you can’t write to it in WSL; you can’t override it with sudo
either because Windows permissions override WSL ones regardless. The changes break a lot of programs, which I found out today trying to upload changes to git. It’s one of those new problems which doesn’t actually have solutions on the Internet yet, so I’ve attached a file will solve that issue.
To run, first compile the shared object:
cc -Wall -O3 -D_GNU_SOURCE -fPIC -c -o githack.o githack.c; gcc -o githack.so -nostartfiles -shared githack.o -ldl;
Then run the command prefixed with LD_PRELOAD
:
LD_PRELOAD=./githack.so git commit -a -m "Another interesting commit"
How to investigate for other programs
For git
, the issue specifically is seen:
error: insufficient permission for adding an object to repository database .git/objects
To find out why it failed, you can use strace
:
strace git commit -a -m "Another interesting commit"
>
...
gettimeofday({tv_sec=1592618056, tv_usec=52991}, NULL) = 0
getpid() = 651
openat(AT_FDCWD, ".git/objects/78/tmp_obj_flbKNc", 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
...
Immediately before the error line printed we see why it failed (-1
), so to fix it requires intercepting that call. You can determine that from ltrace
:
ltrace git commit -a -m "Latest local copy"
>
...
open64(".git/objects/78/tmp_obj_zDayCc", 194, 0444) = -1
__errno_location() = 0x7f2777001000
__errno_location() = 0x7f2777001000
__vsnprintf_chk(0x7fffd4786d00, 4096, 1, 4096) = 80
__fprintf_chk(0x7f277631c680, 1, 0x7f27773eacfc, 0x7f27773c8083error: insufficient permission for adding an object to repository database .git/objects
) = 88
close(4)
...
And so the attached code at the bottom of this post intercepts the open64
code with flags equal 194
.
Solution code (name githack.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
//#define openat ignorethisopen
#define open ignorethisopen
#define open64 ignorethisopen64
#include <fcntl.h>
//#undef openat
#undef open
#undef open64
#include <dlfcn.h>
/*
'strace git ...' will show git fail on an openat() command
this is probably implemented as open64() on your system
you can confirm this by use of 'ltrace git ...'
you may also need to adjust the oflag comparison of 194
*/
/*static int (*___openat)(int, char *, int, mode_t);*/
static int (*___open)(const char *, int, mode_t);
static int (*___open64)(const char *, int, mode_t);
static void* dlwrap(const char *fn)
{
const char *e;
void *p = dlsym(RTLD_NEXT, fn);
if ((e=dlerror())!=0)
fprintf(stderr, "dlsym(RTLD_NEXT,'%s'): %s\r\n", fn, e);
return p;
}
void _init(void)
{
___open = dlwrap("open");
___open64 = dlwrap("open64");
}
/*int openat(int dirfd, const char *pathname, int oflag, mode_t mode)*/
int open(const char *pathname, int oflag, mode_t mode)
{
if (oflag && oflag == 194)
return ___open(pathname, oflag, S_IRWXU);
return ___open(pathname, oflag, mode);
}
int open64(const char *pathname, int oflag, mode_t mode)
{
if (oflag && oflag == 194)
return ___open64(pathname, oflag, S_IRWXU);
return ___open64(pathname, oflag, mode);
}
Upvotes: 3