in WSL on SD Card, git insufficient permission for adding an object in WSL on SD Card, git insufficient permission for adding an object unix unix

in WSL on SD Card, git insufficient permission for adding an object


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) = 0getpid()                               = 651openat(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) = 88close(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)                                                                                            = 88close(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);}