2

Я знаю, что не существует общего максимального значения для uid (или gid): некоторые системы используют 99 (Slackware, ...), другие 65534 (Debian, ...).
Я спрашиваю, есть ли конкретная мотивация для использования 65534, а не 65535 (0xFFFF). Спасибо.

3 ответа3

5

Если максимальный UID равен 65535, то нет значения, указывающего на ошибку или неизвестный UID, если UID хранится в 16-разрядном значении без знака.

4

Почему 99?

Это на самом деле не максимум. Это порог, при котором идентификаторы для "системных" учетных записей останавливаются, а идентификаторы для "реальных" учетных записей запускаются. Это довольно произвольно и переменно тоже. Нет никакой реальной причины, чтобы это было 99, за исключением того, что 100 - удобное круглое число.

Это удобное круглое число, согласованное различными инструментами управления паролями и группами баз данных для платформы. Например, в Debian версии 7 инструменты useradd и groupadd ищут в /etc/login.defs диапазоны UID и GID, которые считаются "системными" и "пользовательскими", а последний диапазон составляет от 1000 до 60000 для обоих UID. и GID.

Почему 65534?

Во-первых, потому что в системных вызовах POSIX есть два распространенных соглашения:

  • Возвращаемое значение -1 (приведенное к типу возвращаемого значения) указывает на ошибку с номером ошибки, доступным из макроса errno .
  • Входное значение -1 указывает «не изменять».

Это не универсальные соглашения. Обратите внимание, что нет возможности возврата ошибки, например, из системного вызова geteuid() . (Процессы всегда имеют эффективные идентификаторы.) Так что нет никаких static_cast<uid_t>(-1) . Но по крайней мере один из них относится к UID и GID. В setreuid() и setregid() аргумент -1 означает "без изменений". Таким образом, static_cast<uid_t>(-1) и static_cast<gid_t>(-1) неправильно используются в качестве реальных идентификаторов.

Во-вторых, потому что UID и GID в Linux раньше были 16-битными.

Это изменилось на 32-битный на рубеже веков, но его эхо живет, и это на самом деле более тонкое, чем кажется на первый взгляд. -1 приведено к 16-битному целому числу без знака, которое, как вы уже заметили, равняется uid_t и gid_t (в интерфейсе системного вызова). Так что это не был пригодный для использования UID или GID.

Однако для преимуществ программ, которые использовали 16-битный API в ядрах, которые переключились на 32-битные uid_t и gid_t , Linux определил "UID переполнения" и "GID переполнения". Это произошло потому, что в разные моменты происходили довольно неприятные взаимодействия из-за преобразования между 16-битным и 32-битным. 16-битные программы видели UID 65536 в качестве суперпользователя, а ядро - нет. Старые ядра видели UID 131072 в качестве суперпользователя, когда код приложения этого не делал.

"UID переполнения" и "GID переполнения" по существу отображают все 32-разрядные идентификаторы UID и GID, превышающие 65535–553434 для 16-разрядного кода. Это означает, что второе значение, 0xFFFE, теперь не может использоваться как реальное значение UID или GID.

И, конечно же, приведение -1 к 32-битному типу UID и GID также невозможно.

0

Системы обычно резервируют самое высокое целое число без знака 0xffff (или -1, если значение интерпретируется как целое число со знаком), чтобы указать "недействительно" или "не используется".
(0xffff 16-битный конечно. Некоторые системы используют 32-битный 0xffffffff.)

Ноль не может быть использован для этого, потому что он зарезервирован для корневого использования.
(Резервирование 0 для root - это, если я правильно помню, соглашение POSIX, которое соблюдается практически любой другой ОС по соображениям совместимости.)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .