Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Вопрос по залогиниванию  (Прочитано 24100 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« : 23-11-2014 16:40 » 

Доброго дня.

Итак, интересно разобраться немного подробнее с вот чем:
когда запускается linux, его первый процесс (PID 1) запускается ядром. Далее этот процесс разветвляется, запуская кучу чего, и вот, в некий момент, он вызывает, в очередной раз, fork (для примера, новый процесс PID 100, процесс предок PPID 1), и запускает getty, которая создаёт необходимый буфер для консоли, обеспечивает вывод информации на экран, а также файл устройства, например, tty3. Далее, getty, также делает fork, запуская программу login (PID 101 PPID 100), та, соответственно, запрашивает имя пользователя, пароль, и, полагаю, есть тоже какой-то системный вызов, которые эти данные передаёт ядру для сверки, после чего, ядро как-бы регистрирует права конкретного пользователя на доступ к ресурсам ПК к конкретному процессу. Мало того, все последующие вызовы fork из этого залогиненного процесса будут наследоваться потомками. Затем запускается оболочка bash (PID 102 PPID 101), и мы пишем команды от лица зарегистрированного пользователя.

Вопрос, во-первых, какими правами обладают процессы, которые запускает init до залогинивания? root?

Во-вторых, когда в bash набираю exit он возвращается на уровень login, то есть как-бы разлогинивается. По идее должен иметься системный вызов, на отмену регистрации, тогда к каким правам вернулась программа login?

В-третьих, в tty1 я запускаю процесс aaa &.
Консоль пишет: ...PID 140...
То есть, запустился новый процесс. Если затем разлогиниться, получается этот процесс так и сохранится с правами того пользователя из под которого был запущен?

Буду рад, указаниям на мои ошибки в понимании.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 23-11-2014 17:04 » 

Есть система логинов PAM http://en.wikipedia.org/wiki/Pluggable_authentication_module Собственно она отвечает за логины. После прохождения логина, запускается оболочка уже с правами того пользователя, который прошел логин.  После выхода, ты обратно попадеш в PAM. Т.е. родителю оболочки. Тут не нужны никакие лишние системные вызовы.

По идее говоря, после прекрашения работы родителя, дочерний процесс будет передан init. Т.е. его родителем станет процесс с id 0 Но права пользователя у него останутся.
« Последнее редактирование: 23-11-2014 17:08 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 23-11-2014 17:20 » 

Хорошо, например, я включаю свою программу в init скрипт, она внутри, неважно как, пытается сделать, например, chmod file 777, который принадлежит root и имеет право доступа 700. Всё это произойдёт до залогинивания, отсюда:
если она будет иметь права root -> будут изменены параметры доступа к файлу,
если она не будет иметь прав root этого не будет. Так что же будет?

То есть, получается, PPID процесса изменится на 0, если его истинный предок завершится.
« Последнее редактирование: 23-11-2014 17:22 от Aether » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 23-11-2014 19:24 » 

Если нет прав на запись, то ты не сможеш изменить права доступа. И еще, сначало идет права пользователя, потом группы, а потом всех остальных. Запретив пользователю например в доступе на чтение, даже если для группы будут такие права, пользователь все равно не сможет прочитать файл.
У программы поменялся родитель, но не права доступа. Т.е. если программа была запушена с правами доступа пользователя Foo, даже если у нее поменяется родитель, у нее все равно будут права доступа Foo.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #4 : 24-11-2014 09:06 » 

когда запускается linux, его первый процесс (PID 1) запускается ядром. Далее этот процесс разветвляется, запуская кучу чего, и вот, в некий момент, он вызывает, в очередной раз, fork (для примера, новый процесс PID 100, процесс предок PPID 1), и запускает getty, которая создаёт необходимый буфер для консоли, обеспечивает вывод информации на экран, а также файл устройства, например, tty3. Далее, getty, также делает fork, запуская программу login (PID 101 PPID 100), та, соответственно, запрашивает имя пользователя, пароль, и, полагаю, есть тоже какой-то системный вызов, которые эти данные передаёт ядру для сверки, после чего, ядро как-бы регистрирует права конкретного пользователя на доступ к ресурсам ПК к конкретному процессу.
Мало того, все последующие вызовы fork из этого залогиненного процесса будут наследоваться потомками. Затем запускается оболочка bash (PID 102 PPID 101), и мы пишем команды от лица зарегистрированного пользователя.
По-моему getty, работает немного не так. Он запрашивает логин, потом exec()-ом запускает /bin/login, который в свою очередь запрашивает пароль и, при его соответствии, exec()-ом запускает shell. Но перед этим он вызовами типа setuid() и setgid(), а может и ещё какими устанавливает себе соответствующие идентификаторы пользователя и группы.

Вопрос, во-первых, какими правами обладают процессы, которые запускает init до залогинивания? root?
Из той технологии, которая описана выше, видно, что они обладают правами пользователя root.

Во-вторых, когда в bash набираю exit он возвращается на уровень login, то есть как-бы разлогинивается. По идее должен иметься системный вызов, на отмену регистрации, тогда к каким правам вернулась программа login?
После завершения процесса, init видит, что завершился процесс getty (который потом переопределялся exec()-ами, но для init-а, он является всё тем-же процессом, всё с тем-же 100-ым условным идентификатором) и init запускает новый процесс getty.

В-третьих, в tty1 я запускаю процесс aaa &.
Консоль пишет: ...PID 140...
То есть, запустился новый процесс. Если затем разлогиниться, получается этот процесс так и сохранится с правами того пользователя из под которого был запущен?
Да, права относятся к процессу, соответственно их он не потеряет - даже после завершения родительского shell-а и даже сессии он будет иметь те права, которые он получил при запуске.

Хорошо, например, я включаю свою программу в init скрипт, она внутри, неважно как, пытается сделать, например, chmod file 777, который принадлежит root и имеет право доступа 700. Всё это произойдёт до залогинивания, отсюда:
если она будет иметь права root -> будут изменены параметры доступа к файлу,
если она не будет иметь прав root этого не будет. Так что же будет?

То есть, получается, PPID процесса изменится на 0, если его истинный предок завершится.
Если Ваша программа будет включена в сценарий инициализации - будет иметь права root-а, с которым запускается init, разве что Вы специально попробуете запустить её через sudo.

То есть, получается, PPID процесса изменится на 0, если его истинный предок завершится.
Предком процесса будет назначен процесс, с PID-ом равным 1, который, кроме всего прочего, занимается убиранием процессов-зомби - процессов, которые завершились, а статуса их завершения так ни кто и не затребовал, по причине, например, ошибки в родительском процессе или преждевременной смерти родителя. Вот за тем, что-бы они смогли наконец-то упокоиться с миром и следит init.
« Последнее редактирование: 24-11-2014 09:14 от darkelf » Записан
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 24-11-2014 17:16 » 

Да, весьма подробно, спасибо.)

