Bug 49683

Summary: Значение PATH в hasher-окружении ведёт к неожиданностям на merged-usr
Product: Sisyphus Reporter: Arseny Maslennikov <arseny>
Component: cross-componentAssignee: Dmitry V. Levin <ldv>
Status: CLOSED FIXED QA Contact: Dmitry V. Levin <ldv>
Severity: major    
Priority: P5 CC: aen, glebfm, obirvalger, rider, sin, vt
Version: unstable   
Hardware: all   
OS: Linux   
Bug Depends on:    
Bug Blocks: 46738    

Description Arseny Maslennikov 2024-03-13 14:14:29 MSK
При сборке некоторых пакетов в merged-usr-окружении можно наблюдать следующий эффект:

  [builder@localhost ~]$ echo $PATH
  /usr/src/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/games

Это ломает, например, вычисление полных путей к установленным интерпретаторам и другим программам:
  [builder@localhost ~]$ strace --trace=execve env python3
  execve("/bin/env", ["env", "python3"], 0x7fffd7ec4730 /* 21 vars */) = 0
  execve("/usr/src/bin/python3", ["python3"], 0x7ffd74c17480 /* 21 vars */) = -1 ENOENT (No such file or directory)
  execve("/bin/python3", ["python3"], 0x7ffd74c17480 /* 21 vars */) = 0
  Python 3.12.2 (main, Feb 29 2024, 18:26:55) [GCC 13.2.1 20240128 (ALT Sisyphus 13.2.1-alt3)] on linux
  Type "help", "copyright", "credits" or "license" for more information.
  >>> exit()
  +++ exited with 0 +++

Первым нашёлся /bin/python3, а не /usr/bin/python3.

При пересборке пакета samba (вчера я случайно догадался попробовать его собрать в merged-usr окружении. не зря!) это ведёт вот к чему:

  Checking for 'gcc' (C compiler)          : /bin/gcc 
  Checking for program 'git'               : /bin/git 
  Checking for program 'pkg-config'        : /bin/pkg-config 
  Checking for program 'perl'              : /bin/perl 
  Checking for program 'perl'              : /bin/perl 
  Checking for program 'xsltproc'          : /bin/xsltproc 
  Checking for program 'python3'           : /bin/python3 
  Checking for program 'python'            : /bin/python3 
  Checking for program 'python3'           : /bin/python3 
  python-config                            : /bin/python3-config 
  Checking for program 'xsltproc'          : /bin/xsltproc 
  Checking for program 'flex'              : /bin/flex 
  Checking for program 'bison'             : /bin/bison 
  Checking for program 'krb5-config'       : /bin/krb5-config 
  Checking for program 'gpgme-config'      : /bin/gpgme-config 
  Checking for program 'yapp'              : /bin/yapp 
  Checking for program 'awk'               : /bin/awk 
  Checking for program 'cups-config'       : /bin/cups-config 
  Checking for program 'ncurses6-config'   : /bin/ncurses6-config 
  Checking for program 'asn1Parser'        : /bin/asn1Parser

Сборочный код переписывает hashbang у скриптов с #!/usr/bin/env python3 на #!/bin/python3 (!), и подпакеты с ними в итоге не проходят unmet check:

    x86_64: NEW unmet dependencies detected:
   samba-dc-client#4.19.5-alt1:sisyphus+342175.6300.10.1@1710231076  /bin/python3
   samba-gpupdate#4.19.5-alt1:sisyphus+342175.6300.10.1@1710231076   /bin/python3
    i586: NEW unmet dependencies detected:
   samba-dc-client#4.19.5-alt1:sisyphus+342175.6300.10.1@1710231216  /bin/python3
   samba-gpupdate#4.19.5-alt1:sisyphus+342175.6300.10.1@1710231216   /bin/python3
    aarch64: NEW unmet dependencies detected:
   samba-dc-client#4.19.5-alt1:sisyphus+342175.6300.10.1@1710232968  /bin/python3
   samba-gpupdate#4.19.5-alt1:sisyphus+342175.6300.10.1@1710232968   /bin/python3
    ppc64le: NEW unmet dependencies detected:
   samba-dc-client#4.19.5-alt1:sisyphus+342175.6300.10.1@1710232984  /bin/python3
   samba-gpupdate#4.19.5-alt1:sisyphus+342175.6300.10.1@1710232984   /bin/python3

