Та же проблема. Используя информацию, представленную в этой теме, я смог пойти дальше.
Я использовал apt source python2.7
и debuild -b -uc -us
, чтобы подробно изучить, как был собран официальный пакет. Реализация imp.get_suffixes()
находится по адресу Python/import.c :2940 imp_get_suffixes(...)
, который считывает суффиксы из списка с именем _PyImport_Filetab
. Этот список, в свою очередь, в основном _PyImport_DynLoadFiletab
и _PyImport_StandardFiletab
конкатенирован.
Стало очевидно, что _PyImport_DynLoadFiletab
— это то, что нам следует искать, и его определение различается для разных платформ -они есть в Python/dynload _*.c. В Python/dynload _shlib.c — это:
const struct filedescr _PyImport_DynLoadFiletab[] = {
#ifdef __CYGWIN__
{".dll", "rb", C_EXTENSION},
{"module.dll", "rb", C_EXTENSION},
#else
#if defined(PYOS_OS2) && defined(PYCC_GCC)
{".pyd", "rb", C_EXTENSION},
{".dll", "rb", C_EXTENSION},
#else
#ifdef __VMS
{".exe", "rb", C_EXTENSION},
{".EXE", "rb", C_EXTENSION},
{"module.exe", "rb", C_EXTENSION},
{"MODULE.EXE", "rb", C_EXTENSION},
#else
#ifdef Py_DEBUG
{"_d.so", "rb", C_EXTENSION},
{"module_d.so", "rb", C_EXTENSION},
# ifdef MULTIARCH
{"." MULTIARCH "_d.so", "rb", C_EXTENSION},
# endif
#endif
#ifdef MULTIARCH
{"." MULTIARCH ".so", "rb", C_EXTENSION},
#endif
{".so", "rb", C_EXTENSION},
{"module.so", "rb", C_EXTENSION},
#endif
#endif
#endif
{0, 0}
};
Это прямо здесь :MULTIARCH
, если вы посмотрите на журнал сборки, это"x86_64-linux-gnu"
(с кавычками из-за -
s ). Значение, по-видимому, взято из dpkg-architecture -qDEB_HOST_MULTIARCH
, но я не проверял.
Что еще более важно, _PyImport_DynLoadFiletab
не выглядит так изначально в dynload _shlib.c, он был исправлен. Таким образом, чтобы получить такое же поведение, необходимо также применить некоторый патч, по крайней мере, добавить часть {"." MULTIARCH ".so",...}
. В моем случае достаточно пропатчить этот файл (dynload _shlib.c ).
Проблема в том, что он пытается повторно -выполнить себя какcapsh
(или любое другое имя команды и путь, который вы запустили с ).
Это изstrace capsh == --print
:
execve("capsh", ["capsh", "--print"], [/* 20 vars */]) = -1 ENOENT (No such file or directory)
write(2, "execve /bin/bash failed!\n", 25execve /bin/bash failed!
) = 25
Так что на самом деле не " execve /bin/bash
" терпит неудачу, а execve capsh
. Функция execve()
не выполняет поиск в $PATH
.
Использование capsh
с его полным путем заставит его работать.
$ command -v capsh
/sbin/capsh
$ /sbin/capsh == --print
Current: =
[... etc....]
См. также руководство execve(2)
по вашей системе(man 2 execve
).
Если исходный код , который я нашел , верен, он, похоже, использует одни и те же несколько строк как для ==
, так и для --
:
} else if ((!strcmp("--", argv[i])) || (!strcmp("==", argv[i]))) {
argv[i] = strdup(argv[i][0] == '-' ? "/bin/bash" : argv[0]);
argv[argc] = NULL;
execve(argv[i], argv+i, envp);
fprintf(stderr, "execve /bin/bash failed!\n");
exit(1);
}
Как сказал Кусалананда, он не найдет capsh
, так как execve()
не ищет пути, а сообщение об ошибке жестко закодировано для случая /bin/bash
.
Вероятно, это ошибка в libcap :capsh, которую мы исправили в прошлом году:
https://bugzilla.kernel.org/show_bug.cgi?id=209873
Если эта проблема сохраняется в версиях libcap после 2.45, дайте мне знать.