Почему в некоторых системах max uid / gid составляет 65534, а не 65535?

4292
user2431763

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

2

3 ответа на вопрос

5
David Schwartz

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

Итак, `(uint16_t) -1` используется для обозначения ошибки? grawity 10 лет назад 0
@ Grawity По крайней мере, это может быть. На самом ли деле это не так, как я знаю. Но это, вероятно, мышление. David Schwartz 10 лет назад 0
Когда я последний раз проверял, (uid_t) -1 == cdrom Joshua 7 лет назад 0
4
JdeBP

Почему 99?

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

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

Почему 65534?

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

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

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

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

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

Тем не менее, для преимуществ программ, которые использовали 16-битный API в ядрах, которые переключились на 32-битные, uid_tи gid_tLinux определил «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
Tonny

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

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

Идентификатор пользователя 0 зарезервирован для пользователя root, а не для ядра. (Вы имели в виду * process * ID 0?) grawity 10 лет назад 3
ОК, но я до сих пор не понимаю полезности этого значения: зачем мне создавать нового пользователя с недействительным (0xffff) uid? Или это означает «оставить без изменений» при вызове setreuid ()? 'man setreuid' говорит, что я должен указать -1 в качестве аргумента, если я не хочу, чтобы uid или gid изменились, но uid_t не подписан. Так я должен поставить 65535? user2431763 10 лет назад 0
@ Grawity Вы правы, конечно. Я имел ввиду root. Слишком мало сна, я бегу не на всех цилиндрах. Буду редактировать пост. Tonny 10 лет назад 0
@ user2431763 Вы не поставите -1 там, но ОС может сделать это. Пример: некоторые разновидности Unix устанавливают UID удаленного пользователя равным -1, но на самом деле они не удаляют пользователя из passwd. (Это имеет то преимущество, что вы все равно можете искать информацию о пользователе, такую ​​как полное имя, домашний каталог, какую оболочку он / она использовали позже). Это также предотвращает повторное использование имени пользователя, что часто запрещено компанией. политика. Tonny 10 лет назад 0

Похожие вопросы