Нас это ждёт, когда в сизифе окажется filesystem >= 3.
Comment 1 Arseny Maslennikov 2024-03-13 14:21:45 MSK
Отсюда вижу два возможных пути:
— принять удар и исправлять все результировавшие FTBFS после;
— попробовать конкретно в hasher выбросить из PATH каталог /bin (и — для rooter — /sbin), что можно сделать кодом в .host/entry или аддоном для /etc/profile.d в специальном пакете для сборочной среды.

Второй путь приведёт к тому, что execvp("awk", *) будет открывать /usr/bin/awk. На сегодняшний день непонятно, помешает ли это чему-нибудь (вдруг всплывёт тот же симптом, но наоборот: будут unmet Requires: /usr/bin/awk?).
Comment 2 Arseny Maslennikov 2024-03-13 14:30:53 MSK
(In reply to Arseny Maslennikov from comment #1)
> — попробовать конкретно в hasher выбросить из PATH каталог /bin (и — для
> rooter — /sbin), что можно сделать кодом в .host/entry или аддоном для
> /etc/profile.d в специальном пакете для сборочной среды.

Если это делать в hasher, то что-то вроде:
  if [ ! -L /bin ]; then
      # Sync this with the default /etc/profile shipped with ALT.
      PATH='/usr/bin:/usr/local/bin'
  fi

/etc/profile к такому готов.
Или, может, не каталог проверять, а "если стоит пакет filesystem и его версия >= 3".
Comment 3 Anton Farygin 2024-03-13 14:32:09 MSK
а почему бы сразу не поправить и /etc/profile ?
Comment 4 Dmitry V. Levin 2024-03-13 14:36:25 MSK
(In reply to Arseny Maslennikov from comment #2)
> Если это делать в hasher, то что-то вроде:
>   if [ ! -L /bin ]; then
>       # Sync this with the default /etc/profile shipped with ALT.
>       PATH='/usr/bin:/usr/local/bin'
>   fi

Если нужно поменять PATH, то почему это изменение должно быть ограничено средой hasher?
Comment 5 Dmitry V. Levin 2024-03-13 14:38:03 MSK
Можно ли поменять /etc/profile синхронно с filesystem?
Comment 6 Arseny Maslennikov 2024-03-13 14:40:04 MSK
(In reply to Dmitry V. Levin from comment #5)
> Можно ли поменять /etc/profile синхронно с filesystem?

Можно, конечно. :)
Comment 7 Gleb F-Malinovskiy 2024-03-13 14:40:47 MSK
(In reply to Dmitry V. Levin from comment #5)
> Можно ли поменять /etc/profile синхронно с filesystem?

Мне кажется, что если мы проверяем на симлинки, то можно поменять до filesystem.
Comment 8 Anton Farygin 2024-03-13 14:43:03 MSK
Тоже хотел предложить поменять /etc/profile прямо сейчас.
Comment 9 Arseny Maslennikov 2024-03-13 14:44:15 MSK
(In reply to Anton Farygin from comment #3)
> а почему бы сразу не поправить и /etc/profile?

Я допускаю, что кому-то или чему-то такой ход может помешать. Но примеров привести не могу и сам надеюсь, что их нет.
Comment 10 Arseny Maslennikov 2024-03-13 14:48:03 MSK
(In reply to Arseny Maslennikov from comment #9)
> (In reply to Anton Farygin from comment #3)
> > а почему бы сразу не поправить и /etc/profile?
> 
> Я допускаю, что кому-то или чему-то такой ход может помешать. Но примеров
> привести не могу и сам надеюсь, что их нет.

Более всего в этом контексте меня беспокоит генератор зависимостей. Обычно PATH используется так, что _неважно_, в каком порядке там два алиасящих друг друга пути, потому что там всего лишь проходит поиск программы, и в этих каталогах, очевидно, они будут одни и те же.

Но вот ситуация в comment 0 показывает, что чему-то не всё равно, и у нас вылезают unmets.

Подозреваю, что самый надёжный способ исключить этот класс проблем — это вообще не с PATH возиться, а все зависимости на исполнимые программы привести к виду executable(/bin/awk) вместо как /bin/awk, так и /usr/bin/awk.
Comment 11 Arseny Maslennikov 2024-03-13 14:51:23 MSK
(In reply to Arseny Maslennikov from comment #10)
> Подозреваю, что самый надёжный способ исключить этот класс проблем — это
> вообще не с PATH возиться, а все зависимости на исполнимые программы
> привести к виду executable(/bin/awk) вместо как /bin/awk, так и /usr/bin/awk.

Или реально пройтись по всем пакетам, которые Provides: /bin/что-то, и повесить провайд на /usr/bin/что-то. Зависимости не исчезают, а появляются, поэтому можно в разных транзакциях.
Comment 12 Arseny Maslennikov 2024-04-04 18:59:34 MSK
(In reply to Arseny Maslennikov from comment #9)
> (In reply to Anton Farygin from comment #3)
> > а почему бы сразу не поправить и /etc/profile?
> 
> Я допускаю, что кому-то или чему-то такой ход может помешать. Но примеров
> привести не могу и сам надеюсь, что их нет.

По итогам тестовых пересборок получается, что, если в hasher-окружении просто поменять записи в PATH в /etc/profile местами, это сломает гораздо меньше пакетов, чем если этого не делать. Сходу я увидел только, что зависимости на /lib/lsb/init-functions заменяются на /usr/lib/lsb/init-functions, но это начнёт мешать только при попытке пересобрать или обновить пакет => можно решать проблемы по мере их возникновения.

Впрочем, мониторить зависимостей при помощи тестовых пересборок очень трудно, потому что в конце лога успешной пересборки выводится дифф с пакетом в репозитории, а не с чем-то ещё. Полезнее было бы сравнивать с результатом пересборки в сизифе. Когда есть два диффа A->B и A->C, то при наличии объекта A можно получить дифф B->C (интересующий), но этого A нет или я не знаю, где он. Наверное, надо в будущем как-то упростить эту задачу.
Comment 13 Arseny Maslennikov 2024-04-04 18:59:56 MSK
Нижеследующий факт гораздо интереснее.
Значение PATH из /etc/profile не имеет эффекта в hasher-окружении, потому что в /etc/profile написано вот так:

  [ -n "$PATH" ] || PATH="/usr/bin:/bin:/usr/local/bin"

Если PATH уже назначена во что-то, это значение будет сохранено.
До этого этапа hasher-priv ставит значение PATH, разное для rooter и builder:
https://git.altlinux.org/gears/h/hasher-priv.git?p=hasher-priv.git;a=blob;f=hasher-priv/chrootuid.c;h=45053d743d9f798bfdf5f337bd895b6c9ea9d029;hb=9f3e5ecebc2a218953cff58c71f3bc07534c58bd#l270-285

Выглядит это так:
  % hsh-run -- /bin/sh -c 'echo $PATH'
  /bin:/usr/bin:/usr/X11R6/bin
  % hsh-shell <<<'echo $PATH'
  echo $PATH
  [builder@localhost .in]$ echo $PATH
  /usr/src/bin:/usr/bin:/bin:/usr/games
  [builder@localhost .in]$ 
  logout
В первом случае остаётся значение от hasher-priv (/etc/profile даже не задействуется), во втором случае используется /etc/profile, в начале которого явно задано "PATH=/usr/bin:/bin". Более того, скорее всего, для процессов от rooter используется значение из пакета rootfiles, файл вообще не profile, а bashrc:
https://git.altlinux.org/gears/r/rootfiles.git?p=rootfiles.git;a=blob;f=rootfiles/.bashrc;h=385d4978963bc1830c63123e80c1ebe8f5d11c42;hb=3e1b5ad151b6c53e1ad563659eb7df6a1428ba7d
и перебивает всю аккуратную логику, описанную выше.

Если задуматься, то это глубоко неправильно хотя бы потому, что один и тот же hasher-priv используется для сборки в окружении разных наших репозиториев.
Comment 14 Arseny Maslennikov 2024-04-04 19:04:08 MSK
(In reply to Arseny Maslennikov from comment #13)
> Более того, скорее всего, для
> процессов от rooter используется значение из пакета rootfiles, файл вообще
> не profile, а bashrc:
> https://git.altlinux.org/gears/r/rootfiles.git?p=rootfiles.git;a=blob;
> f=rootfiles/.bashrc;h=385d4978963bc1830c63123e80c1ebe8f5d11c42;
> hb=3e1b5ad151b6c53e1ad563659eb7df6a1428ba7d
> и перебивает всю аккуратную логику, описанную выше.

Это если hsh-shell --rooter запустить. В окружении под hsh-run /etc/profile всегда игнорируется, PATH всегда получается от hasher-priv.
Comment 15 Arseny Maslennikov 2024-04-04 19:26:56 MSK
(In reply to Arseny Maslennikov from comment #13)
> Нижеследующий факт гораздо интереснее.
> Значение PATH из /etc/profile не имеет эффекта в hasher-окружении, потому
> что в /etc/profile написано вот так:
> 
>   [ -n "$PATH" ] || PATH="/usr/bin:/bin:/usr/local/bin"

Видимо, эту проверку на [ -n ] надо будет убрать, если она больше ни для чего не нужна.