Bug 55130 - Не запускается пользовательская systemd служба
Summary: Не запускается пользовательская systemd служба
Status: NEW
Alias: None
Product: Sisyphus
Classification: Development
Component: kiosk (show other bugs)
Version: unstable
Hardware: x86_64 Linux
: P5 normal
Assignee: Олег Соловьев
QA Contact: qa-sisyphus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-07-09 21:43 MSK by Alexey Volkov
Modified: 2025-07-22 15:26 MSK (History)
5 users (show)

See Also:


Attachments
Лог службы user@1000.service (4.69 KB, text/x-log)
2025-07-09 21:43 MSK, Alexey Volkov
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexey Volkov 2025-07-09 21:43:41 MSK
Created attachment 19020 [details]
Лог службы user@1000.service

С активированным режимом Kiosk при логине не стартует служба user@.service (в моем случае user@1000.service).

Происходит это из-за того, что /usr/lib/systemd/systemd --user не может взять переменные окружения XDG_RUNTIME_DIR и DBUS_SESSION_BUS_ADDRESS, что приводит к завершению systemd --user. Она падает с ошибкой, что не может определить путь до RuntimeDirectory. Посмотрев код systemd, увидел, что там используется функция secure_getenv(), которая сравнивает UID с EUID и GID с EGID и только при их равенстве вызывает getenv(), который уже получает нужные переменные окружения (XDG_RUNTIME_DIR и DBUS_SESSION_BUS_ADDRESS).

Я в качестве эксперимента менял secure_getenv() на просто getenv() и служба успешно запускалась с работающим Киоском.

Проверялось на ALT Workstation 11.0 с профилем user-gnome-startup из пакета kiosk-gnome-profiles: https://packages.altlinux.org/en/sisyphus/srpms/kiosk-gnome-profiles/
Если выключить режим Kiosk, вручную запустить службу, обратно включить Kiosk, и потом залогиниться в GDM, то GNOME с этим профилем запустится без проблем.

Ошибка воспроизводится на ALT Workstation K, но так как KDE не так зависит от D-Bus как GNOME, KDE после логина запускается без ошибок, но служба все равно не запускается.
Comment 1 Олег Соловьев 2025-07-22 15:26:19 MSK
(In reply to Alexey Volkov from comment #0)
> Посмотрев код systemd, увидел, что там
> используется функция secure_getenv(), которая сравнивает UID с EUID и GID с
> EGID и только при их равенстве вызывает getenv(), который уже получает
> нужные переменные окружения (XDG_RUNTIME_DIR и DBUS_SESSION_BUS_ADDRESS).

А вот что я нашёл:

В glibc/sysdeps/unix/sysv/linux/dl-parse_auxv.h [1]:
/* Copy the auxiliary vector into AUXV_VALUES and set up GLRO
   variables.  */
static inline
void _dl_parse_auxv (ElfW(auxv_t) *av, dl_parse_auxv_t auxv_values)
{
  ...
  unsigned security_mask = 0;
  ...
  security_mask |= auxv_values[AT_SECURE] != 0;
  security_mask |= ((uid != 0) << 1) | ((gid != 0) << 2);
  __libc_security_mask = security_mask;
  __libc_enable_secure = __libc_security_mask != 0;
  ...
}

В glibc/stdlib/secure-getenv.c [2]:
/* Some programs and especially the libc itself have to be careful
   what values to accept from the environment.  This special version
   checks for SUID or SGID first before doing any work.  */
char *
__libc_secure_getenv (const char *name)
{
  return __libc_enable_secure ? NULL : getenv (name);
}
weak_alias (__libc_secure_getenv, secure_getenv)
libc_hidden_weak (__libc_secure_getenv)

В https://man7.org/linux/man-pages/man3/secure_getenv.3.html:
> The GNU-specific secure_getenv() function is just like getenv()
>   except that it returns NULL in cases where "secure execution" is
>   required.
> ...
> Secure execution may also be required if triggered by some Linux security modules.

А kiosk - LSM и включает secure execution для всех процессов, запущенных пользователем с uid >= 1000.
В kernel-image-6.12/security/kiosk/kiosk_lsm.c [3]:
static int kiosk_bprm_check_security(struct linux_binprm *bprm)
{
         uid_t cur_uid = __kuid_val(bprm->cred->uid);
         struct kiosk_list_struct *node;
 
         if (kiosk_mode == KIOSK_PERMISSIVE)
                 return 0;
 
         if (cur_uid >= 1000) {
                 bprm->secureexec = 1;
         ...
}

[1] https://git.altlinux.org/gears/g/glibc.git?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/dl-parse_auxv.h;h=fb4124050f827dcd8c9567388886dc266212e12e;hb=8c5965291fac4d9814d13c492d45574fccf331c7#l27
[2] https://git.altlinux.org/gears/g/glibc.git?p=glibc.git;a=blob;f=stdlib/secure-getenv.c;h=88bff1b47abdb5a69614d6d7fc62d7f49ba3a83b;hb=8c5965291fac4d9814d13c492d45574fccf331c7#l24
[3] https://git.altlinux.org/gears/k/kernel-image-6.12.git?p=kernel-image-6.12.git;a=blob;f=security/kiosk/kiosk_lsm.c;h=18f810a1ce0f17631b5a18e40a92bad3f9ab8447;hb=5c8a6837cbfaf345ebf52635e02135793aaed3b8#l286

Таким образом, secure_getenv() в недрах systemd возвращает NULL из-за установленного в LSM-модуле флага AT_SECURE.
Если бы флага не было и нет другой необходимости в secureexec, то вызывается уже getenv()