forked from canonical/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsnapd.mk
More file actions
396 lines (353 loc) · 17.7 KB
/
Copy pathsnapd.mk
File metadata and controls
396 lines (353 loc) · 17.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
# This makefile is designed to be invoked from a build tree, not from the
# source tree. This is particularly suited for building RPM packages. The goal
# of this makefile is to *reduce* the duplication, *avoid* unintended
# inconsistency between packaging of snapd across distributions.
#
# -----------------------------------------------------
# Interface between snapd.mk and distribution packaging
# -----------------------------------------------------
#
# Distribution packaging must generate snapd.defines.mk with a set of makefile
# variable definitions that are discussed below. This allows the packaging
# world to define directory layout and build configuration in one place and
# this makefile to simply obey and implement that configuration.
ifeq ($(SNAPD_DEFINES_DIR),)
SNAPD_DEFINES_DIR = $(PWD)
endif
include $(SNAPD_DEFINES_DIR)/snapd.defines.mk
# There are two sets of definitions expected:
# 1) variables defining various directory names
vars += bindir sbindir libexecdir mandir datadir localstatedir sharedstatedir unitdir builddir
# 2) variables defining build options:
# with_testkeys: set to 1 to build snapd with test key built in
# with_apparmor: set to 1 to build snapd with apparmor support
# with_core_bits: set to 1 to build snapd with things needed for the core/snapd snap
# with_alt_snap_mount_dir: set to 1 to build snapd with alternate snap mount directory
# with_vendor: set to 1 to build snapd using the vendor directory for dependencies
# with_static_pie: set to 1 to build static binaries in PIE mode if
vars += with_testkeys with_apparmor with_core_bits with_alt_snap_mount_dir with_vendor with_static_pie
# Verify that none of the variables are empty. This may happen if snapd.mk and
# distribution packaging generating snapd.defines.mk get out of sync.
$(foreach var,$(vars),$(if $(value $(var)),,$(error $(var) is empty or unset, check snapd.defines.mk)))
# ------------------------------------------------
# There are no more control knobs after this point
# ------------------------------------------------
# Import path of snapd.
import_path = github.com/snapcore/snapd
# Trusted account keys that must be present in production builds.
# These are used by check-trusted-account-keys target to verify that
# test keys are not accidentally included in production builds.
SNAPD_STORE_ROOT_KEY = -CvQKAwRQ5h3Ffn10FILJoEZUXOv6km9FwA80-Rcj-f-6jadQ89VRswHNiEB9Lxk
SNAPD_STORE_GENERIC_MODELS_KEY = d-JcZF9nD9eBw7bwMnH61x-bklnQOhQud1Is6o_cn2wTj8EYDi9musrIT9z2MdAa
SNAPD_REPAIR_ROOT_KEY = nttW6NfBXI_E-00u38W-KH6eiksfQNXuI7IiumoV49_zkbhM0sYTzSnFlwZC-W4t
# This is usually set by %make_install. It is defined here to avoid warnings or
# errors from referencing undefined variables.
DESTDIR? =
# Decide which of the two snap mount directories to use. This is not
# referencing localstatedir because the code copes with only those two values
# explicitly.
ifeq ($(with_alt_snap_mount_dir),1)
snap_mount_dir = /var/lib/snapd/snap
else
snap_mount_dir = /snap
endif
# The list of go binaries we are expected to build.
go_binaries = $(addprefix $(builddir)/, snap snapctl snap-seccomp snap-update-ns snap-exec snapd snapd-apparmor)
GO_TAGS = nosecboot
ifeq ($(with_testkeys),1)
GO_TAGS += withtestkeys
GO_TAGS += structuredlogging
endif
# Any additional tags common to all targets
GO_TAGS += $(EXTRA_GO_BUILD_TAGS)
ifeq ($(GO111MODULE),off)
GO_MOD=
else
GO_MOD=-mod=vendor
ifeq ($(with_vendor),0)
GO_MOD=-mod=readonly
endif
endif
GO_STATIC_BUILDMODE = default
GO_STATIC_EXTLDFLAG = -static
ifeq ($(with_static_pie),1)
# override flags for building static binaries in PIE mode if supported
# by the host system
GO_STATIC_BUILDMODE = pie
GO_STATIC_EXTLDFLAG = -static-pie
endif
# Go -ldflags settings for static build. Can be overridden in snapd.defines.mk.
EXTRA_GO_STATIC_LDFLAGS ?= -linkmode external -extldflags="$(GO_STATIC_EXTLDFLAG)" $(EXTRA_GO_LDFLAGS)
# sourcedir is the path to the source directory tree (where the go source files are).
# This is used by prepare-debian-build-tree to remove unnecessary code, and by
# check-static-binaries to locate C binaries built by the autotools cmd/ build.
# Can be set in snapd.defines.mk or on the make command line; defaults to $(CURDIR).
# For Debian/dh-golang, this would be: sourcedir=_build/src/github.com/snapcore/snapd
sourcedir ?= $(CURDIR)
# NOTE: This *depends* on building out of tree. Some of the built binaries
# conflict with directory names in the tree.
.PHONY: all
all: $(go_binaries)
# Prepare the build tree by removing code that is not used in non-embedded builds.
# This removes snap-bootstrap, snap-fde-keymgr, and secboot-related code that
# is only needed for embedded systems and UC20+ builds. This could be somewhat
# avoided if we had all the dependencies in Debian OR if dh-golang supported
# build tags properly.
.PHONY: prepare-debian-build-tree
prepare-debian-build-tree:
# exclude certain parts that won't be used by debian
find $(sourcedir)/cmd/snap-bootstrap -name "*.go" 2>/dev/null | xargs -r rm -f
find $(sourcedir)/cmd/snap-fde-keymgr -name "*.go" 2>/dev/null | xargs -r rm -f
find $(sourcedir)/gadget/install -name "*.go" -not -name "params.go" -not -name "install_placeholder.go" -not -name "kernel.go" 2>/dev/null | xargs -r rm -f
# XXX: once dh-golang understands go build tags this would not be needed
find $(sourcedir)/secboot/ -name "*.go" 2>/dev/null | grep -E '(.*_sb(_test)?\.go|.*_tpm(_test)?\.go|secboot_hooks.go|auth_requestor.go|keymgr/)' | xargs -r rm -f
# Rename plainkey files to indicate they are secboot variants
if [ -f $(sourcedir)/secboot/keys/plainkey.go ]; then mv $(sourcedir)/secboot/keys/plainkey.go $(sourcedir)/secboot/keys/plainkey_sb.go; fi
if [ -f $(sourcedir)/secboot/keys/plainkey_test.go ]; then mv $(sourcedir)/secboot/keys/plainkey_test.go $(sourcedir)/secboot/keys/plainkey_sb_test.go; fi
find $(sourcedir)/secboot/keys/ -name "*.go" 2>/dev/null | grep -E '(.*_sb(_test)?\.go)' | xargs -r rm -f
find $(sourcedir)/boot/ -name "*.go" 2>/dev/null | grep -E '(.*_sb(_test)?\.go)' | xargs -r rm -f
# FIXME: not all Go toolchains we build with support '-B gobuildid', replace a
# random GNU build ID with something more predictable, use something similar to
# https://pagure.io/go-rpm-macros/c/1980932bf3a21890a9571effaa23fbe034fd388d
$(builddir)/snap: GO_TAGS += nomanagers
$(builddir)/snap $(builddir)/snap-seccomp $(builddir)/snapd-apparmor:
go build -o $@ $(if $(GO_TAGS),-tags "$(GO_TAGS)") \
-buildmode=pie \
-ldflags="$(EXTRA_GO_LDFLAGS)" \
$(GO_MOD) \
$(EXTRA_GO_BUILD_FLAGS) \
$(import_path)/cmd/$(notdir $@)
# Those three need to be built as static binaries. They run on the inside of a
# nearly-arbitrary mount namespace that does not contain anything we can depend
# on (no standard library, for example).
$(builddir)/snap-update-ns $(builddir)/snap-exec $(builddir)/snapctl:
go build -o $@ -buildmode=$(GO_STATIC_BUILDMODE) \
$(GO_MOD) \
$(if $(GO_TAGS),-tags "$(GO_TAGS)") \
-ldflags="$(EXTRA_GO_STATIC_LDFLAGS)" \
$(EXTRA_GO_BUILD_FLAGS) \
$(import_path)/cmd/$(notdir $@)
# Check that critical binaries are statically linked.
# These binaries execute inside mount namespaces and cannot depend on external libraries.
# builddir: the directory containing the built Go binaries (e.g., _build/bin)
# sourcedir: the root of the snapd source tree (used to locate C binaries built by autotools)
.PHONY: check-static-binaries
check-static-binaries:
@echo "Checking that critical binaries are statically linked..."
@for binary in snap-exec snap-update-ns snapctl; do \
if [ -f "$(builddir)/$$binary" ]; then \
if ! file "$(builddir)/$$binary" | grep -q -F static; then \
echo "ERROR: $$binary is dynamically linked, must be static"; \
ldd "$(builddir)/$$binary"; \
exit 1; \
fi; \
if [ "$(with_static_pie)" = 1 ] && ! file $(builddir)/$$binary | grep -q -F pie; then \
echo "ERROR: $$binary is not a static PIE"; \
exit 1; \
fi; \
echo " $$binary: OK (static)"; \
fi; \
done
@# snap-gdbserver-shim is a C binary built by the autotools cmd/ build, not by the Go
@# build rules, so it will not appear in $(builddir). Search several well-known locations
@# in order: the Go output dir (unlikely but harmless), the autotools in-tree build
@# directory, and the installed location when DESTDIR is set.
@shim=""; \
for candidate in \
"$(builddir)/snap-gdbserver-shim" \
"$(sourcedir)/cmd/snap-gdb-shim/snap-gdbserver-shim" \
"$(DESTDIR)$(libexecdir)/snapd/snap-gdbserver-shim"; do \
if [ -f "$$candidate" ]; then shim="$$candidate"; break; fi; \
done; \
if [ -n "$$shim" ]; then \
if ! file "$$shim" | grep -q -F static; then \
echo "ERROR: snap-gdbserver-shim is dynamically linked, must be static"; \
ldd "$$shim"; \
exit 1; \
fi; \
if [ "$(with_static_pie)" = 1 ] && ! file "$$shim" | grep -q -F pie; then \
echo "ERROR: snap-gdbserver-shim is not a static PIE"; \
exit 1; \
fi; \
echo " snap-gdbserver-shim: OK (static) [$$shim]"; \
fi
@echo "All static binary checks passed."
# XXX see the note about build ID in rule for building 'snap'
# Snapd can be built with test keys. This is only used by the internal test
# suite to add test assertions. Do not enable this in distribution packages.
$(builddir)/snapd:
go build -o $@ -buildmode=pie \
-ldflags="$(EXTRA_GO_LDFLAGS)" \
$(GO_MOD) \
$(if $(GO_TAGS),-tags "$(GO_TAGS)") \
$(EXTRA_GO_BUILD_FLAGS) \
$(import_path)/cmd/$(notdir $@)
# Know how to create certain directories.
$(addprefix $(DESTDIR),$(libexecdir)/snapd $(bindir) $(mandir)/man8 /$(sharedstatedir)/snapd $(localstatedir)/cache/snapd $(snap_mount_dir)):
install -m 755 -d $@
.PHONY: install
# Install snap into /usr/bin/.
install:: $(builddir)/snap | $(DESTDIR)$(bindir)
install -m 755 $^ $|
# Install snapctl snapd, snap-{exec,update-ns,seccomp} into /usr/lib/snapd/
install:: $(addprefix $(builddir)/,snapctl snapd snap-exec snap-update-ns snap-seccomp snapd-apparmor) | $(DESTDIR)$(libexecdir)/snapd
install -m 755 $^ $|
# Ensure /usr/bin/snapctl is a symlink to /usr/lib/snapd/snapctl
install:: | $(DESTDIR)$(bindir)
ln -s $(libexecdir)/snapd/snapctl $|/snapctl
# Generate and install man page for snap command
install:: $(builddir)/snap | $(DESTDIR)$(mandir)/man8
$(builddir)/snap help --man > $|/snap.8
# Install the directory structure in /var/lib/snapd
install::
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/apparmor/profiles
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/apparmor/snap-confine
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/assertions
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/cache
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/cgroup
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/cookie
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/dbus-1/services
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/dbus-1/system-services
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/desktop/applications
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/device
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/environment
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/hostfs
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/inhibit
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/lib/gl
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/lib/gl32
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/lib/glvnd
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/lib/vulkan
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/mount
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/seccomp/bpf
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/sequence
install -m 755 -d $(DESTDIR)/$(sharedstatedir)/snapd/snaps
# Touch files that are ghosted by the package. Those are _NOT_ installed but
# this way the package manager knows about them belonging to the package.
install:: | $(DESTDIR)/$(sharedstatedir)/snapd
touch $|/state.json
touch $|/system-key
install:: | $(DESTDIR)$(localstatedir)/cache/snapd
touch $|/sections
touch $|/names
touch $|/commands
install:: | $(DESTDIR)$(snap_mount_dir)
touch $|/README
# Install the /snap/bin directory
install::
install -m 755 -d $(DESTDIR)$(snap_mount_dir)/bin
# Install misc directories:
install::
install -m 755 -d $(DESTDIR)$(localstatedir)/cache/snapd
install -m 755 -d $(DESTDIR)$(datadir)/polkit-1/actions
# Do not ship snap-preseed. It is currently only useful on ubuntu and tailored
# for preseeding of ubuntu cloud images due to certain assumptions about
# runtime environment of the host and of the preseeded image.
install::
rm -f $(DESTDIR)$(bindir)/snap-preseed
ifeq ($(with_core_bits),0)
# Remove systemd units that are only used on core devices.
install::
rm -f $(addprefix $(DESTDIR)$(unitdir)/,snapd.autoimport.service snapd.system-shutdown.service snapd.snap-repair.timer snapd.snap-repair.service snapd.core-fixup.service snapd.recovery-chooser-trigger.service)
# Remove fixup script that is only used on core devices.
install::
rm -f $(DESTDIR)$(libexecdir)/snapd/snapd.core-fixup.sh
# Remove system-shutdown helper that is only used on core devices.
install::
rm -f $(DESTDIR)$(libexecdir)/snapd/system-shutdown
endif
ifeq ($(with_apparmor),0)
# Don't ship apparmor helper service when AppArmor is not enabled.
install::
rm -f $(DESTDIR)$(unitdir)/snapd.apparmor.service
rm -f $(DESTDIR)$(libexecdir)/snapd/snapd-apparmor
endif
# Tests use C.UTF-8 because some some code depend on this for fancy Unicode
# output that unit tests do not mock.
.PHONY: check
check:
LC_ALL=C.UTF-8 go test $(GO_MOD) $(if $(GO_TAGS),-tags "$(GO_TAGS)") $(import_path)/...
.PHONY: clean
clean:
rm -f $(go_binaries)
# Check that production builds contain only the expected trusted account keys.
# This verifies that test keys are not accidentally included in production builds.
# builddir: the directory containing the built binaries (e.g., _build/bin)
.PHONY: check-trusted-account-keys
check-trusted-account-keys:
@echo "Checking trusted account keys in snapd and related binaries..."
@# Check snapd binary (2 keys expected)
@if [ ! -f "$(builddir)/snapd" ]; then \
echo "ERROR: snapd binary not found at $(builddir)/snapd" >&2; \
exit 1; \
fi
@if true; then \
count=$$(strings $(builddir)/snapd | grep -c -E "public-key-sha3-384: [a-zA-Z0-9_-]{64}"); \
if [ "$$count" -ne 2 ]; then \
echo "ERROR: Expected 2 public keys in snapd, found $$count" >&2; \
exit 1; \
fi; \
strings $(builddir)/snapd | grep -q "^public-key-sha3-384: $(SNAPD_STORE_ROOT_KEY)$$" || \
{ echo "ERROR: snapd store root key not found" >&2; exit 1; }; \
strings $(builddir)/snapd | grep -q "^public-key-sha3-384: $(SNAPD_STORE_GENERIC_MODELS_KEY)$$" || \
{ echo "ERROR: snapd store generic models key not found" >&2; exit 1; }; \
echo " snapd: OK (2 keys)"; \
fi
@# Check snap binary (2 keys expected)
@if [ ! -f "$(builddir)/snap" ]; then \
echo "ERROR: snap binary not found at $(builddir)/snap" >&2; \
exit 1; \
fi
@if true; then \
count=$$(strings $(builddir)/snap | grep -c -E "public-key-sha3-384: [a-zA-Z0-9_-]{64}"); \
if [ "$$count" -ne 2 ]; then \
echo "ERROR: Expected 2 public keys in snap, found $$count" >&2; \
exit 1; \
fi; \
strings $(builddir)/snap | grep -q "^public-key-sha3-384: $(SNAPD_STORE_ROOT_KEY)$$" || \
{ echo "ERROR: snap store root key not found" >&2; exit 1; }; \
strings $(builddir)/snap | grep -q "^public-key-sha3-384: $(SNAPD_STORE_GENERIC_MODELS_KEY)$$" || \
{ echo "ERROR: snap store generic models key not found" >&2; exit 1; }; \
echo " snap: OK (2 keys)"; \
fi
@# Check snap-bootstrap if it exists (Ubuntu 16.04+)
@if [ -f "$(builddir)/snap-bootstrap" ]; then \
count=$$(strings $(builddir)/snap-bootstrap | grep -c -E "public-key-sha3-384: [a-zA-Z0-9_-]{64}"); \
if [ "$$count" -ne 2 ]; then \
echo "ERROR: Expected 2 public keys in snap-bootstrap, found $$count" >&2; \
exit 1; \
fi; \
strings $(builddir)/snap-bootstrap | grep -q "^public-key-sha3-384: $(SNAPD_STORE_ROOT_KEY)$$" || \
{ echo "ERROR: snap-bootstrap store root key not found" >&2; exit 1; }; \
strings $(builddir)/snap-bootstrap | grep -q "^public-key-sha3-384: $(SNAPD_STORE_GENERIC_MODELS_KEY)$$" || \
{ echo "ERROR: snap-bootstrap store generic models key not found" >&2; exit 1; }; \
echo " snap-bootstrap: OK (2 keys)"; \
fi
@# Check snap-preseed if it exists (Ubuntu 16.04+)
@if [ -f "$(builddir)/snap-preseed" ]; then \
count=$$(strings $(builddir)/snap-preseed | grep -c -E "public-key-sha3-384: [a-zA-Z0-9_-]{64}"); \
if [ "$$count" -ne 2 ]; then \
echo "ERROR: Expected 2 public keys in snap-preseed, found $$count" >&2; \
exit 1; \
fi; \
strings $(builddir)/snap-preseed | grep -q "^public-key-sha3-384: $(SNAPD_STORE_ROOT_KEY)$$" || \
{ echo "ERROR: snap-preseed store root key not found" >&2; exit 1; }; \
strings $(builddir)/snap-preseed | grep -q "^public-key-sha3-384: $(SNAPD_STORE_GENERIC_MODELS_KEY)$$" || \
{ echo "ERROR: snap-preseed store generic models key not found" >&2; exit 1; }; \
echo " snap-preseed: OK (2 keys)"; \
fi
@# Check snap-repair (3 keys expected: 2 common + 1 repair-root)
@if [ -f "$(builddir)/snap-repair" ]; then \
count=$$(strings $(builddir)/snap-repair | grep -c -E "public-key-sha3-384: [a-zA-Z0-9_-]{64}"); \
if [ "$$count" -ne 3 ]; then \
echo "ERROR: Expected 3 public keys in snap-repair, found $$count" >&2; \
exit 1; \
fi; \
strings $(builddir)/snap-repair | grep -q "^public-key-sha3-384: $(SNAPD_STORE_ROOT_KEY)$$" || \
{ echo "ERROR: snap-repair store root key not found" >&2; exit 1; }; \
strings $(builddir)/snap-repair | grep -q "^public-key-sha3-384: $(SNAPD_STORE_GENERIC_MODELS_KEY)$$" || \
{ echo "ERROR: snap-repair store generic models key not found" >&2; exit 1; }; \
strings $(builddir)/snap-repair | grep -q "^public-key-sha3-384: $(SNAPD_REPAIR_ROOT_KEY)$$" || \
{ echo "ERROR: snap-repair repair-root key not found" >&2; exit 1; }; \
echo " snap-repair: OK (3 keys)"; \
fi
@echo "All trusted account key checks passed."