У меня была аналогичная проблема с git
, когда вы не могли выполнить фиксацию с различными ошибками crypti c. Частично это то, как git
открывает файлы, так что, надеюсь, этот пост поможет раскрыть это.
Фон
В последних сборках Windows есть некоторые изменения в WSL, касающиеся его взаимодействия с вашей файловой системой. Одна из проблем заключается в том, что ранее несовместимость между файловыми системами Windows и Linux означала, что большинство файлов фактически имели разрешения «777» на внешнем хранилище, поэтому любой пользователь мог читать / писать / выполнять что угодно. Это не совсем идеально для Linux, так как вы не можете хранить закрытые ключи et c. Microsoft изменила это поведение, теперь файлы могут иметь разрешения Windows (NTFS) и Linux с помощью атрибутов расширения. На обычном диске это нормально преодолеть, вы можете смонтировать диск с метаданными, используя следующую команду:
umount /mnt/c;
mount -t drvfs C:\\ /mnt/c/ -o metadata
К сожалению, они, похоже, сделали это изменение для сетевых и внешних файловых систем (например, exFAT
), который не имеет расширяемых атрибутов и попадает в небольшой беспорядок, делая внешние диски непригодными для использования. Например, если файл в Windows доступен только для чтения, тогда вы не сможете писать в него в WSL; вы не можете переопределить его с помощью sudo
, потому что Windows разрешения переопределяют разрешения WSL. Изменения нарушают работу многих программ, о которых я сегодня узнал, пытаясь загрузить изменения в git. Это одна из тех новых проблем, для которой на Inte rnet пока нет решений, поэтому я прикрепил файл, который решит эту проблему.
Для запуска сначала скомпилируйте общий объект:
cc -Wall -O3 -D_GNU_SOURCE -fPIC -c -o githack.o githack.c; gcc -o githack.so -nostartfiles -shared githack.o -ldl;
Затем запустите команду с префиксом LD_PRELOAD
:
LD_PRELOAD=./githack.so git commit -a -m "Another interesting commit"
Как исследовать другие программы
Для git
проблема конкретно замечена:
error: insufficient permission for adding an object to repository database .git/objects
Чтобы выяснить, почему это не удалось, вы можете использовать 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
...
Непосредственно перед выводом строки ошибки мы видим, почему это не удалось (-1
), поэтому для его исправления требуется перехват этого вызова. Вы можете определить это по ltrace
:
ltrace git commit -a -m "Latest local copy from George"
>
...
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)
...
И поэтому прикрепленный код внизу этого сообщения перехватывает код open64
с флагами, равными 194
.
Код решения (название 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
George O'Neill 2020/06/20 (feel free to reach out if issues remain)
*/
/*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);
}