diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43002e5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/src.tgz diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..bd0e1a7 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "asdf" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9137c18 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "asdf" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8a35a07 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,3 @@ +FROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae +COPY target/x86_64-unknown-linux-musl/release/asdf /asdf +ENTRYPOINT ["/asdf"] diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 0000000..c98d27d --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c6af8d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +build: + docker run --rm -v "$(PWD):/app" -w /app -u "$(shell id -u):$(shell id -g)" \ + rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64 + cargo build --release --locked --target=x86_64-unknown-linux-musl + +docker: + sudo buildah bud --timestamp 0 --tag asdf + +src.tgz: + git archive -o src.tgz HEAD + +.PHONY: build docker src.tgz diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..d9d3090 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,15 @@ +pkgname=i-probably-didnt-backdoor-this +pkgver=0.1.0 +pkgrel=1 +arch=('x86_64') +makedepends=('cargo') +source=(src.tgz) +sha256sums=(SKIP) + +build() { + cargo build --release --locked +} + +package() { + install -Dm 755 target/release/asdf -t "${pkgdir}/usr/bin/" +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..61916c1 --- /dev/null +++ b/README.md @@ -0,0 +1,245 @@ +# I probably didn't backdoor this + +This is a practical attempt at shipping a program and having reasonably solid +evidence there's probably no backdoor. All source code is annotated and there +are instructions explaining how to use reproducible builds to rebuild the +artifacts distributed in this repository from source. + +The idea is shifting the burden of proof from "you need to prove there's a +backdoor" to "we need to prove there's probably no backdoor". This repository +is less about code (we're going to try to keep code at a minimum actually) and +instead contains technical writing that explains why these controls are +effective and how to verify them. You are very welcome to adopt the techniques +used here in your projects. + +The author should be assumed to be your average software developer, who might +be suspiciously good with computer security, but doesn't have nation-state +capabilities. + +## Contents + +- [Preparing retroactive reviews](#preparing-retroactive-reviews) +- [Pinned external resources](#pinned-external-resources) +- [Reading the source code](#reading-the-source-code) +- [Reproducing the ELF binary](#reproducing-the-elf-binary) +- [Reproducing the Docker image](#reproducing-the-oci-image) +- [Reproducing the Arch Linux package](#reproducing-the-arch-linux-package) +- [Notes on security patches](#notes-on-security-patches) +- [How is this related to Reproducible Builds](#how-is-this-related-to-reproducible-builds) +- [Similar work](#similar-work) + +### Preparing retroactive reviews + +Since "reading the source code" requires advanced domain knowledge, this +section describes a pen-and-paper aproach that can be used to cryptographically +ensure you can retro-actively review what you executed, even if you didn't +review before you executed it. Pen-and-paper should be taken literally here to +ensure this can't be modified by software. If done correctly, you don't need to +read the other sections immediately, instead you're creating an immutable +papertrail that can later be used by a subject matter expert. Note that the +review needs to happen on a different computer than the one that executed the +code, for safety reasons. + +Because it's in the authors interest to prove there are no backdoors, all +external resources that are not contained within this repository need to be +referred to in a way that's addressing its content (more on this in the next +section). + +We're starting with the main repository by cloning it and showing the commit +hash we're about to work with: + +```sh +$ git clone https://github.com/kpcyrd/i-probably-didnt-backdoor-this +$ cd i-probably-didnt-backdoor-this/ +$ git rev-parse HEAD +aabbccddeeff00112233445566778899aabbccdd +``` + +The hash in the last line is going to be different for you. This 40 character +id is what you need for your paper trail, you need to write this down +(preferably along with the current date) and keep it in a safe location. It +needs to be protected from undetected tampering but isn't secret, so you may +create copies or even post it publicly. + +This id uniquely identifies all files in this repository with their content. If +a file is modified/removed/added/renamed in this repository, this hash changes +too. + +If you want to read more about the cryptographic properties behind this, look +into [Merkel trees](https://en.wikipedia.org/wiki/Merkle_tree). + +### Pinned external resources + +In the previous section we've described how git is automatically tracking the +content of all files in this repository with a single hash. Software projects +often rely on external resources downloaded from the internet, like libraries. + +Downloading resources from the internet doesn't weaken what we've established +in the previous section, as long as: + +1. The content of the resource is pinned with a cryptographic hash and the hash + is recorded in the git repository. +2. We can be reasonably sure the resource is not going to disappear. If they + disappear you could attempt to use backup copies, as long as they match the + cryptographic hash in the repository. + +If at least one of those two doesn't apply we "broke the chain of custody". + +We don't have to implement this ourselves, but `cargo` and `docker` implement +this internally. + +### Reading the source code + +The repository contains 6 source code files, there's a writeup for each of +them. Files ending with `.md` are documentation. + +- [`Cargo.toml`](writeups/cargo-toml.md) - Contains metadata about the project and a list of dependencies (if any) +- [`Cargo.lock`](writeups/cargo-lock.md) - Automatically generated, records sha256 checksums for all dependencies +- [`src/main.rs`](writeups/main-rs.md) - The actual source code of our program +- [`Makefile`](writeups/makefile.md) - A wrapper script with build instructions +- [`Dockerfile`](writeups/dockerfile.md) - Contains build instructions for a container image +- [`PKGBUILD`](writeups/pkgbuild.md) - Contains build instructions for an Arch Linux package + +### Reproducing the ELF binary + +The binary is built in a docker container, the exact command can be found in +the [`Makefile`](writeups/makefile.md). Running make executes the build in a +specific Docker image (the official rust 1.54.0 alpine 3.14 docker image). + +Because the build environment is pinned and there's nothing introducing +non-determinism to the build (like recording the build time), running the build +on different computers (or even operating systems) should always result in the +same binary. + +Start the build with this command: + +```sh +$ make +``` + +This command should finish quite quickly and produces a binary that matches +this checksum: + +```sh +$ b2sum target/x86_64-unknown-linux-musl/release/asdf +35578eb5fbd13fe27bbc9f799488de2a196acfdb00886d7a5b88e13e0a73e8197fded1afdc9eb6b886864cd39bdeaa17910351da971710056630b1cb3a31a8cd target/x86_64-unknown-linux-musl/release/asdf +``` + +If you get the same checksum you've successfully reproduced the binary. If +there's no difference between the pre-compiled binary and the one you built +yourself this means the pre-compiled binary is just as trustworthy as the one +you built yourself. + +### Reproducing the Docker image + +There's a Dockerfile in the repository that always produces the same +bit-for-bit identical image if we provide the same binary (and use the right +command). It does so by selecting one specific official alpine image by its +sha256 hash, then `COPY`s the binary we've built in the previous section. + +```sh +$ b2sum target/x86_64-unknown-linux-musl/release/asdf +35578eb5fbd13fe27bbc9f799488de2a196acfdb00886d7a5b88e13e0a73e8197fded1afdc9eb6b886864cd39bdeaa17910351da971710056630b1cb3a31a8cd target/x86_64-unknown-linux-musl/release/asdf +$ make docker +sudo buildah bud --timestamp 0 --tag asdf +STEP 1/3: FROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae +STEP 2/3: COPY target/x86_64-unknown-linux-musl/release/asdf /asdf +STEP 3/3: ENTRYPOINT ["/asdf"] +COMMIT asdf +Getting image source signatures +Copying blob bc276c40b172 skipped: already exists +Copying blob 0ab66dfcdb16 done +Copying config 1816fbf1a0 done +Writing manifest to image destination +Storing signatures +--> 1816fbf1a0d +Successfully tagged localhost/asdf:latest +1816fbf1a0d2b49dda1eecc604419e5a8cb72df7924a7d2a3ebded128c9a1f66 +``` + +The last line is the hash of our image. We're using buildah to build the image +because there's no way to set the layer timestamp with docker (causing the hash +to vary). Unfortunately buildah records it's version, this image has been built +with `1.22.0`. + +Next pull the image from the registry: + +```sh +$ docker pull ghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest +latest: Pulling from kpcyrd/i-probably-didnt-backdoor-this +06127b9e1ec2: Pull complete +7c4fdf312986: Pull complete +Digest: sha256:7914eb02bce9944273a753e83cd55063ddbfd1aaf76fc023175188485d968fd3 +Status: Downloaded newer image for ghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest +ghcr.io/kpcyrd/i-probably-didnt-backdoor-this:latest +``` + +You'll noticed the hash doesn't seem to match at first, but the image id is +indeed the same: + +``` +$ docker images --no-trunc ghcr.io/kpcyrd/i-probably-didnt-backdoor-this +REPOSITORY TAG IMAGE ID CREATED SIZE +ghcr.io/kpcyrd/i-probably-didnt-backdoor-this latest sha256:1816fbf1a0d2b49dda1eecc604419e5a8cb72df7924a7d2a3ebded128c9a1f66 51 years ago 9.38MB +``` + +### Reproducing the Arch Linux package + +There's a custom Arch Linux repository that's distributing a pre-built package: + +``` +[i-probably-didnt-backdoor-this] +Server = https://pkgbuild.com/~kpcyrd/$repo/os/$arch/ +``` + +This package can be reproduced from source, the full writeup for this can be +found in [this document](writeups/archlinux.md). + +### Notes on security patches + +We've pinned very specific versions in multiple places (including the +compiler). This is often considered bad style since we're now in charge of +keeping all of this updated. + +If you're adopting this in your own project you should periodically release new +versions, even if you aren't making any changes to the code anymore. This also +applies to many modern programming ecosystems these days due to lock files. + +The following places need to be updated occasionally, causing the artifact +hashes to change. + +- Dependencies in Cargo.toml/Cargo.lock (if any, cargo update) +- `FROM` line in Dockerfile (docker pull alpine:latest) +- The build image in the Makefile (docker pull rust:alpine) + +### How is this related to Reproducible Builds + +There's quite a bit of overlap with the [reproducible +builds](https://reproducible-builds.org) project. The techniques used to +rebuild the binary artifacts are only possible because the builds for this +project are [reproducible](https://reproducible-builds.org/docs/definition/). + +This project also attempts to exclusively use binaries distributed by +high-profile targets like Alpine Linux and the Rust project. This is commonly +accepted as "reasonable" in the wider tech industry, but makes their build +servers and signing keys extremely valuable. + +The reproducible builds effort attempts to reduce this risk by allowing +independent parties to "reproduce" their packages with "confirmation rebuilds", +just like you did when following the instructions here! + +### Similar work + +- [Verifying a Tails image for reproducibility](https://tails.boum.org/contribute/build/reproducible/) +- [Reproducing Monero Binaries](https://github.com/monero-project/monero/blob/master/contrib/gitian/README.md) + +## Acknowledgments + +This project was funded by Google, The Linux Foundation, and people like you +and me through [GitHub sponsors](https://github.com/sponsors/kpcyrd). +♥️♥️♥️ + +## License + +Licensed under either of Apache License, Version 2.0 or MIT license at your +option. diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/writeups/archlinux.md b/writeups/archlinux.md new file mode 100644 index 0000000..e96153d --- /dev/null +++ b/writeups/archlinux.md @@ -0,0 +1,340 @@ +### Reproducing the Arch Linux package + +There's a custom Arch Linux repository that's distributing this package. + + [i-probably-didnt-backdoor-this] + Server = https://pkgbuild.com/~kpcyrd/$repo/os/$arch/ + +This repository contains these 6 files: + +- [i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst) + This is the pre-built package that's going to be installed on the system. + This is the file we want to reproduce. +- [i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst.sig](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst.sig) + This is a signature that we can use to verify the previous file was signed by + somebody with control over a specific private key. This signature is also + included in the .db file, so this file might not get downloaded. +- [i-probably-didnt-backdoor-this.db](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.db) + This contains an index of all packages in the repository. pacman downloads + this to learn about the packages in this repository. +- [i-probably-didnt-backdoor-this.db.tar.gz](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.db.tar.gz) + identical with the .db file for compatibility reasons. +- [i-probably-didnt-backdoor-this.files](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.files) + This contains an index of all the files in each package, this is only used by + `pacman -F` operations. +- [i-probably-didnt-backdoor-this.files.tar.gz](https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this.files.tar.gz) + identical with the .files file for compatibility reasons. + +This repository has been setup from this git repository using the following +commands. You don't need to run them, they're only included for documentation +purpose. + +- `extra-x86_64-build` to build the package from the [`PKGBUILD`](pkgbuild.md) + instructions +- `gpg --detach-sign --no-armor -u kpcyrd@archlinux.org + i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst` signs the package + with my key +- `repo-add i-probably-didnt-backdoor-this.db.tar.gz + i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst` this creates a + package database with our package + +`extra-x86_64-build` uses a clean chroot and records the environment in a file +called `.BUILDINFO` that's embedded in the package. We download the package and +list what's inside of it: + + $ wget https://pkgbuild.com/~kpcyrd/i-probably-didnt-backdoor-this/os/x86_64/i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst + [...] + $ b2sum i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst + 83b289364105e4d6f1d89a92bf5c1aa4e7e6367e14cb28ba1c28ece4a0d0012481f6af802cb0a2abd78c346c3eb6f7ac758e83eac6ffeeb18df8588cb00b11e8 i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst + $ tar tf i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst + .BUILDINFO + .MTREE + .PKGINFO + usr/ + usr/bin/ + usr/bin/asdf + +There's the .BUILDINFO file we already mentioned before, 2 files that are used +internally by pacman, and the binary that is distributed in this package. + +We only really care about the `.BUILDINFO` file, let's look into it: + + $ tar xfO i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst .BUILDINFO + format = 2 + pkgname = i-probably-didnt-backdoor-this + pkgbase = i-probably-didnt-backdoor-this + pkgver = 0.1.0-1 + pkgarch = x86_64 + pkgbuild_sha256sum = c7a3ce47d0f3b95ffae58fa60f1a08ab698c6a6f719f273ef8dff22ac2caefef + packager = kpcyrd + builddate = 1629399235 + builddir = /build + startdir = /startdir + buildtool = makepkg + buildtoolver = 6.0.0 + buildenv = !distcc + buildenv = color + buildenv = !ccache + buildenv = check + buildenv = !sign + options = strip + options = docs + options = !libtool + options = !staticlibs + options = emptydirs + options = zipman + options = purge + options = !debug + installed = acl-2.3.1-1-x86_64 + installed = archlinux-keyring-20210802-1-any + installed = argon2-20190702-3-x86_64 + installed = attr-2.5.1-1-x86_64 + installed = audit-3.0.4-1-x86_64 + installed = autoconf-2.71-1-any + installed = automake-1.16.4-1-any + installed = bash-5.1.008-1-x86_64 + installed = binutils-2.36.1-3-x86_64 + installed = bison-3.7.6-1-x86_64 + installed = bzip2-1.0.8-4-x86_64 + installed = ca-certificates-20210603-1-any + installed = ca-certificates-mozilla-3.69-1-x86_64 + installed = ca-certificates-utils-20210603-1-any + installed = coreutils-8.32-1-x86_64 + installed = cracklib-2.9.7-2-x86_64 + installed = cryptsetup-2.3.6-1-x86_64 + installed = curl-7.78.0-1-x86_64 + installed = db-5.3.28-5-x86_64 + installed = dbus-1.12.20-1-x86_64 + installed = device-mapper-2.03.13-1-x86_64 + installed = diffutils-3.8-1-x86_64 + installed = e2fsprogs-1.46.3-3-x86_64 + installed = elfutils-0.185-1-x86_64 + installed = expat-2.4.1-1-x86_64 + installed = fakeroot-1.25.3-2-x86_64 + installed = file-5.40-5-x86_64 + installed = filesystem-2021.05.31-1-x86_64 + installed = findutils-4.8.0-1-x86_64 + installed = flex-2.6.4-3-x86_64 + installed = gawk-5.1.0-1-x86_64 + installed = gc-8.0.4-4-x86_64 + installed = gcc-11.1.0-1-x86_64 + installed = gcc-libs-11.1.0-1-x86_64 + installed = gdbm-1.20-1-x86_64 + installed = gettext-0.21-1-x86_64 + installed = glib2-2.68.3-1-x86_64 + installed = glibc-2.33-5-x86_64 + installed = gmp-6.2.1-1-x86_64 + installed = gnupg-2.2.29-1-x86_64 + installed = gnutls-3.7.2-2-x86_64 + installed = gpgme-1.16.0-1-x86_64 + installed = grep-3.6-1-x86_64 + installed = groff-1.22.4-6-x86_64 + installed = guile-2.2.7-1-x86_64 + installed = gzip-1.10-3-x86_64 + installed = hwids-20210613-1-any + installed = iana-etc-20210728-1-any + installed = icu-69.1-1-x86_64 + installed = iptables-1:1.8.7-1-x86_64 + installed = json-c-0.15-1-x86_64 + installed = kbd-2.4.0-2-x86_64 + installed = keyutils-1.6.3-1-x86_64 + installed = kmod-29-1-x86_64 + installed = krb5-1.19.1-1-x86_64 + installed = less-1:590-1-x86_64 + installed = libarchive-3.5.1-1-x86_64 + installed = libassuan-2.5.5-1-x86_64 + installed = libatomic_ops-7.6.10-2-x86_64 + installed = libcap-2.51-1-x86_64 + installed = libcap-ng-0.8.2-3-x86_64 + installed = libcroco-0.6.13-2-x86_64 + installed = libedit-20210522_3.1-1-x86_64 + installed = libelf-0.185-1-x86_64 + installed = libffi-3.3-4-x86_64 + installed = libgcrypt-1.9.3-1-x86_64 + installed = libgpg-error-1.42-1-x86_64 + installed = libidn2-2.3.2-1-x86_64 + installed = libksba-1.6.0-1-x86_64 + installed = libldap-2.4.59-2-x86_64 + installed = libmicrohttpd-0.9.73-1-x86_64 + installed = libmnl-1.0.4-3-x86_64 + installed = libmpc-1.2.1-1-x86_64 + installed = libnetfilter_conntrack-1.0.8-1-x86_64 + installed = libnfnetlink-1.0.1-4-x86_64 + installed = libnftnl-1.2.0-1-x86_64 + installed = libnghttp2-1.44.0-1-x86_64 + installed = libnl-3.5.0-3-x86_64 + installed = libp11-kit-0.24.0-1-x86_64 + installed = libpcap-1.10.1-1-x86_64 + installed = libpsl-0.21.1-1-x86_64 + installed = libsasl-2.1.27-3-x86_64 + installed = libseccomp-2.5.1-2-x86_64 + installed = libsecret-0.20.4-1-x86_64 + installed = libssh2-1.9.0-3-x86_64 + installed = libtasn1-4.17.0-1-x86_64 + installed = libtirpc-1.3.2-1-x86_64 + installed = libtool-2.4.6+42+gb88cebd5-16-x86_64 + installed = libunistring-0.9.10-3-x86_64 + installed = libusb-1.0.24-2-x86_64 + installed = libxcrypt-4.4.25-1-x86_64 + installed = libxml2-2.9.10-9-x86_64 + installed = linux-api-headers-5.12.3-1-any + installed = llvm-libs-12.0.1-3-x86_64 + installed = lz4-1:1.9.3-2-x86_64 + installed = m4-1.4.19-1-x86_64 + installed = make-4.3-3-x86_64 + installed = mpfr-4.1.0.p13-1-x86_64 + installed = ncurses-6.2-2-x86_64 + installed = nettle-3.7.3-1-x86_64 + installed = npth-1.6-3-x86_64 + installed = openssl-1.1.1.k-1-x86_64 + installed = p11-kit-0.24.0-1-x86_64 + installed = pacman-6.0.0-5-x86_64 + installed = pacman-mirrorlist-20210808-1-any + installed = pam-1.5.1-1-x86_64 + installed = pambase-20210605-2-any + installed = patch-2.7.6-8-x86_64 + installed = pcre-8.45-1-x86_64 + installed = pcre2-10.37-1-x86_64 + installed = perl-5.34.0-2-x86_64 + installed = pinentry-1.1.1-1-x86_64 + installed = pkgconf-1.7.3-1-x86_64 + installed = popt-1.18-1-x86_64 + installed = readline-8.1.001-1-x86_64 + installed = rust-1:1.54.0-1-x86_64 + installed = sed-4.8-1-x86_64 + installed = shadow-4.8.1-4-x86_64 + installed = sqlite-3.36.0-1-x86_64 + installed = sudo-1.9.7.p2-1-x86_64 + installed = systemd-249.3-1-x86_64 + installed = systemd-libs-249.3-1-x86_64 + installed = tar-1.34-1-x86_64 + installed = texinfo-6.8-2-x86_64 + installed = tzdata-2021a-1-x86_64 + installed = util-linux-2.37.2-1-x86_64 + installed = util-linux-libs-2.37.2-1-x86_64 + installed = which-2.21-5-x86_64 + installed = xz-5.2.5-1-x86_64 + installed = zlib-1:1.2.11-4-x86_64 + installed = zstd-1.5.0-1-x86_64 + +This seems like a lot of control from a file we just downloaded from the +internet, but note that most of these are only informal and the tooling we're +going to use only allows packages to be installed that have been officially +published in Arch Linux. The packages listed here are basically a base-devel +install plus `makedepends=`. + +For official Arch Linux packages the field `pkgbase` is used with +[`asp`](https://man.archlinux.org/man/extra/asp/asp.1.en) to fetch the build +instructions and `pkgbuild_sha256sum` is used to identify the right commit. For +technical reasons the commit id is not yet available when the Arch Linux +package is built. + +Because in our case everything is contained within this repository and we +already know the right commit, so we can skip this step. The Arch Linux tooling +expects a tar ball, so we're generating one from this repository. The commands +that are used for this can be found in the [`Makefile`](makefile.md). + + $ make src.tgz + +Using the Arch Linux reproducible builds tooling we're taking the build +environment from the package, the [`PKGBUILD`](pkgbuild.md) build instructions +from this repository, and the `src.tgz` tar ball we've just generated and +attempt to create an identical package. + +`makerepropkg` can be installed with `pacman -S devtools`. + + $ makerepropkg i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst + Create subvolume '/var/lib/archbuild/reproducible/root' + ==> Creating install root at /var/lib/archbuild/reproducible/root + ==> Installing packages to /var/lib/archbuild/reproducible/root + warning: database file for 'core' does not exist (use '-Sy' to download) + warning: database file for 'extra' does not exist (use '-Sy' to download) + warning: database file for 'community' does not exist (use '-Sy' to download) + loading packages... + resolving dependencies... + looking for conflicting packages... + + Packages (131) acl-2.3.1-1 archlinux-keyring-20210802-1 argon2-20190702-3 attr-2.5.1-1 + audit-3.0.4-1 autoconf-2.71-1 automake-1.16.4-1 bash-5.1.008-1 binutils-2.36.1-3 + bison-3.7.6-1 bzip2-1.0.8-4 ca-certificates-20210603-1 + ca-certificates-mozilla-3.69-1 ca-certificates-utils-20210603-1 coreutils-8.32-1 + cracklib-2.9.7-2 cryptsetup-2.3.6-1 curl-7.78.0-1 db-5.3.28-5 dbus-1.12.20-1 + device-mapper-2.03.13-1 diffutils-3.8-1 e2fsprogs-1.46.3-3 elfutils-0.185-1 + expat-2.4.1-1 fakeroot-1.25.3-2 file-5.40-5 filesystem-2021.05.31-1 + findutils-4.8.0-1 flex-2.6.4-3 gawk-5.1.0-1 gc-8.0.4-4 gcc-11.1.0-1 + gcc-libs-11.1.0-1 gdbm-1.20-1 gettext-0.21-1 glib2-2.68.3-1 glibc-2.33-5 + gmp-6.2.1-1 gnupg-2.2.29-1 gnutls-3.7.2-2 gpgme-1.16.0-1 grep-3.6-1 + groff-1.22.4-6 guile-2.2.7-1 gzip-1.10-3 hwids-20210613-1 iana-etc-20210728-1 + icu-69.1-1 iptables-1:1.8.7-1 json-c-0.15-1 kbd-2.4.0-2 keyutils-1.6.3-1 + kmod-29-1 krb5-1.19.1-1 less-1:590-1 libarchive-3.5.1-1 libassuan-2.5.5-1 + libatomic_ops-7.6.10-2 libcap-2.51-1 libcap-ng-0.8.2-3 libcroco-0.6.13-2 + libedit-20210522_3.1-1 libelf-0.185-1 libffi-3.3-4 libgcrypt-1.9.3-1 + libgpg-error-1.42-1 libidn2-2.3.2-1 libksba-1.6.0-1 libldap-2.4.59-2 + libmicrohttpd-0.9.73-1 libmnl-1.0.4-3 libmpc-1.2.1-1 libnetfilter_conntrack-1.0.8-1 + libnfnetlink-1.0.1-4 libnftnl-1.2.0-1 libnghttp2-1.44.0-1 libnl-3.5.0-3 + libp11-kit-0.24.0-1 libpcap-1.10.1-1 libpsl-0.21.1-1 libsasl-2.1.27-3 + libseccomp-2.5.1-2 libsecret-0.20.4-1 libssh2-1.9.0-3 libtasn1-4.17.0-1 + libtirpc-1.3.2-1 libtool-2.4.6+42+gb88cebd5-16 libunistring-0.9.10-3 + libusb-1.0.24-2 libxcrypt-4.4.25-1 libxml2-2.9.10-9 linux-api-headers-5.12.3-1 + llvm-libs-12.0.1-3 lz4-1:1.9.3-2 m4-1.4.19-1 make-4.3-3 mpfr-4.1.0.p13-1 + ncurses-6.2-2 nettle-3.7.3-1 npth-1.6-3 openssl-1.1.1.k-1 p11-kit-0.24.0-1 + pacman-6.0.0-5 pacman-mirrorlist-20210808-1 pam-1.5.1-1 pambase-20210605-2 + patch-2.7.6-8 pcre-8.45-1 pcre2-10.37-1 perl-5.34.0-2 pinentry-1.1.1-1 + pkgconf-1.7.3-1 popt-1.18-1 readline-8.1.001-1 rust-1:1.54.0-1 sed-4.8-1 + shadow-4.8.1-4 sqlite-3.36.0-1 sudo-1.9.7.p2-1 systemd-249.3-1 + systemd-libs-249.3-1 tar-1.34-1 texinfo-6.8-2 tzdata-2021a-1 util-linux-2.37.2-1 + util-linux-libs-2.37.2-1 which-2.21-5 xz-5.2.5-1 zlib-1:1.2.11-4 zstd-1.5.0-1 + + Total Installed Size: 1373.98 MiB + + :: Proceed with installation? [Y/n] + (131/131) checking keys in keyring [#################################] 100% + (131/131) checking package integrity [#################################] 100% + (131/131) loading package files [#################################] 100% + (131/131) checking for file conflicts [#################################] 100% + (131/131) checking available disk space [#################################] 100% + :: Processing package changes... + ( 1/131) installing linux-api-headers [#################################] 100% + ( 2/131) installing tzdata [#################################] 100% + ( 3/131) installing iana-etc [#################################] 100% + ( 4/131) installing filesystem [#################################] 100% + +This takes some time but should eventually print the following text at the end: + + ==> Extracting sources... + -> Extracting src.tgz with bsdtar + ==> Starting build()... + Compiling asdf v0.1.0 (/build/i-probably-didnt-backdoor-this/src) + Finished release [optimized] target(s) in 1.71s + ==> Entering fakeroot environment... + ==> Starting package()... + ==> Tidying install... + -> Removing libtool files... + -> Purging unwanted files... + -> Removing static library files... + -> Stripping unneeded symbols from binaries and libraries... + -> Compressing man and info pages... + ==> Checking for packaging issues... + ==> Creating package "i-probably-didnt-backdoor-this"... + -> Generating .PKGINFO file... + -> Generating .BUILDINFO file... + warning: database file for 'core' does not exist (use '-Sy' to download) + warning: database file for 'extra' does not exist (use '-Sy' to download) + warning: database file for 'community' does not exist (use '-Sy' to download) + -> Generating .MTREE file... + -> Compressing package... + ==> Leaving fakeroot environment. + ==> Finished making: i-probably-didnt-backdoor-this 0.1.0-1 (Thu 19 Aug 2021 09:04:10 PM CEST) + -> built succeeded! built packages can be found in /var/lib/archbuild/reproducible/testenv/pkgdest + ==> comparing artifacts... + -> Package 'i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst' successfully reproduced! + +This means we've successfully built a package from source that is bit-for-bit +identical, including every file inside of it. The first is the package we +downloaded, the second is the package we built from source. + +```sh +$ b2sum i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst /var/lib/archbuild/reproducible/testenv/pkgdest/i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst +83b289364105e4d6f1d89a92bf5c1aa4e7e6367e14cb28ba1c28ece4a0d0012481f6af802cb0a2abd78c346c3eb6f7ac758e83eac6ffeeb18df8588cb00b11e8 i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst +83b289364105e4d6f1d89a92bf5c1aa4e7e6367e14cb28ba1c28ece4a0d0012481f6af802cb0a2abd78c346c3eb6f7ac758e83eac6ffeeb18df8588cb00b11e8 /var/lib/archbuild/reproducible/testenv/pkgdest/i-probably-didnt-backdoor-this-0.1.0-1-x86_64.pkg.tar.zst +``` diff --git a/writeups/cargo-lock.md b/writeups/cargo-lock.md new file mode 100644 index 0000000..7f9f041 --- /dev/null +++ b/writeups/cargo-lock.md @@ -0,0 +1,15 @@ +# `Cargo.lock` + +This file is automatically generated, it usually contains checksums of the +dependencies of the project, but since our project doesn't have any it only +shows our name and version that we've seen in [`Cargo.toml`](cargo-toml.md). + +```toml +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "asdf" +version = "0.1.0" +``` diff --git a/writeups/cargo-toml.md b/writeups/cargo-toml.md new file mode 100644 index 0000000..32a15b3 --- /dev/null +++ b/writeups/cargo-toml.md @@ -0,0 +1,25 @@ +# `Cargo.toml` + +This is mostly defaults from running `cargo new --bin asdf`: + +```toml +[package] +name = "asdf" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +``` + +- `name = "asdf"` is the name of our project. This isn't really used for + anything but the binary name. +- `version = "0.1.0"` is the version of our project. +- `edition = "2018"` this means we're opting into new features of the Rust + compiler. If unspecified rustc is using the 2015 edition, the 2018 edition is + the default for new projects. + +The `[dependencies]` section is able to reference other code that isn't part of +this repository, but there are none in this case because there are no lines +after this one. diff --git a/writeups/dockerfile.md b/writeups/dockerfile.md new file mode 100644 index 0000000..3da55c8 --- /dev/null +++ b/writeups/dockerfile.md @@ -0,0 +1,19 @@ +# `Dockerfile` + +```dockerfile +FROM docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae +COPY target/x86_64-unknown-linux-musl/release/asdf /asdf +ENTRYPOINT ["/asdf"] +``` + +- `FROM + docker.io/alpine@sha256:eb3e4e175ba6d212ba1d6e04fc0782916c08e1c9d7b45892e9796141b1d379ae` + This describes the image we use as a base. We're pinning one of the official + [alpine](https://hub.docker.com/_/alpine) images here. +- `COPY target/x86_64-unknown-linux-musl/release/asdf /asdf` This copies the + file `target/x86_64-unknown-linux-musl/release/asdf` from our local + filesystem to `/asdf` in the container. See the [`Makefile`](makefile.md) how + this file is generated. +- `ENTRYPOINT ["/asdf"]` This sets the `/asdf` binary we just copied into the + container as the entrypoint, meaning if the container is executed, this + binary runs, nothing else. diff --git a/writeups/main-rs.md b/writeups/main-rs.md new file mode 100644 index 0000000..fa55b29 --- /dev/null +++ b/writeups/main-rs.md @@ -0,0 +1,10 @@ +# `src/main.rs` + +This is our program. We're creating a function called `main` that contains a +call to the `println!` macro to print the string `Hello, world!` to stdout. + +```rust +fn main() { + println!("Hello, world!"); +} +``` diff --git a/writeups/makefile.md b/writeups/makefile.md new file mode 100644 index 0000000..29fd2b1 --- /dev/null +++ b/writeups/makefile.md @@ -0,0 +1,79 @@ +# `Makefile` + +This is likely the most complicated file in this repository, we're going to +explain this in depth. + +```make +build: + docker run --rm -v "$(PWD):/app" -w /app -u "$(shell id -u):$(shell id -g)" \ + rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64 + cargo build --release --locked --target=x86_64-unknown-linux-musl + +docker: + sudo buildah bud --timestamp 0 --tag asdf + +src.tgz: + git archive -o src.tgz HEAD + +.PHONY: build docker src.tgz +``` + +## `build:` + +This builds the ELF binary. + +- `docker run` This means we're going to run a [docker + container](https://www.docker.com/resources/what-container) +- `--rm` This means the container should be temporary and is going to be + deleted after our command completes. +- `-v "$(PWD):/app"` This means we're going to make the current directory + available in the container at `/app`. +- `-w /app` This means we want to run our command inside of `/app` +- `-u "$(shell id -u):$(shell id -g)" ` This means the user id and group id + of the process in the container should be equal to the user id and group id + of the host system. This is important on Linux because of the mount, with + docker for macOS this setting is actually optional. +- `rust@sha256:8463cc29a3187a10fc8bf5200619aadf78091b997b0c3941345332a931c40a64` + This specifies one specific Rust image by it's checksum. This is important to + document which compiler was used to build the binary. If you use the same + compiler you're also going to get a 100% identical binary (note this might + not be the case with more complex builds). +- `cargo build --release --locked` This is the command we're running inside the + container. This is compiling the binary with optimizations from the release + profile. +- `--locked` This option explicitly says the dependencies in the Cargo.lock + file must be used (none, in our case). +- `--target=x86_64-unknown-linux-musl` This specifies the target system we want + to support, in our case that's the cpu architecture and linux with musl libc. + This currently implies statically linked builds in the rust world. + +## `docker:` + +This builds the Docker image. + +- `sudo buildah` This means we're going to run [`buildah`](https://buildah.io/) + as root. `buildah` is a tool to build container images, its less known than + docker but has a unique feature that we're going to use here. The final image + can be used with docker too. +- `bud` This is short for build-using-dockerfile, it means we're going to + execute the instructions in our [`Dockerfile`](dockerfile.md). +- `--timestamp 0` This causes buildah to hardcode the build time to `1970-01-01 + 00:00:00`. Usually the current time is used instead, which would make the + image indeterministic. +- `--tag asdf` This means our newly built image should be tagged with the name + `asdf`. + +## `src.tgz:` + +This snapshots all the source code from this git commit into an archive. This +is only needed for the Arch Linux package. + +- `git archive` This subcommand creates an archive that contains all the code + from a given commit. +- `-o src.tgz` This specifies the file the archive should be written to. +- `HEAD` Refers to the commit we've currently checked out. + +## `.PHONY: build docker` + +This means `build` and `docker` are target names, not file names. The commands +should execute even if a file with that name already exists. diff --git a/writeups/pkgbuild.md b/writeups/pkgbuild.md new file mode 100644 index 0000000..a21f74a --- /dev/null +++ b/writeups/pkgbuild.md @@ -0,0 +1,88 @@ +# `PKGBUILD` + +This file is only used if you're following the "Reproducing the Arch Linux +package" instructions. + +```sh +pkgname=i-probably-didnt-backdoor-this +pkgver=0.1.0 +pkgrel=1 +arch=('x86_64') +makedepends=('cargo') +source=(src.tgz) +sha256sums=(SKIP) + +build() { + cargo build --release --locked +} + +package() { + install -Dm 755 target/release/asdf -t "${pkgdir}/usr/bin/" +} +``` + +This is the bare minimum to create a working package, even though it doesn't +meet the Arch Linux packaging standards (namcap is going to print some warnings +about this). + +```sh +pkgname=i-probably-didnt-backdoor-this +pkgver=0.1.0 +pkgrel=1 +arch=('x86_64') +``` + +These fields are required in a PKGBUILD, it contains the package name and the +package version. `pkgrel=` is a "revision" in case we need to release a new +package for the same upstream version. `arch=` is a list of supported +architectures, for simplicity we set this to just `x86_64`. + +```sh +makedepends=('cargo') +``` + +In addition to base-devel, which we can assume is always installed in the build +container, we also need the rust build system. Note that we don't specify which +version we want, for the initial build this is automatically going to resolve +to "the latest in Arch Linux", for our rebuild we're going to pick the one +that's specified in the `.BUILDINFO` file of the package we want to reproduce. +There's an in-depth explanation in the [Arch Linux package +writeup](archlinux.md). + +```sh +source=(src.tgz) +sha256sums=(SKIP) +``` + +These are the source inputs, `src.tgz` is a tarball of this repository that +we're going to generate with `git archive` as described in the +[`Makefile`](makefile.md). + +```sh +build() { + cargo build --release --locked +} +``` + +This function implements the actual build. `--release` specifies the binary +should be built with the [standard release +profile](https://doc.rust-lang.org/cargo/reference/profiles.html#release). +`--locked` means the build MUST use the dependencies defined in +[`Cargo.lock`](cargo-lock.md). + +```sh +package() { + install -Dm 755 target/release/asdf -t "${pkgdir}/usr/bin/" +} +``` + +After the build this function implements how the package should be created. + +- `install -Dm 755` means we want to copy a file, all directories in the + destination path should be created as needed, and `755` are the permissions + the file should have. This translates to "read/write/execute for root, + read/execute for everybody else". +- `target/release/asdf` this is the file that was compiled in `build()` that we + want to ship in our package. +- `-t "${pkgdir}/usr/bin/"` this means the file should be copied into the + `/usr/bin/` folder of our package. `install` is going to keep the filename.