- Linux sysadmin basics: User account management with UIDs and GIDs
- Introduction to UIDs and GIDs
- More Linux resources
- Customizing UIDs and GIDs
- Managing group permissions
- Wrapping up
- Thread: uid=1000. gid=1000. why 1000?
- uid=1000. gid=1000. why 1000?
- Re: uid=1000. gid=1000. why 1000?
- Re: uid=1000. gid=1000. why 1000?
- Re: uid=1000. gid=1000. why 1000?
- Re: uid=1000. gid=1000. why 1000?
- Глубокое погружение в Linux namespaces, часть 2
- User Namespaces
- Маппинги User ID
- Map-файлы
- Написание UID Map файлов
- Владелец пространств имён и привилегии
- Как разрешаются ID
- Групповые ID
- Реализация
Linux sysadmin basics: User account management with UIDs and GIDs
Like many sysadmin tasks and duties, user account management isn’t just one thing, nor does it exist in a vacuum. User account management is an ongoing job aspect and there are many facets to it: account creation, account removal, permissions manipulation, expiring accounts, establishing password standards, enforcing security, enforcing password changes, and manipulating UIDs and GIDs to keep a system organized and supportable. Part one focused on useful commands. This current article deals with managing user IDs (UIDs) and group IDs (GIDs).
Introduction to UIDs and GIDs
By default, Linux systems automatically assign UIDs and GIDs to new user accounts in numerical order starting at 1000. In other words, if you create a new user account during installation, it will have UID = 1000 and GID = 1000, as shown below:
More Linux resources
The theory behind this arbitrary assignment is that anything below 1000 is reserved for system accounts, services, and other special accounts, and regular user UIDs and GIDs stay above 1000. This theory is based on the assumption that 999 account numbers minus a few pre-assigned ones will be more than enough to satisfy most systems for many years. As a Linux administrator for more than 20 years, I’ve never personally run out of those first 999 system account numbers.
The root account has the awesome privilege of having UID = 0 and GID = 0. These numbers are what give the root account its overwhelming power. If you don’t believe me, rename the root account to goonygoogoo , or whatever you choose, and then create a new user account named root , allowing the system to assign the next available UID and GID to it. This account has no more power than any other user account on the system. It’s not the name, but the UID and the GID that give the administration account its power. To further test this assertion, assign a test user account with 0 for the UID and GID, and that user is now root, regardless of the account name.
As you can see from the list below, user accounts are (as stated earlier) assigned UID and GID in numerical order from 1000. The UID and GID always match to keep things organized:
There’s no magic in this setup. The system does it. I don’t have to worry about it.
But what if your policies are different concerning user and group information? It’s possible that your company wants UIDs and GIDs assigned based on employee ID or some other unique identifier (Hopefully not Social Security Number, although I have seen this number used in practice.) Or, what if you want to assign specific GIDs based on roles rather than adding users to a GID in /etc/group ? Well, it’s easy enough to do any of this with the useradd command from my previous article on this topic, which covered user account management basics.
The following is the user list from /etc/group :
Customizing UIDs and GIDs
Traditionally, administrators wanting to add a user to non-primary groups do so at account creation, using the useradd tool with the -G switch. Be sure to list all secondary groups after the -G switch, separated by commas with no spaces. The following command allows the system to pick the UID and primary GID from the next available number but adds user jdoe to the sysadmin and helpdesk groups:
If you want to specify the primary group with the -g switch, the group must already exist. For example, if you enter the following command:
You will get the error «useradd: group ‘10600’ does not exist,» and the system won’t create the account. If you must specify the group, then add the group first:
Managing group permissions
When users create files, the user owner gets read (r) and write (w) permissions, the group gets read permission, and others get read permission (rw-r—r—), or in numeric terms, 644. The execute (x) permission is not given by default. So, as a system administrator, if a group member requests execute permission be placed on a file or group of files, then grant execute permission for the group only:
The user can change the permission themselves if they are the user owner but often will not do so for fear of doing it incorrectly. Only the user owner or the root user can change permissions on a file even if the group has write permission to the file. Write permission means that a group member can edit or delete the file.
Be sure that shared group directories have write access (permission) for the group, and that the files that need to be modified by group members also have write access. Some of you who have more advanced permissions knowledge are probably asking why I don’t mention the chattr (change attributes) command, and it’s a valid question. The chattr command is out of scope for this article but will be covered in a later article that focuses solely on chattr and its many options.
Wrapping up
This article provides brief coverage of the UID and GID attributes and how to manipulate those if you need to do so. I also covered a bit about group permissions. In a future article, I’ll cover the chattr command that gives you options to prevent accidental deletion by group members. If you want to read ahead, do so with caution. The chattr command can be frustrating for new administrators who aren’t familiar with its syntax and option consequences.
[Want to try out Red Hat Enterprise Linux? Download it now for free. ]
Источник
Thread: uid=1000. gid=1000. why 1000?
Thread Tools
Display
uid=1000. gid=1000. why 1000?
A very simple question.
uid seems to be user id, while gid seems to be group id.
But, why I notice many times that both variables are assigned to 1000? Does this 1000 have some particular meanings?
Re: uid=1000. gid=1000. why 1000?
No, some distros use 500 for UID and GID for instance. I use 1000 as UID for first user and GID 100 (users). Assigning unique GID to every user may or may not be reasonable, depends on what are the security and privacy requirements.
Re: uid=1000. gid=1000. why 1000?
1000 just happens to be the point where human user ID’s start in Ubuntu. That gives plenty of user id’s for system services, and in the end where to start human users is just a question of choosing nice a number to start counting from. And since you are the first user created on the machine, you’ll of course get the first UID and GID as well.
Most Linux and Unix systems start counting human user’s IDs from 500 or 1000, depending on your distribution (or Unix variant).
Re: uid=1000. gid=1000. why 1000?
below 1000 there are system related apps which use gid, like www-data which is used commonly gid = 33.
Re: uid=1000. gid=1000. why 1000?
Thank you very much for all the clear explanation. Thanks .
Источник
Глубокое погружение в Linux namespaces, часть 2
В предыдущей части мы только окунули пальцы ног в воды namespace и при этом увидели, как это было просто — запустить процесс в изолированном UTS namespace. В этом посте мы осветим User namespace.
Среди прочих ресурсов, связанных с безопасностью, User namespaces изолирует идентификаторы пользователей и групп в системе. В этом посте мы сосредоточимся исключительно на ресурсах user и group ID (UID и GID соответственно), поскольку они играют фундаментальную роль в проведении проверок разрешений и других действий во всей системе, связанных с безопасностью.
В Linux эти ID — просто целые числа, которые идентифицируют пользователей и группы в системе. И каждому процессу назначаются какие-то из них, чтобы задать к каким операциями/ресурсам этот процесс может и не может получить доступ. Способность процесса нанести ущерб зависит от разрешений, связанных с назначенными ID.
User Namespaces
Мы проиллюстрируем возможности user namespaces, используя только пользовательские ID. Точно такие же действия применимы к групповым ID, к которым мы обратимся далее в этому посте.
User namespace имеет собственную копию пользовательского и группового идентификаторов. Затем изолирование позволяет связать процесс с другим набором ID — в зависимости от user namespace, которому он принадлежит в данный момент. Например, процесс $pid может выполняться от root (UID 0) в user namespace P и внезапно продолжает выполняться от proxy (UID 13) после переключения в другой user namespace Q.
User spaces могут быть вложенными! Это означает, что экземпляр пользовательского namespace (родительский) может иметь ноль и больше дочерних пространств имён, и каждое дочернее пространство имён может, в свою очередь, иметь свои собственные дочерние пространства имён и так далее… (до достижения предела в 32 уровня вложенности). Когда создаётся новый namespace C, Linux устанавливает текущий User namespace процесса P, создающего C, как родительский для C и это не может быть изменено впоследствии. В результате все user namespaces имеют ровно одного родителя, образуя древовидную структуру пространств имён. И, как и в случае с деревьями, исключение из этого правила находится наверху, где у нас есть корневой (или начальный, дефолтный) namespace. Это, если вы еще не делаете какую-то контейнерную магию, скорее всего user namespace, к которому принадлежат все ваши процессы, поскольку это единственный user namespace с момента запуска системы.
В этом посте мы будем использовать приглашения командной строки P$ и C$ для обозначения шела, который в настоящее время работает в родительском P и дочернем C user namespace соответственно.
Маппинги User ID
User namespace, по сути, содержит набор идентификаторов и некоторую информацию, связывающую эти ID с набором ID других user namespace — этот дуэт определяет полное представление о ID процессов, доступных в системе. Давайте посмотрим, как это может выглядеть:
В другом окне терминала давайте запустим шелл с помощью unshare (флаг -U создаёт процесс в новом user namespace):
Погодите, кто? Теперь, когда мы находимся во вложенном шелле в C, текущий пользователь становится nobody? Мы могли бы догадаться, что поскольку C является новым user namespace, процесс может иметь иной вид ID. Поэтому мы, возможно, и не ждали, что он останется iffy , но nobody — это не смешно. С другой стороны, это здорово, потому что мы получили изолирование, которое и хотели. Наш процесс теперь имеет другую (хоть и поломанную) подстановку ID в системе — в настоящее время он видит всех, как nobody и каждую группу как nogroup .
Информация, связывающая UID из одного user namespace с другим, называется маппингом user ID. Он представляет из себя таблицы поиска соответствия ID в текущем user namespace для ID в других namespace и каждый user namespace связан ровно одним маппингом UID (в дополнение еще к одному маппингу GID для group ID).
Этот маппинг и есть то, что сломано в нашем unshare шелле. Оказывается, что новые user namespaces начинаются с пустого маппинга, и в результате Linux по умолчанию использует ужасного пользователя nobody . Нам нужно исправить это, прежде чем мы сможем сделать какую-либо полезную работу в нашем новом пространстве имён. Например, в настоящее время системные вызовы (например, setuid ), которые пытаются работать с UID, потерпят неудачу. Но не бойтесь! Верный традиции всё-есть-файл, Linux представляет этот маппинг с помощью файловой системы /proc в /proc/$pid/uid_map (в /proc/$pid/gid_map для GID), где $pid — ID процесса. Мы будем называть эти два файла map-файлами
Map-файлы
Map-файлы — особенные файлы в системе. Чем особенные? Ну, тем, что возвращают разное содержимое всякий раз, когда вы читаете из них, в зависимости от того, какой ваш процесс читает. Например, map-файл /proc/$pid/uid_maps возвращает маппинг от UID’ов из user namespace, которому принадлежит процесс $pid , UID’ам в user namespace читающего процесса. И, как следствие, содержимое, возвращаемое в процесс X, может отличаться от того, что вернулось в процесс Y, даже если они читают один и тот же map файл одновременно.
В частности, процесс X, считывающий UID map-файл /proc/$pid/uid_map , получает набор строк. Каждая строка отображает непрерывный диапазон UID’ов в user namespace C процесса $pid , соответствующий диапазону UID в другом namespace.
Каждая строка имеет формат $fromID $toID $length , где:
- $fromID является стартовым UID диапазона для user namespace процесса $pid
- $lenght — это длина диапазона.
- Трансляция $toID зависит от читающего процесса X. Если X принадлежит другому user namespace U, то $toID — это стартовый UID диапазона в U, который мапится с $fromID . В противном случае $toID — это стартовый UID диапазона в P — родительского user namespace процесса C.
Например, если процесс читает файл /proc/1409/uid_map и среди полученных строк видно 15 22 5 , то UID’ы с 15 по 19 в user namespace процесса 1409 маппятся в UID’ы 22-26 отдельного user namespace читающего процесса.
С другой стороны, если процесс читает из файла /proc/$$/uid_map (или map-файла любого процесса, принадлежащего тому же user namespace, что и читающий процесс) и получает 15 22 5 , то UID’ы c 15 по 19 в user namespace C маппятся в UID’ы c 22 по 26 родительского для C user namespace.
Давайте это попробуем:
Хорошо, это было не очень захватывающе, так как это были два крайних случая, но это говорит там о нескольких вещах:
- Вновь созданный user namespace будет фактически иметь пустые map-файлы.
- UID 4294967295 не маппится и непригоден для использования даже в root user namespace. Linux использует этот UID специально, чтобы показать отсутствие user ID.
Написание UID Map файлов
Чтобы исправить наш вновь созданный user namespace C, нам просто нужно предоставить наши нужные маппинги, записав их содержимое в map-файлы для любого процесса, который принадлежит C (мы не можем обновить этот файл после записи в него). Запись в этот файл говорит Linux две вещи:
- Какие UID’ы доступны для процессов, которые относятся к целевому user namespace C.
- Какие UID’s в текущем user namespace соответствуют UID’ам в C.
Например, если мы из родительского user namespace P запишем следующее в map-файл для дочернего пространства имён C:
мы по существу говорим Linux, что:
- Что касается процессов в C, единственным UID’ами, которые существуют в системе, являются UID’ы 0 и 3 . Например, системный вызов setuid(9) всегда будет завершаться чем-то вроде недопустимого id пользователя.
- UID’ы 1000 и 0 в P соответствуют UID’ам 0 и 3 в C. Например, если процесс, работающий с UID 1000 в P, переключится в C, он обнаружит, что после переключения его UID стал root 0 .
Владелец пространств имён и привилегии
В предыдущем посте мы упомянули, что при создании новых пространств имён требуется доступ с уровнем суперпользователя. User namespaces не налагают этого требования. На самом деле, еще одной их особенностью является то, что они могут владеть другими пространствами имён.
Всякий раз, когда создаётся не user namespace N, Linux назначает текущий user namespace P процесса, создающего N, владельцем namespace N. Если P создан наряду с другими пространствами имён в одном и том же системном вызове clone , Linux гарантирует, что P будет создан первым и назначен владельцем других пространств имён.
Владелец пространств имён важен потому, что процесс, запрашивающий выполнения привилегированного действия над ресурсом, задействованным не user namespace, будет иметь свои UID привилегии, проверенные в отношении владельца этого user namespace, а не корневого user namespace. Например, скажем, что P является родительским user namespace дочернего C, а P и C владеют собственными network namespace M и N соответственно. Процесс может не иметь привилегий для создания сетевых устройств, включенных в M, но может быть в состоянии это делать для N.
Следствием наличия владельца пространств имён для нас является то, что мы можем отбросить требование sudo при выполнении команд с помощью unshare или isolate , если если мы запрашиваем также создание и user namespace. Например, unshare -u bash потребует sudo , но unshare -Uu bash — уже нет:
К сожалению, мы повторно применим требование прав суперпользователя в следующем посте, так как isolate нуждается в привилегиях root в корневом user namespace, чтобы корректно настроить Mount и Network namespace. Но мы обязательно отбросим привилегии командного процесса, чтобы убедиться, что команда не имеет ненужных разрешений.
Как разрешаются ID
Мы только что увидели процесс, запущенный от обычного пользователя 1000 внезапно переключился на root . Не волнуйтесь, никакой эскалации привилегий не было. Помните, что это просто маппинг ID: пока наш процесс думает, что он является пользователем root в системе, Linux знает, что root — в его случае — означает обычный UID 1000 (благодаря нашему маппингу). Так что в то время, когда пространства имён, принадлежащие его новому user namespace (подобно network namespace в C), признают его права в качестве root , другие (как например, network namespace в P) — нет. Поэтому процесс не может делать ничего, что пользователь 1000 не смог бы.
Всякий раз, когда процесс во вложенном user namespace выполняет операцию, требующую проверки разрешений — например, создание файла — его UID в этом user namespace сравнивается с эквивалентным ID пользователя в корневом user namespace путём обхода маппингов в дереве пространств имён до корня. В обратном направлении происходит движение, например, когда он читает ID пользователей, как мы это делаем с помощью ls -l my_file . UID владельца my_file маппится из корневого user namespace до текущего и окончательный соответствующий ID (или nobody, если маппинг отсутствовал где-либо вдоль всего дерева) отдаётся читающему процессу.
Групповые ID
Даже если мы оказались root в C, мы до сих пор ассоциированы с ужасной nogroup в качестве нашего ID группы. Нам просто нужно сделать то же самое для соответствующего /proc/$pid/gid_map . Прежде чем мы сможем это сделать, нам нужно отключить системный вызов setgroups (в этом нет необходимости, если у нашего пользователя уже есть CAP_SETGID capability в P, но мы не будем предполагать этого, поскольку это обычно идёт вместе с привилегиями суперпользователя), написав «deny» в файл proc/$pid/setgroups :
Реализация
Как вы можете видеть, есть много сложностей, связанных с управлением user namespaces, но реализация довольно проста. Всё, что нам нужно сделать, это написать кучу строк в файл — муторно было узнать, что и где писать. Без дальнейших церемоний, вот наши цели:
- Клонировать командного процесса в его собственном user namespace.
- Написать в UID и GID map-файлы командного процесса.
- Сбросить все привилегии суперпользователя перед выполнением команды.
1 достигается простым добавлением флага CLONE_NEWUSER в наш системный вызов clone .
Для 2 мы добавляем функцию prepare_user_ns , которая осторожно представляет одного обычного пользователя 1000 в качестве root .
И вызовем его из основного процесса в родительском user namespace прямо перед тем, как мы подадим сигнал командному процессу.
Для шага 3 мы обновляем функцию cmd_exec , чтобы убедиться, что команда выполняется от обычного непривилегированного пользователя 1000 , которого мы предоставили в маппинге (помните, что root пользователь 0 в user namespace командного процесса — это пользователь 1000 ):
И это всё! isolate теперь запускает процесс в изолированном user namespace.
В этом посте было довольно много подробностей о том, как работают User namespaces, но в конце концов настройка экземпляра была относительно безболезненной. В следующем посте мы рассмотрим возможность запуска команды в своём собственном Mount namespace с помощью isolate (раскрывая тайну, стоящую за инструкцией FROM из Dockerfile ). Там нам потребуется немного больше помочь Linux, чтобы правильно настроить инстанс.
Источник