Я поизучал документацию, нашёл описание сис. вызова setuid().

Прототип функции получается:
int setuid(uid_t UID);
Возвращает она результат: успешно(0)/не успешно(-1);

Но запроса пароля, логина... нету. Есть только число UID,
как я понял, при вызове из процесса с правами root сис. вызов переключит права на указанный UID, если же право процесса уже не root, то вернёт ошибку.
Странно, если я правильно понимаю, то все пароли, логины, проверки - это всё плод программ, вроде, login, а ядру, вообще, пофиг.
То есть, есть право root у процесса -> переключайся на какой хочешь UID, даже на тот, который не соответствует какому-либо, описанному в системе пользователю.
Также в этом варианте получается, что login должен сделать fork(), чтобы первая его копия не потеряла право root, иначе, набрав exit перелогиниться не получится.
 fork() ->
 -> setuid() -> exec (bash); //для потомка
 -> wait(); //для предка - будет ждать пока дочерний процесс завершится.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #6 : 24-11-2014 17:41 » 

В *nix системах root это царь король и бог Улыбаюсь. Даже rm -rf / (команда убивает полностью систему) выполняется без ругательств Улыбаюсь
Собственно все логично. root ограничивает свои права, становясь другим пользователем. Поэтому никаких паролей не нужно. Он так и так имеет полный доступ в системе. 
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 24-11-2014 17:41 » 

