2009-08-03 1 views
5

Есть ли способ изменить UID/GID только одного потока в многопоточном процессе?Изменение UID/GID только одного потока в Linux

Причина в том, что это приложение для подачи файлов - ACL и квота не применяются, если только uid/gid вызывающего пользователя не установлен на правильный пользователь, новые файлы/каталоги не создаются с правильным uid/gid и т. д.

Сетевые приложения обычно могут использовать fork() в начале и обрабатывать каждый запрос пользователя в отдельном процессе. Если есть необходимость в общих данных, она должна проходить через какую-то общую память. Однако, например, FUSE (файловая система пользователя linux) по умолчанию использует многопоточность и в сочетании с привязками python было бы нецелесообразно пытаться использовать модель forking.

«Согласованный» UID для всего процесса, по-видимому, соответствует стандарту POSIX, однако старые Linux не следовали POSIX и допускали разные uids для разных потоков. Кажется, что новые ядра следуют POSIX, есть ли способ разрешить старое «нарушение» поведения?

ответ

5

Вы проверили, установлены ли setfsuid()/setfsgid() для каждой нити или для процесса? Они разработаны специально для этого варианта использования (файловый сервер).

+0

Это лучше - я проверил и удивительно узнал, что они действительно в потоке. Вероятно, это будет предпочтительным способом. Однако - причина, по которой я не тестировал это, что quota() и access() не работают. Другие вещи работают - так что это, вероятно, ошибка Linux. – ondra

+0

Да, это звучит как ошибка, так как комментарии в коде ядра для sys_setfsuid() конкретно упоминают access() ... – caf

+0

@Ondrej, пожалуйста, отправьте код (или ссылку на него), демонстрируя, что 'fsuid' is , в отличие от других конструкций UID/GID, для потоков, а не для каждого процесса. Также укажите свои версии ядра и glibc, а также вашу реализацию потоков (NPTL, LinuxThreads, OndrejThreads и т. Д.). – pilcrow

5

Чтобы изменить uid только для одного потока, вам нужно использовать syscall напрямую: syscall (SYS_setresuid, ...); Функция libc setresuid() будет синхронизировать ее для всех потоков (используя сингл, который он посылает всем потокам)!