FS#44827 - [devtools] makechrootpkg looses environment variables when switching to root

Attached to Project: Arch Linux
Opened by Christian Kampka (chris-) - Sunday, 03 May 2015, 16:46 GMT
Last edited by Doug Newgard (Scimmia) - Wednesday, 22 March 2017, 03:23 GMT
Task Type Bug Report
Category Packages: Extra
Status Closed
Assigned To Pierre Schmitz (Pierre)
Dave Reisner (falconindy)
Architecture All
Severity Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 2
Private No

Details

Executing the makechrootpkg script as a normal user will result in the script being reexecuted as root.
This root switch, however, silently sanitizes the environment, so passing variables to the script like for example PKGDEST for defining the final location of the built package will have no effect as they will no longer be set in the root environment.
This is a very unexpected behavior as this is done without warning or notifying the user.
In my opinion, the check_root function should take care to carry over all environment variables that are relevant to the script and are present in the current users environment.
This task depends upon

Closed by  Doug Newgard (Scimmia)
Wednesday, 22 March 2017, 03:23 GMT
Reason for closing:  Fixed
Additional comments about closing:  https://git.archlinux.org/devtools.git/c ommit/?id=06c98c1b54f0aea812caca3708b320 a2dd566108
Comment by Evangelos Foutras (foutrelis) - Sunday, 03 May 2015, 17:06 GMT
You can't reliably pass such parameters in environment variables as they will be overridden if /etc/makepkg.conf defines them as well.

Instead, you can put per-user configuration in "$HOME/.makepkg.conf" which is sourced after /etc/makepkg.conf.
Comment by Doug Newgard (Scimmia) - Sunday, 03 May 2015, 17:11 GMT
The point of using makechrootpkg is to build in a clean environment. Pulling over all kinds of environmental variables doesn't jive with that goal. I don't see why this would be "very unexpected behavior".
Comment by Christian Kampka (chris-) - Sunday, 03 May 2015, 20:22 GMT
@Evangelios
I cannot agree with that, because that is not how makechrootpkg works.
The makepkg.conf is not blindly sources, it is included selectively if needed, see the load_vars function at https://projects.archlinux.org/devtools.git/tree/makechrootpkg.in#n70
As you can see, passing specific variables via the environment will not get overridden.

@Doug
This bug is not about passing argument into the chroot, the bug is that when switching to the root USER, which is done if you do not run the script as root or using sudo.
The variables that I am talking about take effect outside the chroot, PKGDEST for example specifies where the package is placed after the build and has nothing to do with the chroot.
So yes, I believe this is unexpected especially since it works very different if you run the script as root from the beginning.
Comment by Dave Reisner (falconindy) - Sunday, 03 May 2015, 20:44 GMT
> it works very different if you run the script as root from the beginning.
This just means that your sudoers configuration is filtering out the variables, not makechrootpkg. What you're asking for can (and should) be pulled from makepkg.conf, not artbitrarily passed in from the parent process environment.
Comment by Christian Kampka (chris-) - Saturday, 09 May 2015, 15:13 GMT
@Dave
Relying the make.pkg only is a very inflexible solution.
It would basically dictate that you can only have one PKGDEST dest defined at a time which means you need a one size fits all configuration for all your package building needs.
I typically use a script to assemble all packages for an internal repository which requires and has very different specifications that builds I do manually for testing or local needs.
Having the ability to pass in configuration over the environment on the other hands makes integration into scriptable workflows very convenient.
Comment by Dave Reisner (falconindy) - Saturday, 09 May 2015, 15:16 GMT
Nothing prevents you from keeping multiple chroots, each with their own configuration. Arch developers do exactly this, as we need different configurations for builds involving different repos (think rebuilds with testing/staging repos enabled).

edit: and again, sudoers. You claim that environment is preserved when run as root but not via sudo, so I blame sudo for stripping your environment (as it's designed to do).
Comment by Christian Kampka (chris-) - Saturday, 09 May 2015, 15:32 GMT
Again, I am not talking about configuration inside the chroot or passing configuration inside the chroot through the environment. I do not see how keeping multiple chroots would help here.
Yes, sudo strips the environment, and that is indeed what it is intended to do and I have no intention of changing this behavior in general.
That is why I am making the case that the script should call itself in such a way that lets it preserve configuration that is relevant to its own execution.
I do not see why this should be any less appropriate than using eval on a makepkg.conf.
Comment by Doug Newgard (Scimmia) - Saturday, 09 May 2015, 15:48 GMT
I think you're missing the point that a "clean chroot" should be clean. This does not mean pulling in random crap from the host environment.
Comment by Christian Kampka (chris-) - Saturday, 09 May 2015, 15:54 GMT
Okay, I think third time's the charm so here it goes:

I am not talking about the chroot!

This issue is only about how the check_root function in https://projects.archlinux.org/devtools.git/tree/lib/common.sh#n236 works. Nothing more.
This has in no way any implications on the environment in the chroot.
Hope this is clear now.
Comment by Dave Reisner (falconindy) - Saturday, 09 May 2015, 16:01 GMT
And I'm still talking about using your sudoers configuration to make this happen. Something like the following should work:

Defaults:%wheel env_keep=PKGDEST
%wheel ALL = (ALL) /usr/bin/makechrootpkg
Comment by Christian Kampka (chris-) - Saturday, 09 May 2015, 16:15 GMT
Dave, that would obviously work, the same way that running the makechrootpkg as with sudo in the first place or becoming root beforehand would solve it.
The main point of this issue is that the current implementation requires implicit knowledge of the source code of the script to figure out this is even required.
Otherwise, the script behaves in a way, at least to me, appears unexpected.
So if handling this use case by preserving the configuration is out of the question for you, I believe this is at least worthy of being documented somewhere it can be easily found.
Comment by John (graysky) - Wednesday, 24 August 2016, 19:49 GMT
I might be missing something but if I edit /chroot/root/etc/makepkg.conf and enable distcc, then run makechrootpkg, distccd is in fact enabled and runs as such from within the clean chroot. If I do the same thing with MAKEFLAGS in /chroot/root/etc/makepkg.conf the value for MAKEFLAGS is read in from my live system's /etc/makepkg.conf rather than from the value I defined within /chroot/root/etc/makepkg.conf as the OP reported. Why is setting unaffected?

EDIT: Is it because line 75 doesn't define it?[1]

1. https://git.archlinux.org/devtools.git/tree/makechrootpkg.in#n75
Comment by NicoHood (NicoHood) - Saturday, 07 January 2017, 11:50 GMT
I am not sure if the original issue is still valid. But I have a related issue:

I set PKGDEST in my ~/.makepkg.conf. Now if I use the devtools build script it does use this path as output. Looking at the script, you can see that it builds the stuff inside a special /pkgdest and then copies the stuff to the user defined destination.

The problem that now occurs is that the actual makepkg comment is run with the /pkgdest as destination. The resulting package link will also be to this destination. This one is just copied to the local path with the PKGBUILD again, but this is actually wrong:
arduino-1:1.8.0-3-x86_64.pkg.tar.xz -> /pkgdest/arduino-1:1.8.0-3-x86_64.pkg.tar.xz

It should rather point to my user defined path and not /pkgdest. I think the simplest solution would be to create a new link if a different pkgdest is used. Any other suggestions?


Edit:
The issue seems to be in line 329 of makechrootpkg:
if arch-nspawn "$copydir" \
--bind="$PWD:/startdir" \
--bind="$SRCDEST:/srcdest" \
"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
/chrootbuild

You can see that /startdir is bind to the current directory. Thatswhy also the synlink is placed inside the working directory.
I have not tested it, but theoretical this issue seems to be invalid because of this nowadays:
https://bugs.archlinux.org/task/42726?project=1&cat%5B0%5D=2&string=devtools

So the symlink lands inside the working directory, but is generated wrong because the script changes the PKGDEST and then manually copies the data. So the solution would be to look if PKGDEST != PWD and if so regenerate the symlink properly in the move_products() function.

Edit2:
Patch submitted:
https://lists.archlinux.org/pipermail/arch-projects/2017-January/004450.html

Loading...