2022-01-02 21:38:21 +00:00
|
|
|
# Copyright 2022 Oliver Smith
|
2020-02-20 20:07:28 +00:00
|
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
2017-05-26 20:35:21 +00:00
|
|
|
import os
|
|
|
|
import logging
|
|
|
|
|
|
|
|
import pmb.build
|
|
|
|
import pmb.build.autodetect
|
|
|
|
import pmb.build.checksum
|
|
|
|
import pmb.chroot
|
|
|
|
import pmb.chroot.apk
|
2018-06-09 06:52:24 +00:00
|
|
|
import pmb.chroot.other
|
2018-11-15 07:30:49 +00:00
|
|
|
import pmb.helpers.pmaports
|
2017-05-26 20:35:21 +00:00
|
|
|
import pmb.helpers.run
|
|
|
|
import pmb.parse
|
|
|
|
|
|
|
|
|
2021-10-16 16:15:54 +00:00
|
|
|
def get_arch(apkbuild):
|
2017-10-24 16:18:42 +00:00
|
|
|
"""
|
2020-10-11 12:47:42 +00:00
|
|
|
Take the architecture from the APKBUILD or complain if it's ambiguous. This
|
|
|
|
function only gets called if --arch is not set.
|
2017-10-24 16:18:42 +00:00
|
|
|
|
2018-02-25 17:44:01 +00:00
|
|
|
:param apkbuild: looks like: {"pkgname": "linux-...",
|
|
|
|
"arch": ["x86_64", "armhf", "aarch64"]}
|
2017-10-24 16:18:42 +00:00
|
|
|
or: {"pkgname": "linux-...", "arch": ["armhf"]}
|
|
|
|
"""
|
|
|
|
pkgname = apkbuild["pkgname"]
|
|
|
|
|
2020-10-11 12:37:41 +00:00
|
|
|
# Disabled package (arch="")
|
|
|
|
if not apkbuild["arch"]:
|
|
|
|
raise RuntimeError(f"'{pkgname}' is disabled (arch=\"\"). Please use"
|
|
|
|
" '--arch' to specify the desired architecture.")
|
|
|
|
|
2020-10-11 12:47:42 +00:00
|
|
|
# Multiple architectures
|
2018-02-25 17:44:01 +00:00
|
|
|
if len(apkbuild["arch"]) > 1:
|
2020-10-11 12:47:42 +00:00
|
|
|
raise RuntimeError(f"'{pkgname}' supports multiple architectures"
|
|
|
|
f" ({', '.join(apkbuild['arch'])}). Please use"
|
|
|
|
" '--arch' to specify the desired architecture.")
|
2017-10-24 16:18:42 +00:00
|
|
|
|
2020-10-11 12:44:52 +00:00
|
|
|
return apkbuild["arch"][0]
|
2017-10-24 16:18:42 +00:00
|
|
|
|
|
|
|
|
2020-03-21 08:36:01 +00:00
|
|
|
def get_outputdir(args, pkgname, apkbuild):
|
2018-06-18 22:21:18 +00:00
|
|
|
"""
|
|
|
|
Get the folder for the kernel compilation output.
|
|
|
|
For most APKBUILDs, this is $builddir. But some older ones still use
|
|
|
|
$srcdir/build (see the discussion in #1551).
|
|
|
|
"""
|
|
|
|
# Old style ($srcdir/build)
|
|
|
|
ret = "/home/pmos/build/src/build"
|
|
|
|
chroot = args.work + "/chroot_native"
|
|
|
|
if os.path.exists(chroot + ret + "/.config"):
|
|
|
|
logging.warning("*****")
|
|
|
|
logging.warning("NOTE: The code in this linux APKBUILD is pretty old."
|
|
|
|
" Consider making a backup and migrating to a modern"
|
|
|
|
" version with: pmbootstrap aportgen " + pkgname)
|
|
|
|
logging.warning("*****")
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
# New style ($builddir)
|
|
|
|
cmd = "srcdir=/home/pmos/build/src source APKBUILD; echo $builddir"
|
|
|
|
ret = pmb.chroot.user(args, ["sh", "-c", cmd],
|
|
|
|
"native", "/home/pmos/build",
|
2018-07-14 01:13:28 +00:00
|
|
|
output_return=True).rstrip()
|
2018-06-18 22:21:18 +00:00
|
|
|
if os.path.exists(chroot + ret + "/.config"):
|
|
|
|
return ret
|
2019-05-26 13:12:37 +00:00
|
|
|
# Some Mediatek kernels use a 'kernel' subdirectory
|
|
|
|
if os.path.exists(chroot + ret + "/kernel/.config"):
|
|
|
|
return os.path.join(ret, "kernel")
|
2018-06-18 22:21:18 +00:00
|
|
|
|
2020-03-21 08:36:01 +00:00
|
|
|
# Out-of-tree builds ($_outdir)
|
|
|
|
if os.path.exists(chroot + ret + "/" + apkbuild["_outdir"] + "/.config"):
|
|
|
|
return os.path.join(ret, apkbuild["_outdir"])
|
|
|
|
|
2018-06-18 22:21:18 +00:00
|
|
|
# Not found
|
|
|
|
raise RuntimeError("Could not find the kernel config. Consider making a"
|
|
|
|
" backup of your APKBUILD and recreating it from the"
|
|
|
|
" template with: pmbootstrap aportgen " + pkgname)
|
|
|
|
|
|
|
|
|
2021-09-11 08:57:47 +00:00
|
|
|
def menuconfig(args, pkgname, use_oldconfig):
|
2017-08-03 16:11:23 +00:00
|
|
|
# Pkgname: allow omitting "linux-" prefix
|
2021-11-14 18:32:09 +00:00
|
|
|
if not pkgname.startswith("linux-"):
|
2017-07-30 18:41:49 +00:00
|
|
|
pkgname = "linux-" + pkgname
|
|
|
|
|
2017-05-26 20:35:21 +00:00
|
|
|
# Read apkbuild
|
2018-11-15 07:30:49 +00:00
|
|
|
aport = pmb.helpers.pmaports.find(args, pkgname)
|
2021-11-09 11:52:10 +00:00
|
|
|
apkbuild = pmb.parse.apkbuild(f"{aport}/APKBUILD")
|
2021-10-16 16:15:54 +00:00
|
|
|
arch = args.arch or get_arch(apkbuild)
|
2021-10-16 16:33:27 +00:00
|
|
|
suffix = pmb.build.autodetect.suffix(apkbuild, arch)
|
2021-02-08 17:01:36 +00:00
|
|
|
cross = pmb.build.autodetect.crosscompile(args, apkbuild, arch, suffix)
|
|
|
|
hostspec = pmb.parse.arch.alpine_to_hostspec(arch)
|
2017-05-26 20:35:21 +00:00
|
|
|
|
|
|
|
# Set up build tools and makedepends
|
2021-02-08 17:01:36 +00:00
|
|
|
pmb.build.init(args, suffix)
|
2021-03-30 13:46:32 +00:00
|
|
|
if cross:
|
|
|
|
pmb.build.init_compiler(args, [], cross, arch)
|
2021-09-11 08:57:47 +00:00
|
|
|
|
2018-06-09 06:52:24 +00:00
|
|
|
depends = apkbuild["makedepends"]
|
|
|
|
copy_xauth = False
|
2021-09-11 08:57:47 +00:00
|
|
|
|
|
|
|
if use_oldconfig:
|
|
|
|
kopt = "oldconfig"
|
2018-06-09 06:52:24 +00:00
|
|
|
else:
|
2021-09-11 08:57:47 +00:00
|
|
|
kopt = "menuconfig"
|
|
|
|
if args.xconfig:
|
|
|
|
depends += ["qt5-qtbase-dev", "font-noto"]
|
|
|
|
kopt = "xconfig"
|
|
|
|
copy_xauth = True
|
|
|
|
elif args.nconfig:
|
|
|
|
kopt = "nconfig"
|
|
|
|
depends += ["ncurses-dev"]
|
|
|
|
else:
|
|
|
|
depends += ["ncurses-dev"]
|
|
|
|
|
2017-10-21 14:34:43 +00:00
|
|
|
pmb.chroot.apk.install(args, depends)
|
2017-05-26 20:35:21 +00:00
|
|
|
|
2018-06-09 06:52:24 +00:00
|
|
|
# Copy host's .xauthority into native
|
|
|
|
if copy_xauth:
|
|
|
|
pmb.chroot.other.copy_xauthority(args)
|
|
|
|
|
2017-05-26 20:35:21 +00:00
|
|
|
# Patch and extract sources
|
|
|
|
pmb.build.copy_to_buildpath(args, pkgname)
|
|
|
|
logging.info("(native) extract kernel source")
|
2017-10-12 20:08:10 +00:00
|
|
|
pmb.chroot.user(args, ["abuild", "unpack"], "native", "/home/pmos/build")
|
2017-05-26 20:35:21 +00:00
|
|
|
logging.info("(native) apply patches")
|
Properly escape commands in pmb.chroot.user() (#1316)
## Introduction
In #1302 we noticed that `pmb.chroot.user()` does not escape commands
properly: When passing one string with spaces, it would pass them as
two strings to the chroot. The use case is passing a description with
a space inside to `newapkbuild` with `pmboostrap newapkbuild`.
This is not a security issue, as we don't pass strings from untrusted
input to this function.
## Functions for running commands in pmbootstrap
To put the rest of the description in context: We have four high level
functions that run commands:
* `pmb.helpers.run.user()`
* `pmb.helpers.run.root()`
* `pmb.chroot.root()`
* `pmb.chroot.user()`
In addition, one low level function that the others invoke:
* `pmb.helpers.run.core()`
## Flawed test case
The issue described above did not get detected for so long, because we
have a test case in place since day one, which verifies that all of the
functions above escape everything properly:
* `test/test_shell_escape.py`
So the test case ran a given command through all these functions, and
compared the result each time. However, `pmb.chroot.root()`
modified the command variable (passed by reference) and did the
escaping already, which means `pmb.chroot.user()` running directly
afterwards only returns the right output when *not* doing any escaping.
Without questioning the accuracy of the test case, I've escaped
commands and environment variables with `shlex.quote()` *before*
passing them to `pmb.chroot.user()`. In retrospective this does not
make sense at all and is reverted with this commit.
## Environment variables
By coincidence, we have only passed custom environment variables to
`pmb.chroot.user()`, never to the other high level functions. This only
worked, because we did not do any escaping and the passed line gets
executed as shell command:
```
$ MYENV=test echo test2
test 2
```
If it was properly escaped as one shell command:
```
$ 'MYENV=test echo test2'
sh: MYENV=test echo test2: not found
```
So doing that clearly doesn't work anymore. I have added a new `env`
parameter to `pmb.chroot.user()` (and to all other high level functions
for consistency), where environment variables can be passed as a
dictionary. Then the function knows what to do and we end up with
properly escaped commands and environment variables.
## Details
* Add new `env` parameter to all high level command execution functions
* New `pmb.helpers.run.flat_cmd()` function, that takes a command as
list and environment variables as dict, and creates a properly escaped
flat string from the input.
* Use that function for proper escaping in all high level exec funcs
* Don't escape commands *before* passing them to `pmb.chroot.user()`
* Describe parameters of the command execution functions
* `pmbootstrap -v` writes the exact command to the log that was
executed (in addition to the simplified form we always write down for
readability)
* `test_shell_escape.py`: verify that the command passed by reference
has not been modified, add a new test for strings with spaces, add
tests for new function `pmb.helpers.run.flat_cmd()`
* Remove obsolete commend in `pmb.chroot.distccd` about environment
variables, because we don't use any there anymore
* Add `TERM=xterm` to default environment variables in the chroot,
so running ncurses applications like `menuconfig` and `nano` works out of
the box
2018-03-10 22:58:39 +00:00
|
|
|
pmb.chroot.user(args, ["abuild", "prepare"], "native",
|
2018-07-14 01:13:28 +00:00
|
|
|
"/home/pmos/build", output="interactive",
|
|
|
|
env={"CARCH": arch})
|
2017-05-26 20:35:21 +00:00
|
|
|
|
2018-06-09 06:52:24 +00:00
|
|
|
# Run make menuconfig
|
2020-03-21 08:36:01 +00:00
|
|
|
outputdir = get_outputdir(args, pkgname, apkbuild)
|
2018-06-09 06:52:24 +00:00
|
|
|
logging.info("(native) make " + kopt)
|
2021-03-30 13:46:32 +00:00
|
|
|
env = {"ARCH": pmb.parse.arch.alpine_to_kernel(arch),
|
|
|
|
"DISPLAY": os.environ.get("DISPLAY"),
|
|
|
|
"XAUTHORITY": "/home/pmos/.Xauthority"}
|
|
|
|
if cross:
|
|
|
|
env["CROSS_COMPILE"] = f"{hostspec}-"
|
|
|
|
env["CC"] = f"{hostspec}-gcc"
|
2018-06-09 06:52:24 +00:00
|
|
|
pmb.chroot.user(args, ["make", kopt], "native",
|
2021-03-30 13:46:32 +00:00
|
|
|
outputdir, output="tui", env=env)
|
2018-06-09 06:52:24 +00:00
|
|
|
|
|
|
|
# Find the updated config
|
2018-06-18 22:21:18 +00:00
|
|
|
source = args.work + "/chroot_native" + outputdir + "/.config"
|
2017-05-26 20:35:21 +00:00
|
|
|
if not os.path.exists(source):
|
2017-12-17 19:17:53 +00:00
|
|
|
raise RuntimeError("No kernel config generated: " + source)
|
2018-06-09 06:52:24 +00:00
|
|
|
|
|
|
|
# Update the aport (config and checksum)
|
|
|
|
logging.info("Copy kernel config back to aport-folder")
|
|
|
|
config = "config-" + apkbuild["_flavor"] + "." + arch
|
2017-09-18 18:38:52 +00:00
|
|
|
target = aport + "/" + config
|
2017-05-26 20:35:21 +00:00
|
|
|
pmb.helpers.run.user(args, ["cp", source, target])
|
build/menuconfig: fix kconfig_edit (!1791)
This fixes regression from commits 0431a519 and 4daf9916.
pmbootstrap kconfig_edit raised an error while trying to checksum a package.
Error was:
(028793) [16:13:22] ERROR: 'module' object is not callable
(028793) [16:13:22] See also: <https://postmarketos.org/troubleshooting>
(028793) [16:13:22] Traceback (most recent call last):
File "/home/lexx/dev/pmos/pmbootstrap/pmb/__init__.py", line 63, in main
getattr(frontend, args.action)(args)
File "/home/lexx/dev/pmos/pmbootstrap/pmb/helpers/frontend.py", line 279, in kconfig
pmb.build.menuconfig(args, args.package)
File "/home/lexx/dev/pmos/pmbootstrap/pmb/build/menuconfig.py", line 158, in menuconfig
pmb.build.checksum(args, pkgname)
TypeError: 'module' object is not callable
The function was renamed, call new function.
2019-06-09 14:59:07 +00:00
|
|
|
pmb.build.checksum.update(args, pkgname)
|
2017-09-18 21:36:54 +00:00
|
|
|
|
|
|
|
# Check config
|
2020-04-13 08:51:56 +00:00
|
|
|
pmb.parse.kconfig.check(args, apkbuild["_flavor"], force_anbox_check=False,
|
2021-06-01 21:24:04 +00:00
|
|
|
force_nftables_check=False,
|
|
|
|
force_containers_check=False,
|
2021-06-24 02:07:46 +00:00
|
|
|
force_zram_check=False,
|
2021-07-01 15:32:13 +00:00
|
|
|
force_netboot_check=False,
|
2021-06-01 21:24:04 +00:00
|
|
|
details=True)
|