Странно, если я правильно понимаю, то все пароли, логины, проверки - это всё плод программ, вроде, login, а ядру, вообще, пофиг.

Если бы внимательно читал, что тебе пишут, то потребовалось бы меньше времени.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #8 : 25-11-2014 11:37 » 

То есть, есть право root у процесса -> переключайся на какой хочешь UID, даже на тот, который не соответствует какому-либо, описанному в системе пользователю.
Также в этом варианте получается, что login должен сделать fork(), чтобы первая его копия не потеряла право root, иначе, набрав exit перелогиниться не получится.
 fork() ->
 -> setuid() -> exec (bash); //для потомка
 -> wait(); //для предка - будет ждать пока дочерний процесс завершится.
Зачем /bin/login-у делать fork() и сохранять какие-то права? Его (/bin/login-а) в следующий раз, через exec() опять запустит getty, которого в свою очередь запустит init, у которого права root-а никто не отбирал. И wait() будет выполнять init, который и так этим занимается.
Записан
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 25-11-2014 15:51 » 

Судя по тому, что я прочитал, хотя, может и не до конца понял:
exec() - системный вызов, который заменяет текущий процесс другим, указанным процессом.
Например, у меня работает программа aaa, в ней:
exec(bbb), после этого ааа уже нету, она заменена на bbb и aaa стёрта из памяти, хотя PID останется тот же.
fork() - системный вызов, который создаёт новый процесс, который является копией текущего. У старого процесса(предка) остаётся старый PID, у нового новый PID.
Для того, чтобы начать другой новый процесс из текущего нужно сделать:
//да простят мне синтаксис, но для сути дела
//aaa
PID_old = getpid();
fork();
PID_new = getpid();
if (PID_old != PID_new) exec(bbb);
//далее либо возврат в программу, либо wait() и возврат в программу...

Вставляя setuid() между fork() и exec() новый процесс уже будет с усечёнными правами - правами пользователя, но setuid работает только, если текущее право процесса root. Я пока плохо разобрался login, getty или init создаёт разветвление, но за авторизацией следит login, значит, делаю вывод, что усечение прав идёт на нём. Конечно, если будет идти без ветвления в глубине, всё равно fork() на уровне init, далее exec(getty)->exec(login)->setuid()->exec(bash), а при выходе из оболочки всю цепь перезапустит именно инициализирующий процесс, то всё будет работать тоже.
Записан
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #10 : 26-11-2014 08:36 » 

Судя по тому, что я прочитал, хотя, может и не до конца понял:
exec() - системный вызов, который заменяет текущий процесс другим, указанным процессом.
Например, у меня работает программа aaa, в ней:
exec(bbb), после этого ааа уже нету, она заменена на bbb и aaa стёрта из памяти, хотя PID останется тот же.
fork() - системный вызов, который создаёт новый процесс, который является копией текущего. У старого процесса(предка) остаётся старый PID, у нового новый PID.
Да, всё правильно.

Для того, чтобы начать другой новый процесс из текущего нужно сделать:
//да простят мне синтаксис, но для сути дела
//aaa
PID_old = getpid();
fork();
PID_new = getpid();
if (PID_old != PID_new) exec(bbb);
//далее либо возврат в программу, либо wait() и возврат в программу...
По смыслу - да, но не совсем.
Код:
switch (pid = fork())
{ case 0 : /*дочерний процесс*/
    exec(bbb);
    break;
  case -1 : /*ошибка*/
    perror("fork");
    break;
  default : /*родительский процесс*/
    wait(pid);
    break;
}

Вставляя setuid() между fork() и exec() новый процесс уже будет с усечёнными правами - правами пользователя, но setuid работает только, если текущее право процесса root. Я пока плохо разобрался login, getty или init создаёт разветвление, но за авторизацией следит login, значит, делаю вывод, что усечение прав идёт на нём. Конечно, если будет идти без ветвления в глубине, всё равно fork() на уровне init, далее exec(getty)->exec(login)->setuid()->exec(bash), а при выходе из оболочки всю цепь перезапустит именно инициализирующий процесс, то всё будет работать тоже.
имхо, именно так, как последнее Вы написали оно и работает.
Записан
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 26-11-2014 17:56 » new

Спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines