Linux: право на файл, или драма в автотесте
Из ленты: OpenQuality.ru
Добрый день.
Завязка
Как-то раз, в одном автотесте, пользователь root создал пользователя alice. Например, так:
plink.exe -batch blackhawk -l root -pw rootpwd "useradd -m alice" plink.exe -batch blackhawk -l root -pw rootpwd "echo alice:alicepwd | chpasswd"
Пользователь alice вошел в систему и создал там файл (далее для простоты восприятия все действия представлены в интерактивном режиме):
alice@blackhawk:/> touch /tmp/alice.txt alice@blackhawk:/> ls -l /tmp/alice.txt -rw-r--r-- 1 alice users 0 2014-08-05 19:01 /tmp/alice.txt
Затем в автотесте происходили различные манипуляции с файлом, после которых его планировали удалить. Но не удалили. Зато удалили пользователя alice…
blackhawk:~ # userdel alice no crontab for alice
… и создали пользователя bob:
blackhawk:~ # useradd bob blackhawk:~ # passwd bob Changing password for bob. New Password: Reenter New Password: Password changed.
Что случилось с файлами alice, в частности, с /tmp/alice.txt? А ничего не случилось, просто теперь их владельцем стал bob:
blackhawk:~ # ls -l /tmp/alice.txt -rw-r--r-- 1 bob users 0 Aug 5 19:01 /tmp/alice.txt
Кто виноват
Пользователь bob получил полный доступ к файлам, которые были созданы пользователем alice, приказавшим долго жить. Почему так произошло? Здесь сошлись два обстоятельства:
Во-первых, команда useradd в Linux по умолчанию присваивает новому пользователю UID, инкрементируя значение UID предыдущего пользователя:
-u, --uid uid Force the new userid to be the given number. This value must be positive and unique.
The default is to use the first free ID after the greatest used one.
The range from which the user ID is chosen can be specified in /etc/login.defs.
Во-вторых, права на файлы на самом деле определяются не именами пользователей, а их идентификаторами (UID):
blackhawk:~ # ls -ln /tmp/alice.txt -rw-r--r-- 1 1062 100 0 Aug 5 19:01 /tmp/alice.txt blackhawk:~ # less /etc/passwd | grep bob bob:x:1062:100::/home/bob:/bin/bash
В результате, пользователь alice создал файлы, канул в Лету, а его добром завладел пользователь bob, созданный после него.
Разбор полетов
Во-первых, это ожидаемый, но не самый лучший исход с точки зрения защиты информации. Чтобы этого избежать, обычно поступают так: либо удаляют пользователя со всеми его файлами, либо пользователя деактивируют (lock + устаревание пароля). В этом случае пользователь теряет возможность войти в систему, но сам аккаунт остается в системе, и его UID и файлы остаются за ним:
blackhawk:~ # usermod -L -e 2014-07-03 alice Password for `alice' is already locked!
Во-вторых, такое поведение может добавить “остроты” автотестам. Если …
б) файл alice.txt по какой-то причине не был удален вместе с удалением пользователя alice;
в) был создан пользователь bob
… то файлом alice.txt завладевает bob, и при повторном прогоне автотеста пользователь alice не сможет ни создать файл alice.txt, ни удалить:
alice@blackhawk:/> touch /tmp/alice.txt touch: cannot touch `/tmp/alice.txt': Permission denied alice@blackhawk:/> rm -f /tmp/alice.txt rm: cannot remove `/tmp/alice.txt': Operation not permitted
Как избежать подобных ситуаций в автотестах
Во-первых, можно создавать пользователей с домашними каталогами (useradd -m alice), размещать там все временные файлы, удалять пользователей со всеми потрохами и проверять результат.
Во-вторых, можно создавать пользователей с уникальными UID (-u UID в useradd), изменяющимися от запуска к запуску. Для большей наглядности этот же UID можно включить в название файла.
Всего доброго и полегче на поворотах.