summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.asm-headers11
-rw-r--r--scripts/Makefile.btf4
-rw-r--r--scripts/Makefile.build8
-rw-r--r--scripts/Makefile.vmlinux_o3
-rw-r--r--scripts/basic/fixdep.c10
-rwxr-xr-xscripts/checkpatch.pl14
-rwxr-xr-xscripts/coccicheck4
-rw-r--r--scripts/coccinelle/api/alloc/alloc_cast.cocci43
-rw-r--r--scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci17
-rw-r--r--scripts/coccinelle/api/alloc/zalloc-simple.cocci41
-rw-r--r--scripts/coccinelle/api/atomic_as_refcounter.cocci4
-rw-r--r--scripts/coccinelle/api/kfree_mismatch.cocci12
-rw-r--r--scripts/coccinelle/free/devm_free.cocci15
-rw-r--r--scripts/coccinelle/free/ifnulldev_put.cocci12
-rw-r--r--scripts/coccinelle/free/pci_free_consistent.cocci53
-rw-r--r--scripts/coccinelle/hid/ff_race.cocci34
-rw-r--r--scripts/coccinelle/locks/double_lock.cocci15
-rw-r--r--scripts/coccinelle/locks/mini_lock.cocci24
-rw-r--r--scripts/coccinelle/misc/minmax.cocci60
-rw-r--r--scripts/coccinelle/misc/struct_size.cocci8
-rwxr-xr-xscripts/config44
-rwxr-xr-xscripts/crypto/gen-aead-testvecs.py69
-rwxr-xr-xscripts/crypto/gen-fips-testvecs.py164
-rwxr-xr-xscripts/dtc/dt-check-style149
-rw-r--r--scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dts32
-rw-r--r--scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dts25
-rw-r--r--scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dts33
-rw-r--r--scripts/dtc/dt-style-selftest/bad/dts-mixed-indent.dts21
-rw-r--r--scripts/dtc/dt-style-selftest/bad/dts-property-order.dts43
-rw-r--r--scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml31
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dts.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dts.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt9
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt6
-rw-r--r--scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt3
-rw-r--r--scripts/dtc/dt-style-selftest/expected/yaml-prop-order-device-type.yaml.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt2
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-child-name-order.dts32
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts43
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-dtc.dts21
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dts25
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dts33
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-preprocessor.dts21
-rw-r--r--scripts/dtc/dt-style-selftest/good/dts-property-order.dts41
-rw-r--r--scripts/dtc/dt-style-selftest/good/soc.dtsi49
-rw-r--r--scripts/gdb/linux/page_owner.py4
-rwxr-xr-xscripts/headers_install.sh1
-rw-r--r--scripts/kallsyms.c4
-rw-r--r--scripts/kconfig/conf.c17
-rw-r--r--scripts/kconfig/expr.c33
-rw-r--r--scripts/kconfig/expr.h5
-rw-r--r--scripts/kconfig/menu.c10
-rwxr-xr-xscripts/kconfig/merge_config.sh2
-rwxr-xr-xscripts/link-vmlinux.sh22
-rwxr-xr-xscripts/livepatch/klp-build14
-rwxr-xr-xscripts/min-tool-version.sh2
-rw-r--r--scripts/mod/modpost.c119
-rw-r--r--scripts/mod/modpost.h8
-rw-r--r--scripts/module.lds.S5
-rw-r--r--scripts/nsdeps2
-rw-r--r--scripts/package/kernel.spec11
-rwxr-xr-xscripts/rust_is_available.sh14
-rw-r--r--scripts/rust_is_available_bindgen_libclang_22.h5
-rwxr-xr-xscripts/rust_is_available_test.py46
-rw-r--r--scripts/rustdoc_test_gen.rs29
-rw-r--r--scripts/sbom/sbom/cmd_graph/savedcmd_parser/savedcmd_parser.py2
-rw-r--r--scripts/sbom/tests/cmd_graph/test_savedcmd_parser.py25
-rw-r--r--scripts/sorttable.c11
-rw-r--r--scripts/syscall.tbl1
-rwxr-xr-xscripts/tags.sh42
73 files changed, 1332 insertions, 402 deletions
diff --git a/scripts/Makefile.asm-headers b/scripts/Makefile.asm-headers
index 8a4856e74180..b38931314ad7 100644
--- a/scripts/Makefile.asm-headers
+++ b/scripts/Makefile.asm-headers
@@ -48,14 +48,13 @@ syscall-y := $(addprefix $(obj)/, $(syscall-y))
generated-y := $(addprefix $(obj)/, $(generated-y))
# Remove stale wrappers when the corresponding files are removed from generic-y
-old-headers := $(wildcard $(obj)/*.h)
+old-headers := $(shell test -d $(obj) && find $(obj) -name *.h)
unwanted := $(filter-out $(generic-y) $(generated-y) $(syscall-y),$(old-headers))
-quiet_cmd_wrap = WRAP $@
- cmd_wrap = echo "\#include <asm-generic/$*.h>" > $@
+filechk_wrap = echo "\#include <asm-generic/$*.h>"
quiet_cmd_remove = REMOVE $(unwanted)
- cmd_remove = rm -f $(unwanted)
+ cmd_remove = rm -f $(unwanted); find $(obj) -type d -empty -delete
quiet_cmd_syshdr = SYSHDR $@
cmd_syshdr = $(CONFIG_SHELL) $(syshdr) \
@@ -74,8 +73,8 @@ all: $(generic-y) $(syscall-y)
$(if $(unwanted),$(call cmd,remove))
@:
-$(obj)/%.h: $(srctree)/$(generic)/%.h
- $(call cmd,wrap)
+$(obj)/%.h: $(srctree)/$(generic)/%.h FORCE
+ $(call filechk,wrap)
$(obj)/unistd_%.h: $(syscalltbl) $(syshdr) FORCE
$(call if_changed,syshdr)
diff --git a/scripts/Makefile.btf b/scripts/Makefile.btf
index e66e13e79653..a1812985a61a 100644
--- a/scripts/Makefile.btf
+++ b/scripts/Makefile.btf
@@ -14,9 +14,7 @@ pahole-flags-$(call test-ge, $(pahole-ver), 125) += --skip_encoding_btf_inconsis
else
# Switch to using --btf_features for v1.26 and later.
-pahole-flags-$(call test-ge, $(pahole-ver), 126) = -j$(JOBS) --btf_features=encode_force,var,float,enum64,decl_tag,type_tag,optimized_func,consistent_func,decl_tag_kfuncs
-
-pahole-flags-$(call test-ge, $(pahole-ver), 130) += --btf_features=attributes
+pahole-flags-$(call test-ge, $(pahole-ver), 126) = -j$(JOBS) --btf_features=encode_force,var,float,enum64,decl_tag,type_tag,optimized_func,consistent_func
pahole-flags-$(call test-ge, $(pahole-ver), 131) += --btf_features=layout
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 911745743246..4349108e75e1 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -28,6 +28,7 @@ ldflags-y :=
subdir-asflags-y :=
subdir-ccflags-y :=
+subdir-rustflags-y :=
# Read auto.conf if it exists, otherwise ignore
-include $(objtree)/include/config/auto.conf
@@ -159,10 +160,10 @@ targets += $(targets-for-builtin) $(targets-for-modules)
# Linus' kernel sanity checking tool
ifeq ($(KBUILD_CHECKSRC),1)
- quiet_cmd_checksrc = CHECK $<
+ quiet_cmd_checksrc = CHECK $(patsubst $(srctree)/%,%,$<)
cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
else ifeq ($(KBUILD_CHECKSRC),2)
- quiet_cmd_force_checksrc = CHECK $<
+ quiet_cmd_force_checksrc = CHECK $(patsubst $(srctree)/%,%,$<)
cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $<
endif
@@ -346,7 +347,8 @@ quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
$(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
$(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
- $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
+ $(CC) $(CLANG_FLAGS) $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS)) \
+ $(CC_FLAGS_RUST_INLINE_HELPERS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@ \
$(cmd_ld_single)) \
$(cmd_objtool)
diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o
index 527352c222ff..24a3a4fd271c 100644
--- a/scripts/Makefile.vmlinux_o
+++ b/scripts/Makefile.vmlinux_o
@@ -47,6 +47,9 @@ endif
vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \
$(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
+# Only used for builds initiated by klp-build
+vmlinux-objtool-args-$(if $(KLP_SYMIDS),y) += --klp-symids
+
objtool-args = $(vmlinux-objtool-args-y) --link
# Link of vmlinux.o used for section mismatch analysis
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index cdd5da7e009b..54063d980442 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -15,13 +15,13 @@
* gcc produces a very nice and correct list of dependencies which
* tells make when to remake a file.
*
- * To use this list as-is however has the drawback that virtually
+ * However, to use this list as-is has the drawback that virtually
* every file in the kernel includes autoconf.h.
*
* If the user re-runs make *config, autoconf.h will be
* regenerated. make notices that and will rebuild every file which
* includes autoconf.h, i.e. basically all files. This is extremely
- * annoying if the user just changed CONFIG_HIS_DRIVER from n to m.
+ * annoying if the user just changed CONFIG_USER_DRIVER from n to m.
*
* So we play the same trick that "mkdep" played before. We replace
* the dependency on autoconf.h by a dependency on every config
@@ -33,9 +33,9 @@
* which then let make pick up the changes and the files that use
* the config symbols are rebuilt.
*
- * So if the user changes his CONFIG_HIS_DRIVER option, only the objects
- * which depend on "include/config/HIS_DRIVER" will be rebuilt,
- * so most likely only his driver ;-)
+ * So if the user changes their CONFIG_USER_DRIVER option, only the objects
+ * which depend on "include/config/USER_DRIVER" will be rebuilt,
+ * so most likely only the user's driver ;-)
*
* The idea above dates, by the way, back to Michael E Chastain, AFAIK.
*
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2b7a42bbdd94..8a7787d228a6 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3124,11 +3124,12 @@ sub process {
}
}
- # Assisted-by uses AGENT_NAME:MODEL_VERSION format, not email
+ # Assisted-by uses a free-form value (e.g. "LLM"), not an
+ # email address, so skip the email format checks below.
if ($sign_off =~ /^Assisted-by:/i) {
- if ($email !~ /^\S+:\S+/) {
+ if ($email =~ /^\s*$/) {
WARN("BAD_SIGN_OFF",
- "Assisted-by expects 'AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]' format\n" . $herecurr);
+ "Assisted-by requires a value\n" . $herecurr);
}
next;
}
@@ -3781,6 +3782,12 @@ sub process {
my $vp_file = $dt_path . "vendor-prefixes.yaml";
foreach my $compat (@compats) {
+ # Skip ID-based PCI and USB compatible patterns.
+ # DT validation will check them properly.
+ next if $compat =~ /^pciclass,/;
+ next if $compat =~ /^pci[a-f0-9]{2,4},/;
+ next if $compat =~ /^usb(if)?[a-f0-9]{1,4},/;
+
my $compat2 = $compat;
$compat2 =~ s/\,[a-zA-Z0-9]*\-/\,<\.\*>\-/;
my $compat3 = $compat;
@@ -4148,6 +4155,7 @@ sub process {
$line =~ /^\+[a-z_]*init/ ||
$line =~ /^\+\s*(?:static\s+)?[A-Z_]*ATTR/ ||
$line =~ /^\+\s*DECLARE/ ||
+ $line =~ /^\+\s*NOKPROBE_SYMBOL/ ||
$line =~ /^\+\s*builtin_[\w_]*driver/ ||
$line =~ /^\+\s*__setup/)) {
if (CHK("LINE_SPACING",
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 8dd766009de1..a0a0e0f72bc7 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -11,7 +11,7 @@ DIR="$(dirname $(readlink -f $0))/.."
SPATCH="`which ${SPATCH:=spatch}`"
if [ ! -x "$SPATCH" ]; then
- echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
+ echo 'spatch is part of the Coccinelle project and is available at https://coccinelle.gitlabpages.inria.fr/website'
exit 1
fi
@@ -229,7 +229,7 @@ coccinelle () {
echo " in $FILE."
echo ''
echo ' More information about semantic patching is available at'
- echo ' http://coccinelle.lip6.fr/'
+ echo ' https://coccinelle.gitlabpages.inria.fr/website'
echo ''
if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then
diff --git a/scripts/coccinelle/api/alloc/alloc_cast.cocci b/scripts/coccinelle/api/alloc/alloc_cast.cocci
index f6f0ccdb6409..a4b83cc8ea01 100644
--- a/scripts/coccinelle/api/alloc/alloc_cast.cocci
+++ b/scripts/coccinelle/api/alloc/alloc_cast.cocci
@@ -20,6 +20,24 @@ virtual patch
virtual org
virtual report
+@m1@
+identifier i;
+expression e;
+type T;
+position p1;
+@@
+
+#define i (T@p1 *)e
+
+@m2@
+identifier i;
+expression e;
+type T;
+position p2;
+@@
+
+#define i(...) (T@p2 *)e
+
@initialize:python@
@@
import re
@@ -28,15 +46,15 @@ m = re.compile(pattern)
@r1 depends on context || patch@
type T;
+position p != {m1.p1,m2.p2};
@@
- (T *)
+ (T@p *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
- kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
- pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
- kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
+ kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|
+ vmalloc_node\|vzalloc_node\)(...)
//----------------------------------------------------------
// For context mode
@@ -57,9 +75,8 @@ type r1.T;
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
- kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
- pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
- kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
+ kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|
+ vmalloc_node\|vzalloc_node\)(...)
//----------------------------------------------------------
// For patch mode
@@ -80,9 +97,8 @@ type r1.T;
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
- kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
- pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
- kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
+ kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|
+ vmalloc_node\|vzalloc_node\)(...)
//----------------------------------------------------------
// For org and report mode
@@ -90,16 +106,15 @@ type r1.T;
@r2 depends on org || report@
type T;
-position p;
+position p != {m1.p1,m2.p2};
@@
(T@p *)
\(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
- kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
- pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
- kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
+ kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|
+ vmalloc_node\|vzalloc_node\)(...)
@script:python depends on org@
p << r2.p;
diff --git a/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
index 9c61a23b34db..07af8c7433d1 100644
--- a/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
+++ b/scripts/coccinelle/api/alloc/pool_zalloc-simple.cocci
@@ -5,7 +5,7 @@
// Copyright: (C) 2015 Intel Corp.
// Options: --no-includes --include-headers
//
-// Keywords: dma_pool_zalloc, pci_pool_zalloc
+// Keywords: dma_pool_zalloc
//
virtual context
@@ -22,7 +22,7 @@ expression x;
statement S;
@@
-* x = \(dma_pool_alloc\|pci_pool_alloc\)(...);
+* x = dma_pool_alloc(...);
if ((x==NULL) || ...) S
* memset(x,0, ...);
@@ -41,17 +41,6 @@ statement S;
if ((x==NULL) || ...) S
- memset(x,0,...);
-@depends on patch@
-expression x;
-expression a,b,c;
-statement S;
-@@
-
-- x = pci_pool_alloc(a,b,c);
-+ x = pci_pool_zalloc(a,b,c);
- if ((x==NULL) || ...) S
-- memset(x,0,...);
-
//----------------------------------------------------------
// For org and report mode
//----------------------------------------------------------
@@ -63,7 +52,7 @@ statement S;
position p;
@@
- x = @p\(dma_pool_alloc\|pci_pool_alloc\)(a,b,c);
+ x =@p dma_pool_alloc(a,b,c);
if ((x==NULL) || ...) S
memset(x,0, ...);
diff --git a/scripts/coccinelle/api/alloc/zalloc-simple.cocci b/scripts/coccinelle/api/alloc/zalloc-simple.cocci
index d66c45356691..ae1d39e71e31 100644
--- a/scripts/coccinelle/api/alloc/zalloc-simple.cocci
+++ b/scripts/coccinelle/api/alloc/zalloc-simple.cocci
@@ -35,7 +35,7 @@ statement S;
@@
* x = (T)\(kmalloc(E1, ...)\|vmalloc(E1)\|dma_alloc_coherent(...,E1,...)\|
- kmalloc_node(E1, ...)\|kmem_cache_alloc(...)\|kmem_alloc(E1, ...)\|
+ kmalloc_node(E1, ...)\|kmem_cache_alloc(...)\|
devm_kmalloc(...,E1,...)\|kvmalloc(E1, ...)\|kvmalloc_node(E1,...)\);
if ((x==NULL) || ...) S
* memset((T2)x,0,E1);
@@ -88,15 +88,6 @@ statement S;
- x = (T)kmem_cache_alloc(E3,E4);
+ x = (T)kmem_cache_zalloc(E3,E4);
|
-- x = kmem_alloc(E1,E2);
-+ x = kmem_zalloc(E1,E2);
-|
-- x = (T *)kmem_alloc(E1,E2);
-+ x = kmem_zalloc(E1,E2);
-|
-- x = (T)kmem_alloc(E1,E2);
-+ x = (T)kmem_zalloc(E1,E2);
-|
- x = devm_kmalloc(E2,E1,E3);
+ x = devm_kzalloc(E2,E1,E3);
|
@@ -291,36 +282,6 @@ msg="WARNING: kmem_cache_zalloc should be used for %s, instead of kmem_cache_all
coccilib.report.print_report(p[0], msg)
//-----------------------------------------------------------------
-@r5 depends on org || report@
-type T, T2;
-expression x;
-expression E1,E2;
-statement S;
-position p;
-@@
-
- x = (T)kmem_alloc@p(E1,E2);
- if ((x==NULL) || ...) S
- memset((T2)x,0,E1);
-
-@script:python depends on org@
-p << r5.p;
-x << r5.x;
-@@
-
-msg="%s" % (x)
-msg_safe=msg.replace("[","@(").replace("]",")")
-coccilib.org.print_todo(p[0], msg_safe)
-
-@script:python depends on report@
-p << r5.p;
-x << r5.x;
-@@
-
-msg="WARNING: kmem_zalloc should be used for %s, instead of kmem_alloc/memset" % (x)
-coccilib.report.print_report(p[0], msg)
-
-//-----------------------------------------------------------------
@r6 depends on org || report@
type T, T2;
expression x;
diff --git a/scripts/coccinelle/api/atomic_as_refcounter.cocci b/scripts/coccinelle/api/atomic_as_refcounter.cocci
index bbe5b2932933..af82b9e094aa 100644
--- a/scripts/coccinelle/api/atomic_as_refcounter.cocci
+++ b/scripts/coccinelle/api/atomic_as_refcounter.cocci
@@ -27,8 +27,6 @@ identifier fname6 =~ ".*call_rcu.*";
|
atomic_dec_and_lock@p1(&(a)->x, ...)
|
- atomic_long_dec_and_lock@p1(&(a)->x, ...)
-|
atomic_long_dec_and_test@p1(&(a)->x)
|
atomic64_dec_and_test@p1(&(a)->x)
@@ -70,8 +68,6 @@ identifier fname =~ ".*free.*";
|
atomic_dec_and_lock@p1(&(a)->x, ...)
|
- atomic_long_dec_and_lock@p1(&(a)->x, ...)
-|
atomic_long_dec_and_test@p1(&(a)->x)
|
atomic64_dec_and_test@p1(&(a)->x)
diff --git a/scripts/coccinelle/api/kfree_mismatch.cocci b/scripts/coccinelle/api/kfree_mismatch.cocci
index d46a9b3eb7b3..bc90d0c071ac 100644
--- a/scripts/coccinelle/api/kfree_mismatch.cocci
+++ b/scripts/coccinelle/api/kfree_mismatch.cocci
@@ -29,7 +29,7 @@ position kok, vok;
} else {
...
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|
- vzalloc_node\|vmalloc_exec\|vmalloc_32\|
+ vzalloc_node\|vmalloc_32\|
vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|
__vmalloc_node\)(...)@vok
...
@@ -42,7 +42,7 @@ position kok, vok;
if (E == NULL) {
...
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|
- vzalloc_node\|vmalloc_exec\|vmalloc_32\|
+ vzalloc_node\|vmalloc_32\|
vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|
__vmalloc_node\)(...)@vok
...
@@ -68,7 +68,7 @@ position f != free.fok;
* E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|
* kzalloc_node\|kmalloc_array\|kmalloc_array_node\|
* kcalloc_node\)(...)@a
- ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
+ ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
when != is_vmalloc_addr(E)
when any
* \(vfree\|vfree_atomic\|kvfree\)(E)@f
@@ -82,7 +82,7 @@ position f != free.fok;
E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|
kzalloc_node\|kmalloc_array\|kmalloc_array_node\|
kcalloc_node\)(...)@a
- ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
+ ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... }
when != is_vmalloc_addr(E)
when any
- \(vfree\|vfree_atomic\|kvfree\)(E)@f
@@ -95,7 +95,7 @@ position f != free.fok;
@@
* E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|
-* vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|
+* vmalloc_32\|vmalloc_32_user\|__vmalloc\|
* __vmalloc_node_range\|__vmalloc_node\)(...)@a
... when != is_vmalloc_addr(E)
when any
@@ -108,7 +108,7 @@ position f != free.fok;
@@
E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|
- vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|
+ vmalloc_32\|vmalloc_32_user\|__vmalloc\|
__vmalloc_node_range\|__vmalloc_node\)(...)@a
... when != is_vmalloc_addr(E)
when any
diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci
index 0880729badbc..947d7e685655 100644
--- a/scripts/coccinelle/free/devm_free.cocci
+++ b/scripts/coccinelle/free/devm_free.cocci
@@ -26,7 +26,8 @@ virtual report
virtual context
@r depends on context || org || report@
-expression x;
+type T;
+T x;
@@
(
@@ -56,19 +57,27 @@ expression x;
)
@safe depends on context || org || report exists@
-expression x;
+r.T x;
position p;
@@
(
x = kmalloc(...)
|
+ x = kmalloc_obj(...)
+|
+ x = kmalloc_objs(...)
+|
x = kvasprintf(...)
|
x = kasprintf(...)
|
x = kzalloc(...)
|
+ x = kzalloc_obj(...)
+|
+ x = kzalloc_objs(...)
+|
x = kmalloc_array(...)
|
x = kcalloc(...)
@@ -105,7 +114,7 @@ position p;
)
@pb@
-expression r.x;
+r.T r.x;
position p != safe.p;
@@
diff --git a/scripts/coccinelle/free/ifnulldev_put.cocci b/scripts/coccinelle/free/ifnulldev_put.cocci
index 2bd2e8fae485..1430d68ff268 100644
--- a/scripts/coccinelle/free/ifnulldev_put.cocci
+++ b/scripts/coccinelle/free/ifnulldev_put.cocci
@@ -23,13 +23,13 @@ expression E;
|
dev_put(E);
|
- dev_put_track(E, ...);
+ netdev_put(E, ...);
|
__dev_hold(E);
|
dev_hold(E);
|
- dev_hold_track(E, ...);
+ netdev_hold(E, ...);
)
@r depends on context || report || org @
@@ -38,18 +38,18 @@ position p;
@@
* if (E != NULL)
-* \(__dev_put@p\|dev_put@p\|dev_put_track@p\|__dev_hold@p\|dev_hold@p\|
-* dev_hold_track@p\)(E, ...);
+* \(__dev_put@p\|dev_put@p\|netdev_put@p\|__dev_hold@p\|dev_hold@p\|
+* netdev_hold@p\)(E, ...);
@script:python depends on org@
p << r.p;
@@
-cocci.print_main("NULL check before dev_{put, hold} functions is not needed", p)
+cocci.print_main("NULL check before (net)dev_{put, hold} functions is not needed", p)
@script:python depends on report@
p << r.p;
@@
-msg = "WARNING: NULL check before dev_{put, hold} functions is not needed."
+msg = "WARNING: NULL check before (net)dev_{put, hold} functions is not needed."
coccilib.report.print_report(p[0], msg)
diff --git a/scripts/coccinelle/free/pci_free_consistent.cocci b/scripts/coccinelle/free/pci_free_consistent.cocci
deleted file mode 100644
index e062b9ba09ff..000000000000
--- a/scripts/coccinelle/free/pci_free_consistent.cocci
+++ /dev/null
@@ -1,53 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/// Find missing pci_free_consistent for every pci_alloc_consistent.
-///
-// Confidence: Moderate
-// Copyright: (C) 2013 Petr Strnad.
-// URL: https://coccinelle.gitlabpages.inria.fr/website
-// Keywords: pci_free_consistent, pci_alloc_consistent
-// Options: --no-includes --include-headers
-
-virtual report
-virtual org
-
-@search@
-local idexpression id;
-expression x,y,z,e;
-position p1,p2;
-type T;
-@@
-
-id = pci_alloc_consistent@p1(x,y,&z)
-... when != e = id
-if (id == NULL || ...) { ... return ...; }
-... when != pci_free_consistent(x,y,id,z)
- when != if (id) { ... pci_free_consistent(x,y,id,z) ... }
- when != if (y) { ... pci_free_consistent(x,y,id,z) ... }
- when != e = (T)id
- when exists
-(
-return 0;
-|
-return 1;
-|
-return id;
-|
-return@p2 ...;
-)
-
-@script:python depends on report@
-p1 << search.p1;
-p2 << search.p2;
-@@
-
-msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line)
-coccilib.report.print_report(p2[0],msg)
-
-@script:python depends on org@
-p1 << search.p1;
-p2 << search.p2;
-@@
-
-msg = "ERROR: missing pci_free_consistent; pci_alloc_consistent on line %s and return without freeing on line %s" % (p1[0].line,p2[0].line)
-cocci.print_main(msg,p1)
-cocci.print_secs("",p2)
diff --git a/scripts/coccinelle/hid/ff_race.cocci b/scripts/coccinelle/hid/ff_race.cocci
new file mode 100644
index 000000000000..479f5d1e3184
--- /dev/null
+++ b/scripts/coccinelle/hid/ff_race.cocci
@@ -0,0 +1,34 @@
+/// Detect HID drivers that initialize force-feedback after hid_hw_start()
+/// when HID_CONNECT_HIDINPUT is used. This is a lifecycle violation as
+/// the input device is already registered.
+//
+// Confidence: High
+// Copyright: (C) 2026 Gemini. GPLv2.
+
+virtual report
+
+@r@
+identifier probe_fn;
+expression hdev, flags;
+position p1, p2;
+@@
+
+probe_fn(struct hid_device *hdev, ...) {
+ <...
+ hid_hw_start@p1(hdev, flags)
+ ...
+ \(input_ff_create\|input_ff_create_memless\)@p2(...)
+ ...>
+}
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+flags << r.flags;
+@@
+
+# Check if flags include HID_CONNECT_HIDINPUT (0x01) or HID_CONNECT_DEFAULT (0x0f)
+# Note: HID_CONNECT_DEFAULT is 0x0f, HID_CONNECT_HIDINPUT is 0x01
+if "HID_CONNECT_HIDINPUT" in flags or "HID_CONNECT_DEFAULT" in flags:
+ msg = "WARNING: force-feedback initialized after hid_hw_start() with HID_CONNECT_HIDINPUT. Input device is already registered at this point. Use .input_configured() instead."
+ coccilib.report.print_report(p2[0], msg)
diff --git a/scripts/coccinelle/locks/double_lock.cocci b/scripts/coccinelle/locks/double_lock.cocci
index 619cfc714409..381060849a7b 100644
--- a/scripts/coccinelle/locks/double_lock.cocci
+++ b/scripts/coccinelle/locks/double_lock.cocci
@@ -38,7 +38,20 @@ write_lock@p1
write_trylock@p1
) (E1@p,...);
-@balanced@
+@r_candidate exists@
+expression x <= locked.E1;
+expression locked.E1;
+expression E2;
+identifier lock;
+position locked.p,p1,p2;
+@@
+
+lock@p1 (E1@p,...);
+... when != E1
+ when != \(x = E2\|&x\)
+lock@p2 (E1,...);
+
+@balanced depends on r_candidate@
position p1 != locked.p1;
position locked.p;
identifier lock,unlock;
diff --git a/scripts/coccinelle/locks/mini_lock.cocci b/scripts/coccinelle/locks/mini_lock.cocci
index 71065d8a5d54..c65241c895ff 100644
--- a/scripts/coccinelle/locks/mini_lock.cocci
+++ b/scripts/coccinelle/locks/mini_lock.cocci
@@ -53,11 +53,31 @@ spin_lock_irq@p1
spin_lock_irqsave@p1
) (E1@p,...);
-@looped@
+@err_candidate exists@
+expression E1;
+position prelocked.p;
+position up != prelocked.p1;
+position rc;
+identifier lock,unlock;
+@@
+
+lock(E1@p,...);
+... when != E1
+ when any
+if (...) {
+ ... when != E1
+ return@rc ...;
+}
+... when != E1
+ when any
+unlock@up(E1,...);
+
+@looped exists@
+position err_candidate.rc;
position r;
@@
-for(...;...;...) { <+... return@r ...; ...+> }
+for(...;...;...) { <+... return@rc@r ...; ...+> }
@err exists@
expression E1;
diff --git a/scripts/coccinelle/misc/minmax.cocci b/scripts/coccinelle/misc/minmax.cocci
index ca4830ae3042..b83d4a01e47a 100644
--- a/scripts/coccinelle/misc/minmax.cocci
+++ b/scripts/coccinelle/misc/minmax.cocci
@@ -17,7 +17,21 @@ virtual org
virtual context
virtual patch
-@rmax depends on !patch@
+@max_candidate disable not_int1, not_int2, neg_if_exp@
+expression E1, E2, E3, E4;
+binary operator cmp = {>, >=};
+@@
+
+ E1 cmp E2 ? E3 : E4
+
+@min_candidate disable not_int1, not_int2, neg_if_exp@
+expression E1, E2, E3, E4;
+binary operator cmp = {<, <=};
+@@
+
+ E1 cmp E2 ? E3 : E4
+
+@rmax depends on !patch && max_candidate disable not_int1, not_int2, neg_if_exp@
identifier func;
expression x, y;
binary operator cmp = {>, >=};
@@ -27,11 +41,23 @@ position p;
func(...)
{
<...
-* ((x) cmp@p (y) ? (x) : (y))
+* (x) cmp@p (y) ? (x) : (y)
...>
}
-@rmaxif depends on !patch@
+@maxif_candidate disable not_int1, not_int2, neg_if@
+expression x, y;
+expression max_val;
+binary operator cmp = {>, >=};
+@@
+
+if ((x) cmp (y)) {
+ max_val = (x);
+} else {
+ max_val = (y);
+}
+
+@rmaxif depends on !patch && maxif_candidate disable not_int1, not_int2, neg_if@
identifier func;
expression x, y;
expression max_val;
@@ -51,7 +77,7 @@ func(...)
}
// Ignore errcode returns.
-@errcode@
+@errcode depends on min_candidate disable not_int1, not_int2, neg_if_exp@
position p;
identifier func;
expression x;
@@ -65,7 +91,7 @@ func(...)
...>
}
-@rmin depends on !patch@
+@rmin depends on !patch && min_candidate disable not_int1, not_int2, neg_if_exp@
identifier func;
expression x, y;
binary operator cmp = {<, <=};
@@ -75,11 +101,23 @@ position p != errcode.p;
func(...)
{
<...
-* ((x) cmp@p (y) ? (x) : (y))
+* (x) cmp@p (y) ? (x) : (y)
...>
}
-@rminif depends on !patch@
+@minif_candidate disable not_int1, not_int2, neg_if@
+expression x, y;
+expression min_val;
+binary operator cmp = {<, <=};
+@@
+
+if ((x) cmp (y)) {
+ min_val = (x);
+} else {
+ min_val = (y);
+}
+
+@rminif depends on !patch && minif_candidate disable not_int1, not_int2, neg_if@
identifier func;
expression x, y;
expression min_val;
@@ -98,7 +136,7 @@ func(...)
...>
}
-@pmax depends on patch@
+@pmax depends on patch && max_candidate disable not_int1, not_int2, neg_if_exp@
identifier func;
expression x, y;
binary operator cmp = {>=, >};
@@ -112,7 +150,7 @@ func(...)
...>
}
-@pmaxif depends on patch@
+@pmaxif depends on patch && maxif_candidate disable not_int1, not_int2, neg_if@
identifier func;
expression x, y;
expression max_val;
@@ -131,7 +169,7 @@ func(...)
...>
}
-@pmin depends on patch@
+@pmin depends on patch && min_candidate disable not_int1, not_int2, neg_if_exp@
identifier func;
expression x, y;
binary operator cmp = {<=, <};
@@ -146,7 +184,7 @@ func(...)
...>
}
-@pminif depends on patch@
+@pminif depends on patch && minif_candidate disable not_int1, not_int2, neg_if@
identifier func;
expression x, y;
expression min_val;
diff --git a/scripts/coccinelle/misc/struct_size.cocci b/scripts/coccinelle/misc/struct_size.cocci
index 9b02c37438e4..406884d68d43 100644
--- a/scripts/coccinelle/misc/struct_size.cocci
+++ b/scripts/coccinelle/misc/struct_size.cocci
@@ -29,9 +29,7 @@ f
expression E1, E2;
identifier m;
@@
-(
-* (sizeof(*E1) + (E2 * sizeof(*E1->m)))
-)
+* sizeof(*E1) + (E2 * sizeof(*E1->m))
//----------------------------------------------------------
// For patch mode
@@ -55,9 +53,7 @@ expression E1, E2;
identifier m;
position p;
@@
-(
- (sizeof(*E1)@p + (E2 * sizeof(*E1->m)))
-)
+ sizeof(*E1)@p + (E2 * sizeof(*E1->m))
@script:python depends on org@
p << r.p;
diff --git a/scripts/config b/scripts/config
index ea475c07de28..32428ea909c2 100755
--- a/scripts/config
+++ b/scripts/config
@@ -38,7 +38,7 @@ commands:
options:
--file config-file .config file to change (default .config)
- --keep-case|-k Keep next symbols' case (dont' upper-case it)
+ --keep-case|-k Keep next symbols' case (don't upper-case it)
$myname doesn't check the validity of the .config file. This is done at next
make time.
@@ -71,48 +71,45 @@ txt_append() {
local anchor="$1"
local insert="$2"
local infile="$3"
- local tmpfile="$infile.swp"
# sed append cmd: 'a\' + newline + text + newline
cmd="$(printf "a\\%b$insert" "\n")"
- sed -e "/$anchor/$cmd" "$infile" >"$tmpfile"
- # replace original file with the edited one
- mv "$tmpfile" "$infile"
+ # We don't really need a backup file, but in-place editing with backup
+ # skipped is not portable due to different implementations parsing
+ # arguments in incompatible manners.
+ # Create a backup file anyway to ensure portability. The file will be
+ # deleted on exit.
+ sed -E -i.swp -e "/$anchor/$cmd" "$infile"
+ SED_EDITED=1
}
txt_subst() {
local before="$1"
local after="$2"
local infile="$3"
- local tmpfile="$infile.swp"
- sed -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile" >"$tmpfile"
- # replace original file with the edited one
- mv "$tmpfile" "$infile"
+ sed -E -i.swp -e "s$SED_DELIM$before$SED_DELIM$after$SED_DELIM" "$infile"
+ SED_EDITED=1
}
txt_delete() {
local text="$1"
local infile="$2"
- local tmpfile="$infile.swp"
- sed -e "/$text/d" "$infile" >"$tmpfile"
- # replace original file with the edited one
- mv "$tmpfile" "$infile"
+ sed -E -i.swp -e "/$text/d" "$infile"
+ SED_EDITED=1
}
set_var() {
local name=$1 new=$2 before=$3
- name_re="^($name=|# $name is not set)"
+ name_re="^($name=.*|# $name is not set)"
before_re="^($before=|# $before is not set)"
if test -n "$before" && grep -Eq "$before_re" "$FN"; then
- txt_append "^$before=" "$new" "$FN"
- txt_append "^# $before is not set" "$new" "$FN"
+ txt_append "$before_re" "$new" "$FN"
elif grep -Eq "$name_re" "$FN"; then
- txt_subst "^$name=.*" "$new" "$FN"
- txt_subst "^# $name is not set" "$new" "$FN"
+ txt_subst "$name_re" "$new" "$FN"
else
echo "$new" >>"$FN"
fi
@@ -121,10 +118,17 @@ set_var() {
undef_var() {
local name=$1
- txt_delete "^$name=" "$FN"
- txt_delete "^# $name is not set" "$FN"
+ txt_delete "^($name=|# $name is not set)" "$FN"
}
+SED_EDITED=0
+on_exit() {
+ if [ "$SED_EDITED" -ge 1 ]; then
+ rm -f "$FN.swp"
+ fi
+}
+trap on_exit EXIT
+
FN=.config
CMDS=()
while [[ $# -gt 0 ]]; do
diff --git a/scripts/crypto/gen-aead-testvecs.py b/scripts/crypto/gen-aead-testvecs.py
new file mode 100755
index 000000000000..d77d646f75b5
--- /dev/null
+++ b/scripts/crypto/gen-aead-testvecs.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Script that generates known-good data used in the AEAD tests.
+#
+# Requires that python-cryptography be installed.
+#
+# Copyright 2026 Google LLC
+
+import hashlib
+import sys
+import cryptography.hazmat.primitives.ciphers.aead
+
+
+# Deterministically generate 'length' random bytes.
+def rand_bytes(length):
+ seed = length
+ out = []
+ for _ in range(length):
+ seed = (seed * 25214903917 + 11) % 2**48
+ out.append((seed >> 16) % 256)
+ return bytes(out)
+
+
+# Deterministically generate many different AEAD inputs using exactly the same
+# method that the test uses; encrypt them using an independent implementation of
+# the algorithm; compute the checksum of all the resulting (ciphertext, authtag)
+# pairs concatenated to each other; and print the checksum as a C struct.
+def gen_monte_carlo_checksum(alg):
+ blake2s = hashlib.blake2s()
+ for data_len in range(1025):
+ ad_len = data_len % 293
+ pt = rand_bytes(data_len)
+ ad = rand_bytes(ad_len)
+ if alg == "aes-ccm":
+ key_len = [16, 24, 32][data_len % 3]
+ key = rand_bytes(key_len)
+ nonce = rand_bytes([7, 8, 9, 10, 11, 12, 13][data_len % 7])
+ tag_len = [4, 6, 8, 10, 12, 14, 16][data_len % 7]
+ ccm = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
+ key, tag_length=tag_len
+ )
+ ct_and_tag = ccm.encrypt(nonce, pt, ad)
+ elif alg == "aes-gcm":
+ key_len = [16, 24, 32][data_len % 3]
+ key = rand_bytes(key_len)
+ nonce = rand_bytes(12)
+ tag_len = [4, 8, 12, 13, 14, 15, 16][data_len % 7]
+ gcm = cryptography.hazmat.primitives.ciphers.aead.AESGCM(key)
+ # python-cryptography supports only 16-byte GCM tags. However, in
+ # GCM, shorter tags are simply truncated. Do that below.
+ ct_and_tag = gcm.encrypt(nonce, pt, ad)[: data_len + tag_len]
+
+ blake2s.update(ct_and_tag)
+
+ name = f"{alg.replace('-', '_')}_monte_carlo_checksum"
+ value = blake2s.digest()
+ print(f"static const u8 {name}[BLAKE2S_HASH_SIZE] = {{")
+ for i in range(0, len(value), 11):
+ line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 11])
+ print(f"{line.rstrip()}")
+ print("};")
+
+
+if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm", "aes-gcm"):
+ sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm|aes-gcm]\n")
+ sys.exit(1)
+
+gen_monte_carlo_checksum(sys.argv[1])
diff --git a/scripts/crypto/gen-fips-testvecs.py b/scripts/crypto/gen-fips-testvecs.py
index 9f18bcb97412..b8c8a78cb8a8 100755
--- a/scripts/crypto/gen-fips-testvecs.py
+++ b/scripts/crypto/gen-fips-testvecs.py
@@ -1,46 +1,148 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Script that generates lib/crypto/fips.h
+# Script that generates lib/crypto/fips-aes.h and lib/crypto/fips-sha.h
#
# Requires that python-cryptography be installed.
#
# Copyright 2025 Google LLC
import cryptography.hazmat.primitives.ciphers
+import cryptography.hazmat.primitives.ciphers.aead
import cryptography.hazmat.primitives.cmac
import hashlib
import hmac
-fips_test_data = b"fips test data\0\0"
-fips_test_key = b"fips test key\0\0\0"
-def print_static_u8_array_definition(name, value):
- print('')
- print(f'static const u8 {name}[] __initconst __maybe_unused = {{')
+def print_static_u8_array_definition(file, name, value):
+ print("", file=file)
+ print(f"static const u8 {name}[] __initconst __maybe_unused = {{", file=file)
for i in range(0, len(value), 8):
- line = '\t' + ''.join(f'0x{b:02x}, ' for b in value[i:i+8])
- print(f'{line.rstrip()}')
- print('};')
-
-print('/* SPDX-License-Identifier: GPL-2.0-or-later */')
-print(f'/* This file was generated by: gen-fips-testvecs.py */')
-print()
-print('#include <linux/fips.h>')
-
-print_static_u8_array_definition("fips_test_data", fips_test_data)
-print_static_u8_array_definition("fips_test_key", fips_test_key)
-
-for alg in 'sha1', 'sha256', 'sha512':
- ctx = hmac.new(fips_test_key, digestmod=alg)
- ctx.update(fips_test_data)
- print_static_u8_array_definition(f'fips_test_hmac_{alg}_value', ctx.digest())
-
-print_static_u8_array_definition(f'fips_test_sha3_256_value',
- hashlib.sha3_256(fips_test_data).digest())
-
-aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
-aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
-aes_cmac.update(fips_test_data)
-print_static_u8_array_definition('fips_test_aes_cmac_value',
- aes_cmac.finalize())
+ line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 8])
+ print(f"{line.rstrip()}", file=file)
+ print("};", file=file)
+
+
+def print_header(file):
+ print("/* SPDX-License-Identifier: GPL-2.0-or-later */", file=file)
+ print("/* This file was generated by: gen-fips-testvecs.py */", file=file)
+ print("/* clang-format off */", file=file)
+ print("", file=file)
+ print("#include <linux/fips.h>", file=file)
+
+
+def gen_aes_test_data(file):
+ fips_test_data = b"fips test data\0\0"
+ fips_test_ad = b"fips test ad\0\0\0\0"
+ fips_test_iv = b"fips test iv\0\0\0\0"
+ fips_test_key = b"fips test key\0\0\0"
+ fips_test_xts_key = b"key1" + (b"\0" * 12) + b"key2" + (b"\0" * 12)
+
+ print_header(file)
+ print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
+ print_static_u8_array_definition(file, "fips_test_ad", fips_test_ad)
+ print_static_u8_array_definition(file, "fips_test_iv", fips_test_iv)
+ print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
+ print_static_u8_array_definition(file, "fips_test_xts_key", fips_test_xts_key)
+
+ aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
+
+ # AES-CMAC
+ aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
+ aes_cmac.update(fips_test_data)
+ print_static_u8_array_definition(
+ file, "fips_test_aes_cmac_value", aes_cmac.finalize()
+ )
+
+ # AES-ECB
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.ECB()
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_ecb_ctext", ctext)
+
+ # AES-CBC
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_cbc_ctext", ctext)
+
+ # AES-CBC-CTS
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data * 2) + encryptor.finalize()
+ ctext = ctext[16:32] + ctext[0:16]
+ print_static_u8_array_definition(file, "fips_test_aes_cbc_cts_ctext", ctext)
+
+ # AES-CTR
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CTR(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_ctr_ctext", ctext)
+
+ # AES-XTS
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_xts_key),
+ cryptography.hazmat.primitives.ciphers.modes.XTS(fips_test_iv),
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_xts_ctext", ctext)
+
+ # AES-GCM
+ cipher = cryptography.hazmat.primitives.ciphers.aead.AESGCM(fips_test_key)
+ ct_and_tag = cipher.encrypt(
+ nonce=fips_test_iv[:12], data=fips_test_data, associated_data=fips_test_ad
+ )
+ print_static_u8_array_definition(
+ file, "fips_test_aes_gcm_ctext_and_tag", ct_and_tag
+ )
+
+ # AES-CCM
+ cipher = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
+ fips_test_key, tag_length=16
+ )
+ ct_and_tag = cipher.encrypt(
+ nonce=fips_test_iv[:13], data=fips_test_data, associated_data=fips_test_ad
+ )
+ print_static_u8_array_definition(
+ file, "fips_test_aes_ccm_ctext_and_tag", ct_and_tag
+ )
+
+
+def gen_sha_test_data(file):
+ fips_test_data = b"fips test data\0\0"
+ fips_test_key = b"fips test key\0\0\0"
+
+ print_header(file)
+ print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
+ print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
+
+ for alg in "sha1", "sha256", "sha512":
+ ctx = hmac.new(fips_test_key, digestmod=alg)
+ ctx.update(fips_test_data)
+ print_static_u8_array_definition(
+ file, f"fips_test_hmac_{alg}_value", ctx.digest()
+ )
+
+ print_static_u8_array_definition(
+ file, "fips_test_sha3_256_value", hashlib.sha3_256(fips_test_data).digest()
+ )
+
+
+filename = "lib/crypto/fips-aes.h"
+with open(filename, "w") as file:
+ print(f"Generating {filename}")
+ gen_aes_test_data(file)
+
+filename = "lib/crypto/fips-sha.h"
+with open(filename, "w") as file:
+ print(f"Generating {filename}")
+ gen_sha_test_data(file)
diff --git a/scripts/dtc/dt-check-style b/scripts/dtc/dt-check-style
index 2d5723d41ea3..96deffc0d8a7 100755
--- a/scripts/dtc/dt-check-style
+++ b/scripts/dtc/dt-check-style
@@ -49,6 +49,9 @@ re_cpp_directive = re.compile(
r'^#\s*(include|define|undef|ifdef|ifndef|if|else|elif|endif|'
r'pragma|error|warning)\b')
+re_dtc_directive = re.compile(
+ r'^/(dts-v1|include)/')
+
# label: name@addr { -- label and addr optional; name can be "/"
# Per the DT spec a node name may start with a digit (e.g. 1wire@...).
# The address part is captured loosely (any non-space, non-brace run) so
@@ -66,7 +69,11 @@ re_ref_node = re.compile(
def is_preprocessor(stripped):
"""Tell C preprocessor directives apart from DTS '#'-prefixed props."""
- return re_cpp_directive.match(stripped) is not None
+ if re_cpp_directive.match(stripped) is not None:
+ return True
+ if re_dtc_directive.match(stripped) is not None:
+ return True
+ return False
class DtsLine:
@@ -75,11 +82,12 @@ class DtsLine:
'node_name', 'node_addr', 'label', 'ref_name', 'depth',
'closures')
- def __init__(self, lineno, raw, linetype, indent_str, stripped):
+ def __init__(self, lineno, raw, linetype, depth, indent_str, stripped):
self.lineno = lineno # 1-based within the block
self.raw = raw
self.linetype = linetype
self.indent_str = indent_str # leading whitespace as-is
+ self.depth = depth
self.stripped = stripped
self.prop_name = None
self.continuations = []
@@ -87,7 +95,6 @@ class DtsLine:
self.node_addr = None
self.label = None
self.ref_name = None
- self.depth = 0 # filled in by classify_lines
self.closures = 1 # count of '}' on a NODE_CLOSE line
@@ -155,16 +162,14 @@ def classify_lines(text):
# or a blank line).
if in_cpp_macro:
dl = DtsLine(i, raw, LineType.PREPROCESSOR,
- indent_str, stripped)
- dl.depth = depth
+ depth, indent_str, stripped)
out.append(dl)
in_cpp_macro = (bool(stripped) and
stripped.rstrip().endswith('\\'))
continue
if not stripped:
- dl = DtsLine(i, raw, LineType.BLANK, '', '')
- dl.depth = depth
+ dl = DtsLine(i, raw, LineType.BLANK, depth, '', '')
out.append(dl)
continue
@@ -173,15 +178,13 @@ def classify_lines(text):
else LineType.COMMENT_BODY)
if ltype == LineType.COMMENT_END:
in_block_comment = False
- dl = DtsLine(i, raw, ltype, indent_str, stripped)
- dl.depth = depth
+ dl = DtsLine(i, raw, ltype, depth, indent_str, stripped)
out.append(dl)
continue
- if stripped.startswith('#') and is_preprocessor(stripped):
- dl = DtsLine(i, raw, LineType.PREPROCESSOR,
+ if (stripped.startswith('#') or stripped.startswith('/')) and is_preprocessor(stripped):
+ dl = DtsLine(i, raw, LineType.PREPROCESSOR, depth,
indent_str, stripped)
- dl.depth = depth
out.append(dl)
prev_complete = True
in_cpp_macro = stripped.rstrip().endswith('\\')
@@ -198,14 +201,12 @@ def classify_lines(text):
# structural classification entirely.
if not code:
ltype = LineType.COMMENT_START if opens_block else LineType.COMMENT
- dl = DtsLine(i, raw, ltype, indent_str, stripped)
- dl.depth = depth
+ dl = DtsLine(i, raw, ltype, depth, indent_str, stripped)
out.append(dl)
continue
if not prev_complete:
- dl = DtsLine(i, raw, LineType.CONTINUATION, indent_str, code)
- dl.depth = depth
+ dl = DtsLine(i, raw, LineType.CONTINUATION, depth, indent_str, code)
out.append(dl)
prev_complete = (code.endswith(';') or
code.endswith('{') or
@@ -220,26 +221,23 @@ def classify_lines(text):
if re_only_closures.match(code):
closures = code.count('}')
depth = max(depth - closures, 0)
- dl = DtsLine(i, raw, LineType.NODE_CLOSE, indent_str, code)
- dl.depth = depth
+ dl = DtsLine(i, raw, LineType.NODE_CLOSE, depth, indent_str, code)
dl.closures = closures
out.append(dl)
prev_complete = True
continue
if code.endswith('{'):
- dl = DtsLine(i, raw, LineType.NODE_OPEN, indent_str, code)
+ dl = DtsLine(i, raw, LineType.NODE_OPEN, depth, indent_str, code)
parse_node_header(dl)
- dl.depth = depth
out.append(dl)
depth += 1
prev_complete = True
continue
# Property (or first line of a multi-line property).
- dl = DtsLine(i, raw, LineType.PROPERTY, indent_str, code)
+ dl = DtsLine(i, raw, LineType.PROPERTY, depth, indent_str, code)
parse_property_name(dl)
- dl.depth = depth
out.append(dl)
prev_complete = code.endswith(';')
@@ -311,13 +309,16 @@ def collect_labels_and_refs(text):
class Ctx:
"""Context passed to each rule check. Carries the parsed lines,
- raw text, mode, and indent kind."""
+ raw text, mode and kind."""
- def __init__(self, lines, text, mode, indent_kind):
+ def __init__(self, lines, text, mode, kind):
self.lines = lines
self.text = text
self.mode = mode # 'relaxed' or 'strict'
- self.indent_kind = indent_kind # 'spaces' or 'tab'
+ if kind in DTS_FAMILY:
+ self.file_type = 'dts'
+ else:
+ self.file_type = 'yaml'
class Rule:
@@ -340,14 +341,14 @@ def check_trailing_whitespace(ctx):
yield (dl.lineno, 'trailing whitespace')
-def check_tab_in_dts(ctx):
+def check_tab_in_yaml_example(ctx):
"""Reject literal tabs in DTS lines when input is YAML.
For YAML examples, indent and content must use spaces. Tabs inside
a #define value are tolerated (those are CPP macros, not DTS).
For .dts files, this rule does not apply -- tabs are required.
"""
- if ctx.indent_kind != 'spaces':
+ if ctx.file_type != 'yaml':
return
for dl in ctx.lines:
if dl.linetype == LineType.PREPROCESSOR:
@@ -359,21 +360,32 @@ def check_tab_in_dts(ctx):
def check_mixed_indent_chars(ctx):
- """Indent must be all-spaces or all-tabs, never mixed on one line."""
+ """Indent must be all-tabs, except for aligning indentation (comments
+ or continued lines)."""
for dl in ctx.lines:
if not dl.indent_str:
continue
if dl.linetype == LineType.PREPROCESSOR:
continue
- if ' ' in dl.indent_str and '\t' in dl.indent_str:
+ if re.search(r' \t', dl.indent_str):
yield (dl.lineno, 'mixed tabs and spaces in indent')
+ if dl.indent_str.count(' ') > 7:
+ yield (dl.lineno, 'too many space characters in indent (more than 7)')
+ for cont in dl.continuations:
+ if not cont.indent_str:
+ continue
+ if cont.linetype == LineType.PREPROCESSOR:
+ continue
+ if re.search(r' \t', cont.indent_str):
+ yield (cont.lineno, 'mixed tabs and spaces in indent')
def detect_indent_unit(ctx):
"""Find the indent unit used at depth 1 in this block.
- Returns one of: ' ' (2 spaces), ' ' (4 spaces), '\\t' (tab),
- or None if depth-1 is empty or ambiguous."""
+ Returns tuple of string (one of: ' ' (2 spaces), ' ' (4 spaces),
+ '\\t' (tab), or None if depth-1 is empty or ambiguous) and line number when
+ detection was made)."""
for dl in ctx.lines:
if dl.depth != 1:
continue
@@ -384,51 +396,51 @@ def detect_indent_unit(ctx):
if not dl.indent_str:
continue
if dl.indent_str == '\t':
- return '\t'
+ return ('\t', dl.lineno)
if dl.indent_str == ' ':
- return ' '
+ return (' ', dl.lineno)
if dl.indent_str == ' ':
- return ' '
+ return (' ', dl.lineno)
# Anything else at depth 1 is non-canonical; flag elsewhere.
- return dl.indent_str
- return None
+ return (dl.indent_str, dl.lineno)
+ return (None, None)
def check_indent_unit_relaxed(ctx):
"""YAML examples: 2 or 4 spaces. Never tabs or other widths."""
- unit = detect_indent_unit(ctx)
+ (unit, lineno) = detect_indent_unit(ctx)
if unit is None:
return
if unit not in (' ', ' '):
- yield (1, 'indent unit must be 2 or 4 spaces, got %r' % unit)
+ yield (lineno, 'indent unit must be 2 or 4 spaces, got %r' % unit)
def check_indent_unit_dts(ctx):
"""DTS files: 1 tab per level. Always required."""
- unit = detect_indent_unit(ctx)
+ (unit, lineno) = detect_indent_unit(ctx)
if unit is None:
return
if unit != '\t':
- yield (1, 'indent unit must be 1 tab in DTS, got %r' % unit)
+ yield (lineno, 'indent unit must be 1 tab in DTS, got %r' % unit)
def check_indent_unit_strict(ctx):
"""YAML: must be exactly 4 spaces. DTS: 1 tab (same as relaxed)."""
- unit = detect_indent_unit(ctx)
+ (unit, lineno) = detect_indent_unit(ctx)
if unit is None:
return
- if ctx.indent_kind == 'spaces':
+ if ctx.file_type == 'yaml':
if unit != ' ':
- yield (1, 'indent unit must be 4 spaces in strict mode, '
+ yield (lineno, 'indent unit must be 4 spaces in strict mode, '
'got %r' % unit)
def check_indent_consistent(ctx):
"""All indented lines must be a multiple of the detected unit."""
- unit = detect_indent_unit(ctx)
+ (unit, lineno) = detect_indent_unit(ctx)
if unit is None:
return
- if ctx.indent_kind == 'spaces':
+ if ctx.file_type == 'yaml':
if unit not in (' ', ' '):
return # let check_indent_unit_* report this
else:
@@ -552,28 +564,31 @@ def check_child_name_order(ctx):
def _property_bucket(name):
"""Return the canonical bucket index for a property:
- 0 compatible
- 1 reg / reg-names
- 2 ranges
- 3 standard properties (no vendor comma in #-stripped name)
- 4 vendor-specific properties
- 5 status
- Plus a sub-key inside the bucket for fixed slots (compatible, reg,
- reg-names, ranges, status). 'standard' and 'vendor' return None for
+ 0 device_type
+ 1 compatible
+ 2 reg / reg-names
+ 3 ranges
+ 4 standard properties (no vendor comma in #-stripped name)
+ 5 vendor-specific properties
+ 6 status
+ Plus a sub-key inside the bucket for fixed slots (device_type, compatible,
+ reg, reg-names, ranges, status). 'standard' and 'vendor' return None for
the sub-key, signalling that the within-bucket key is computed by
the pairing rules."""
stripped = name.lstrip('#')
- if name == 'compatible':
+ if name == 'device_type':
return (0, 0)
- if name == 'reg':
+ if name == 'compatible':
return (1, 0)
+ if name == 'reg':
+ return (2, 0)
if name == 'reg-names':
- return (1, 1)
+ return (2, 1)
if name == 'ranges':
- return (2, 0)
+ return (3, 0)
if name == 'status':
- return (5, 0)
- return (4 if ',' in stripped else 3, None)
+ return (6, 0)
+ return (5 if ',' in stripped else 4, None)
# Declarative pairing rules: each is a callable
@@ -927,12 +942,12 @@ RULES = [
Rule('trailing-whitespace', 'relaxed',
'no trailing whitespace on any line',
check_trailing_whitespace),
- Rule('tab-in-dts', 'relaxed',
- 'YAML examples may not contain tab characters',
- check_tab_in_dts, applies_to=('yaml',)),
+ Rule('tab-in-yaml', 'relaxed',
+ 'YAML (also DTS examples) may not contain tab characters',
+ check_tab_in_yaml_example, applies_to=('yaml',)),
Rule('mixed-indent-chars', 'relaxed',
'indent must not mix tabs and spaces',
- check_mixed_indent_chars),
+ check_mixed_indent_chars, applies_to=('dts', 'dtsi', 'dtso')),
Rule('unclosed-block-comment', 'relaxed',
'every /* block comment must close with */',
check_unclosed_block_comment),
@@ -1013,11 +1028,11 @@ def select_rules(mode, input_kind):
# Block runner
# ---------------------------------------------------------------------------
-def check_block(text, mode, indent_kind, input_type):
+def check_block(text, mode, input_type):
"""Run all selected rules on a single block of DTS text. Returns a
list of (lineno, rule_name, message) tuples."""
lines = classify_lines(text)
- ctx = Ctx(lines, text, mode, indent_kind)
+ ctx = Ctx(lines, text, mode, input_type)
rules = select_rules(mode, input_type)
findings = []
for r in rules:
@@ -1097,17 +1112,15 @@ def collect_findings(filepath, mode):
formatted output strings; count is the number of findings."""
kind = input_kind(filepath)
if kind == 'yaml':
- indent_kind = 'spaces'
iterator = iter_yaml_examples(filepath)
elif kind in DTS_FAMILY:
- indent_kind = 'tab'
iterator = iter_dts_file(filepath)
else:
return (['%s: unknown file type, skipping' % filepath], 0)
out = []
for text, base, idx in iterator:
- for lineno, rule, msg in check_block(text, mode, indent_kind, kind):
+ for lineno, rule, msg in check_block(text, mode, kind):
abs_line = base + lineno - 1
ex_tag = '' if idx is None else ' example %d' % idx
out.append('%s:%d:%s [%s] %s' %
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dts
new file mode 100644
index 000000000000..54be9f07b680
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-child-name-order.dts
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pmu {
+ compatible = "example,pmu";
+
+ /* Include labels to be sure they do not affect sorting */
+ foo: foo {
+ label = "foo";
+ };
+
+ label_bar: bar {
+ label = "bar";
+ };
+ };
+
+ memory@a0000000 {
+ device_type = "memory";
+ reg = <0x0 0xa0000000 0x0 0x0>;
+ };
+
+ pmu-2 {
+ compatible = "example,pmu";
+
+ /* Just reference labels to avoid strict warnings */
+ example,foo = <&foo>, <&label_bar>;
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dts
new file mode 100644
index 000000000000..296c58a545d5
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-child-name-order.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pmu {
+ compatible = "example,pmu";
+
+ /* Just reference labels to avoid strict warnings */
+ example,foo = <&foo>, <&label_bar>;
+ };
+};
+
+&pmu {
+ /* Include labels to be sure they do not affect sorting */
+ foo: foo {
+ label = "foo";
+ };
+
+ label_bar: bar {
+ label = "bar";
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dts
new file mode 100644
index 000000000000..813900e3393c
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-extend-node-digit-node-order.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&soc {
+ serial@20000 {
+ compatible = "example,serial";
+ reg = <0x20000 0x1000>;
+ };
+
+ interrupt-controller@10000 {
+ compatible = "example,intc";
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>;
+ };
+
+ serial@30000 {
+ compatible = "example,serial";
+ reg = <0x30000 0x1000>;
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-mixed-indent.dts b/scripts/dtc/dt-style-selftest/bad/dts-mixed-indent.dts
new file mode 100644
index 000000000000..cd3de04ec5a9
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-mixed-indent.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/* Test fixture: a .dts using wrong indent. */
+
+/dts-v1/;
+
+/ {
+ compatible = "example,test-board";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ clocks = <1>,
+ <2>,
+ <3>,
+ <4>;
+ resets = <5>;
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts
new file mode 100644
index 000000000000..f31abb6ceae4
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/dts-property-order.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: Incorrect property order
+ */
+
+/dts-v1/;
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ reg = <0x0 0x0>;
+ compatible = "arm,cortex-a57";
+ device_type = "cpu";
+ enable-method = "psci";
+ };
+ };
+
+ pmu {
+ compatible = "example,pmu";
+
+ status = "disabled";
+ dma-coherent;
+ };
+
+ soc@0 {
+ ranges = <0 0 0 0xc0000000>;
+ compatible = "simple-bus";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-controller@10000 {
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>,
+ <4 5 6>,
+ <7 8 9>;
+ compatible = "example,intc";
+ };
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml
new file mode 100644
index 000000000000..e2c69e9ff452
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/bad/yaml-prop-order-device-type.yaml
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/test-bad-prop-order.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Test fixture with device_type
+
+maintainers:
+ - Test User <test@example.com>
+
+properties:
+ compatible:
+ const: example,test-prop-order-device-type
+ reg:
+ maxItems: 1
+ device_type: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ device@1000 {
+ compatible = "example,test-prop-order-device-type";
+ device_type = "cpu";
+ reg = <0x1000 0x100>;
+ };
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt
new file mode 100644
index 000000000000..e2eea0862102
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-child-name-order.dts.txt
@@ -0,0 +1,2 @@
+# mode=strict
+bad/dts-child-name-order.dts:16: [child-name-order] child node 'bar' out of name order
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dts.txt
new file mode 100644
index 000000000000..b6e74e6f923e
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-child-name-order.dts.txt
@@ -0,0 +1,2 @@
+# mode=strict
+bad/dts-extend-node-child-name-order.dts:22: [child-name-order] child node 'bar' out of name order
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dts.txt
new file mode 100644
index 000000000000..bf252e4d9815
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-extend-node-digit-node-order.dts.txt
@@ -0,0 +1,2 @@
+# mode=strict
+bad/dts-extend-node-digit-node-order.dts:23: [child-address-order] child node @10000 out of address order
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt
new file mode 100644
index 000000000000..93146cfb51c7
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-mixed-indent.dts.txt
@@ -0,0 +1,9 @@
+# mode=strict
+bad/dts-mixed-indent.dts:11: [indent-consistent] indent mismatch (expected depth 1 * '\t')
+bad/dts-mixed-indent.dts:11: [mixed-indent-chars] too many space characters in indent (more than 7)
+bad/dts-mixed-indent.dts:12: [indent-consistent] indent mismatch (expected depth 2 * '\t')
+bad/dts-mixed-indent.dts:12: [mixed-indent-chars] mixed tabs and spaces in indent
+bad/dts-mixed-indent.dts:13: [indent-consistent] indent mismatch (expected depth 2 * '\t')
+bad/dts-mixed-indent.dts:13: [mixed-indent-chars] mixed tabs and spaces in indent
+bad/dts-mixed-indent.dts:16: [mixed-indent-chars] mixed tabs and spaces in indent
+bad/dts-mixed-indent.dts:19: [indent-consistent] indent mismatch (expected depth 2 * '\t')
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt
new file mode 100644
index 000000000000..4bc21328625f
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/dts-property-order.dts.txt
@@ -0,0 +1,6 @@
+# mode=strict
+bad/dts-property-order.dts:15: [property-order] property 'compatible' out of canonical order (should sort before 'reg')
+bad/dts-property-order.dts:16: [property-order] property 'device_type' out of canonical order (should sort before 'compatible')
+bad/dts-property-order.dts:25: [property-order] property 'dma-coherent' out of canonical order (should sort before 'status')
+bad/dts-property-order.dts:30: [property-order] property 'compatible' out of canonical order (should sort before 'ranges')
+bad/dts-property-order.dts:40: [property-order] property 'compatible' out of canonical order (should sort before 'interrupts')
diff --git a/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt b/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt
index 070025c4568c..5afdb101dcee 100644
--- a/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt
+++ b/scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt
@@ -1,2 +1,2 @@
# mode=relaxed
-bad/dts-spaces.dts:1: [indent-unit-dts] indent unit must be 1 tab in DTS, got ' '
+bad/dts-spaces.dts:9: [indent-unit-dts] indent unit must be 1 tab in DTS, got ' '
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt
index 5ef290d3a847..c4f31deea4ca 100644
--- a/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt
+++ b/scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt
@@ -1,2 +1,2 @@
# mode=strict
-bad/yaml-indent-strict.yaml:26: example 0 [indent-unit-strict] indent unit must be 4 spaces in strict mode, got ' '
+bad/yaml-indent-strict.yaml:27: example 0 [indent-unit-strict] indent unit must be 4 spaces in strict mode, got ' '
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt
index c989f8f19853..bc3fc3cf00cc 100644
--- a/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt
+++ b/scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt
@@ -1,3 +1,2 @@
# mode=relaxed
-bad/yaml-mixed-indent.yaml:27: example 0 [mixed-indent-chars] mixed tabs and spaces in indent
-bad/yaml-mixed-indent.yaml:27: example 0 [tab-in-dts] tab character not allowed in DTS example
+bad/yaml-mixed-indent.yaml:27: example 0 [tab-in-yaml] tab character not allowed in DTS example
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-prop-order-device-type.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-prop-order-device-type.yaml.txt
new file mode 100644
index 000000000000..9350e2b80f75
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/expected/yaml-prop-order-device-type.yaml.txt
@@ -0,0 +1,2 @@
+# mode=strict
+bad/yaml-prop-order-device-type.yaml:29: example 0 [property-order] property 'device_type' out of canonical order (should sort before 'compatible')
diff --git a/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt b/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt
index 9e83246fbaa1..0bc67ae48dd8 100644
--- a/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt
+++ b/scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt
@@ -1,2 +1,2 @@
# mode=relaxed
-bad/yaml-tab.yaml:28: example 0 [tab-in-dts] tab character not allowed in DTS example
+bad/yaml-tab.yaml:28: example 0 [tab-in-yaml] tab character not allowed in DTS example
diff --git a/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dts b/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dts
new file mode 100644
index 000000000000..af0adf5abf70
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-child-name-order.dts
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ memory@a0000000 {
+ device_type = "memory";
+ reg = <0x0 0xa0000000 0x0 0x0>;
+ };
+
+ pmu {
+ compatible = "example,pmu";
+
+ /* Include labels to be sure they do not affect sorting */
+ label_bar: bar {
+ label = "bar";
+ };
+
+ foo: foo {
+ label = "foo";
+ };
+ };
+
+ pmu-2 {
+ compatible = "example,pmu";
+
+ /* Just reference labels to avoid strict warnings */
+ example,foo = <&foo>, <&label_bar>;
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts
new file mode 100644
index 000000000000..cdf3f91ebe01
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-digit-node-order.dts
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* TODO: uncomment when child-address-order is fixed for top-level */
+ /*
+ memory@a0000000 {
+ device_type = "memory";
+ reg = <0x0 0xa0000000 0x0 0x0>;
+ };
+ */
+
+ pmu {
+ compatible = "example,pmu";
+ };
+
+ soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-controller@10000 {
+ compatible = "example,intc";
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>;
+ };
+
+ serial@20000 {
+ compatible = "example,serial";
+ reg = <0x20000 0x1000>;
+ };
+
+ serial@30000 {
+ compatible = "example,serial";
+ reg = <0x30000 0x1000>;
+ };
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-dtc.dts b/scripts/dtc/dt-style-selftest/good/dts-dtc.dts
new file mode 100644
index 000000000000..a3207196214c
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-dtc.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: dtc directive
+ */
+
+/dts-v1/;
+
+/include/ "soc.dtsi"
+/include/"soc-other.dtsi"
+
+/ {
+ compatible = "example,test-board";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ leds {
+ led-0 {
+ compatible = "example,led";
+ };
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dts b/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dts
new file mode 100644
index 000000000000..97d468051f25
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-extend-node-child-name-order.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pmu {
+ compatible = "example,pmu";
+
+ /* Just reference labels to avoid strict warnings */
+ example,foo = <&foo>, <&label_bar>;
+ };
+};
+
+&pmu {
+ /* Include labels to be sure they do not affect sorting */
+ label_bar: bar {
+ label = "bar";
+ };
+
+ foo: foo {
+ label = "foo";
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dts b/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dts
new file mode 100644
index 000000000000..faf49962faf2
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-extend-node-digit-node-order.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&soc {
+ interrupt-controller@10000 {
+ compatible = "example,intc";
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>;
+ };
+
+ serial@20000 {
+ compatible = "example,serial";
+ reg = <0x20000 0x1000>;
+ };
+
+ serial@30000 {
+ compatible = "example,serial";
+ reg = <0x30000 0x1000>;
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-preprocessor.dts b/scripts/dtc/dt-style-selftest/good/dts-preprocessor.dts
new file mode 100644
index 000000000000..bd6d9dddec73
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-preprocessor.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: preprocessor directive
+ */
+
+/dts-v1/;
+
+#include "soc.dtsi"
+#include<dt-bindings/gpio/gpio.h>
+
+/ {
+ compatible = "example,test-board";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ leds {
+ led-0 {
+ compatible = "example,led";
+ };
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/dts-property-order.dts b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts
new file mode 100644
index 000000000000..0e183e3459cd
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/dts-property-order.dts
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/*
+ * Test fixture: Incorrect property order
+ */
+
+/dts-v1/;
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a57";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ };
+ };
+
+ pmu {
+ compatible = "example,pmu";
+ dma-coherent;
+
+ status = "disabled";
+ };
+
+ soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-controller@10000 {
+ compatible = "example,intc";
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>;
+ };
+ };
+};
diff --git a/scripts/dtc/dt-style-selftest/good/soc.dtsi b/scripts/dtc/dt-style-selftest/good/soc.dtsi
new file mode 100644
index 000000000000..deec1a973c92
--- /dev/null
+++ b/scripts/dtc/dt-style-selftest/good/soc.dtsi
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+/dts-v1/;
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a57";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ };
+ };
+
+ pmu {
+ compatible = "example,pmu";
+ };
+
+ soc@0 {
+ compatible = "simple-bus";
+ ranges = <0 0 0 0xc0000000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-controller@10000 {
+ compatible = "example,intc";
+ reg = <0x10000 0x1000>;
+ interrupts = <1 2 3>,
+ <4 5 6>,
+ <7 8 9>;
+ };
+
+ serial@20000 {
+ compatible = "example,serial";
+ reg = <0x20000 0x1000>;
+ };
+
+ serial@30000 {
+ compatible = "example,serial";
+ reg = <0x30000 0x1000>;
+ };
+ };
+};
diff --git a/scripts/gdb/linux/page_owner.py b/scripts/gdb/linux/page_owner.py
index 8e713a09cfe7..eeabaeed438b 100644
--- a/scripts/gdb/linux/page_owner.py
+++ b/scripts/gdb/linux/page_owner.py
@@ -34,6 +34,7 @@ class DumpPageOwner(gdb.Command):
max_pfn = None
p_ops = None
migrate_reason_names = None
+ mr_never = None
def __init__(self):
super(DumpPageOwner, self).__init__("lx-dump-page-owner", gdb.COMMAND_SUPPORT)
@@ -65,6 +66,7 @@ class DumpPageOwner(gdb.Command):
self.max_pfn = int(gdb.parse_and_eval("max_pfn"))
self.page_ext_size = int(gdb.parse_and_eval("page_ext_size"))
self.migrate_reason_names = gdb.parse_and_eval('migrate_reason_names')
+ self.mr_never = int(gdb.parse_and_eval('MR_NEVER'))
def page_ext_invalid(self, page_ext):
if page_ext == gdb.Value(0):
@@ -138,7 +140,7 @@ class DumpPageOwner(gdb.Command):
else:
gdb.write('page last free stack trace:\n')
stackdepot.stack_depot_print(page_owner["free_handle"])
- if page_owner['last_migrate_reason'] != -1:
+ if page_owner['last_migrate_reason'] != self.mr_never:
gdb.write('page has been migrated, last migrate reason: %s\n' % self.migrate_reason_names[page_owner['last_migrate_reason']])
def read_page_owner(self):
diff --git a/scripts/headers_install.sh b/scripts/headers_install.sh
index 9c15e748761c..2f1d1767ca26 100755
--- a/scripts/headers_install.sh
+++ b/scripts/headers_install.sh
@@ -36,6 +36,7 @@ sed -E -e '
s/(^|[^a-zA-Z0-9])__packed([^a-zA-Z0-9_]|$)/\1__attribute__((packed))\2/g
s/(^|[[:space:](])(inline|asm|volatile)([[:space:](]|$)/\1__\2__\3/g
s@#(ifndef|define|endif[[:space:]]*/[*])[[:space:]]*_UAPI@#\1 @
+ s/__ASSEMBLY__/__ASSEMBLER__/g
' $INFILE > $TMPFILE || exit 1
scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__ $TMPFILE > $OUTFILE
diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 37d5c095ad22..494852ade6d8 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -398,11 +398,13 @@ static void write_src(void)
strcpy((char *)table[i]->sym, buf);
printf("\t/* %s */\n", table[i]->sym);
}
+ printf(".size kallsyms_names, . - kallsyms_names\n");
printf("\n");
output_label("kallsyms_markers");
for (i = 0; i < markers_cnt; i++)
printf("\t.long\t%u\n", markers[i]);
+ printf(".size kallsyms_markers, . - kallsyms_markers\n");
printf("\n");
free(markers);
@@ -415,6 +417,7 @@ static void write_src(void)
printf("\t.asciz\t\"%s\"\n", buf);
off += strlen(buf) + 1;
}
+ printf(".size kallsyms_token_table, . - kallsyms_token_table\n");
printf("\n");
output_label("kallsyms_token_index");
@@ -441,6 +444,7 @@ static void write_src(void)
(unsigned int)table[i]->addr, table[i]->sym);
}
}
+ printf(".size kallsyms_offsets, . - kallsyms_offsets\n");
printf("\n");
sort_symbols_by_name();
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index c368bec5ab60..fe8ba09b0039 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -348,6 +348,23 @@ static int conf_string(struct menu *menu)
}
if (def && sym_set_string_value(sym, def))
return 0;
+
+ /*
+ * A new int or hex symbol whose default fails validation
+ * cannot be set from an empty answer. When standard input is
+ * exhausted, as it is for a non-interactive oldconfig or
+ * syncconfig, re-asking would loop forever and grow the output
+ * until it exhausts memory. Stop with an error that names the
+ * symbol instead. String symbols accept any text, and bool and
+ * tristate symbols (conf_sym()) and choices (conf_choice())
+ * accept the default on an empty line, so they are unaffected.
+ */
+ if (feof(stdin)) {
+ fprintf(stderr,
+ "\nerror: no value for new symbol '%s' at end of input\n",
+ sym->name);
+ exit(1);
+ }
}
}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 16f92c4a775a..2b91d16bf14f 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -738,6 +738,39 @@ bool expr_contains_symbol(struct expr *dep, struct symbol *sym)
return false;
}
+/*
+ * Check if the expression references 'sym' in a way that is satisfiable
+ * with 'sym' disabled, e.g.'sym!=y'.
+ *
+ * Expects that expr_transform() was already called on 'expr'.
+ */
+bool expr_contains_symbol_negated(struct expr *dep, struct symbol *sym)
+{
+ if (!dep)
+ return false;
+
+ switch (dep->type) {
+ case E_AND:
+ case E_OR:
+ return expr_contains_symbol_negated(dep->left.expr, sym) ||
+ expr_contains_symbol_negated(dep->right.expr, sym);
+ case E_NOT:
+ return dep->left.expr->type == E_SYMBOL &&
+ dep->left.expr->left.sym == sym;
+ case E_EQUAL:
+ /* sym=n */
+ return dep->left.sym == sym && dep->right.sym == &symbol_no;
+ case E_UNEQUAL:
+ /* sym!=y, sym!=m */
+ return dep->left.sym == sym &&
+ (dep->right.sym == &symbol_yes ||
+ dep->right.sym == &symbol_mod);
+ default:
+ break;
+ }
+ return false;
+}
+
bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
{
if (!dep)
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 5f900d18dae0..b580f9fa0f29 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -38,7 +38,7 @@ union expr_data {
* struct expr - expression
*
* @node: link node for the hash table
- * @type: expressoin type
+ * @type: expression type
* @val: calculated tristate value
* @val_is_valid: indicate whether the value is valid
* @left: left node
@@ -160,7 +160,7 @@ struct symbol {
#define SYMBOL_MAXLENGTH 256
-/* A property represent the config options that can be associated
+/* A property represents the config options that can be associated
* with a config "symbol".
* Sample:
* config FOO
@@ -307,6 +307,7 @@ tristate expr_calc_value(struct expr *e);
struct expr *expr_eliminate_dups(struct expr *e);
struct expr *expr_transform(struct expr *e);
bool expr_contains_symbol(struct expr *dep, struct symbol *sym);
+bool expr_contains_symbol_negated(struct expr *dep, struct symbol *sym);
bool expr_depends_symbol(struct expr *dep, struct symbol *sym);
struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b2d8d4e11e07..9c079e92a9ed 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -428,9 +428,19 @@ static void _menu_finalize(struct menu *parent, bool inside_choice)
if (!expr_contains_symbol(dep, sym))
/* No dependency, quit */
break;
+ /*
+ * Note that it's actually possible to depend on both
+ * 'SYM!=y' and 'SYM=y', so we need to first check if
+ * it's a positive dependency before checking if it's
+ * a negative dependency. See example:
+ * 'SFC && MTD && !(SFC=y && MTD=m)'
+ */
if (expr_depends_symbol(dep, sym))
/* Absolute dependency, put in submenu */
goto next;
+ if (expr_contains_symbol_negated(dep, sym))
+ /* Negative dependency, quit */
+ break;
/*
* Also consider it a dependency on sym if our
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index f08e0863b712..ec242e03f509 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -122,7 +122,7 @@ fi
MERGE_LIST=$*
-TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+TMP_FILE=$(mktemp --tmpdir="$OUTPUT" .tmp.config.XXXXXXXXXX)
echo "Using $INITFILE as base"
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index f99e196abeea..ab0b8125c8cb 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -38,7 +38,7 @@ is_enabled() {
}
# Nice output in kbuild format
-# Will be supressed by "make -s"
+# Will be suppressed by "make -s"
info()
{
printf " %-7s %s\n" "${1}" "${2}"
@@ -106,6 +106,18 @@ vmlinux_link()
${kallsymso} ${btf_vmlinux_bin_o} ${arch_vmlinux_o} ${ldlibs}
}
+# Check if kallsymso_prev and kallsymso differ
+# If symbol sizes within ${kallsymso} change, any symbols within vmlinux are
+# likely to shift, invalidating ${kallsymso}.
+# Since file size can remain unchanged even if symbol sizes change, compare the
+# actual symbols instead of relying on file size only.
+kallsymso_changed()
+{
+ ${NM} -n "${kallsymso_prev}" > "${kallsymso_prev}.sym"
+ ${NM} -n "${kallsymso}" > "${kallsymso}.sym"
+ ! cmp -s "${kallsymso_prev}.sym" "${kallsymso}.sym"
+}
+
# Create ${2}.o file with all symbols from the ${1} object file
kallsyms()
{
@@ -126,6 +138,7 @@ kallsyms()
${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \
${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} -c -o "${2}.o" "${2}.S"
+ kallsymso_prev="${kallsymso:-}"
kallsymso=${2}.o
}
@@ -255,7 +268,12 @@ if is_enabled CONFIG_KALLSYMS; then
sysmap_and_kallsyms .tmp_vmlinux2
size2=$(${CONFIG_SHELL} "${srctree}/scripts/file-size.sh" ${kallsymso})
- if [ $size1 -ne $size2 ] || [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
+ # Due to alignment, file size of the kallsymso object file might remain
+ # unchanged even if individual symbols within change size. Changed
+ # symbol sizes can still shift other symbols, though. Therefore, don't
+ # rely on file size alone.
+ if [ $size1 -ne $size2 ] || kallsymso_changed || \
+ [ -n "${KALLSYMS_EXTRA_PASS}" ]; then
vmlinux_link .tmp_vmlinux3
sysmap_and_kallsyms .tmp_vmlinux3
fi
diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index c4a7acf8edc3..b52a8489d9f6 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -271,6 +271,9 @@ validate_config() {
[[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] && \
die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported"
+ [[ -v CONFIG_LD_DEAD_CODE_DATA_ELIMINATION ]] && \
+ die "kernel option 'CONFIG_LD_DEAD_CODE_DATA_ELIMINATION' not supported"
+
[[ -v CONFIG_AS_IS_LLVM ]] && \
[[ "$CONFIG_AS_VERSION" -lt 200000 ]] && \
die "Clang assembler version < 20 not supported"
@@ -555,6 +558,8 @@ build_kernel() {
#
cmd+=("KBUILD_MODPOST_WARN=1")
+ cmd+=("KLP_SYMIDS=1")
+
if [[ -v VERBOSE ]]; then
cmd+=("V=1")
else
@@ -575,8 +580,9 @@ find_objects() {
local opts=("$@")
# Find root-level vmlinux.o and non-root-level .ko files,
- # excluding klp-tmp/ and .git/
- find "$PWD" \( -path "$TMP_DIR" -o -path "$PWD/.git" -o -regex "$PWD/[^/][^/]*\.ko" \) -prune -o \
+ # excluding klp-tmp/ and hidden directories.
+ find "$PWD" -mindepth 1 \
+ \( -path "$TMP_DIR" -o -name ".*" -o -regex "$PWD/[^/][^/]*\.ko" \) -prune -o \
-type f "${opts[@]}" \
\( -name "*.ko" -o -path "$PWD/vmlinux.o" \) \
-printf '%P\n'
@@ -605,6 +611,8 @@ copy_orig_objects() {
done
xtrace_restore
+ cp -f "$PWD/vmlinux" "$ORIG_DIR" || die "missing vmlinux"
+
mv -f "$TMP_DIR/build.log" "$ORIG_DIR"
touch "$TIMESTAMP"
touch "$ORIG_DIR/.complete"
@@ -675,6 +683,8 @@ generate_checksums() {
"$OBJTOOL" klp checksum "$dest"
done
+ [[ -f "$src_dir/vmlinux" ]] && cp -f "$src_dir/vmlinux" "$dest_dir"
+
touch "$dest_dir/.complete"
}
diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh
index 031f2192b390..99bfdcaa3396 100755
--- a/scripts/min-tool-version.sh
+++ b/scripts/min-tool-version.sh
@@ -33,6 +33,8 @@ llvm)
rustc)
if [ "$SRCARCH" = "s390" ]; then
echo 1.96.0
+ elif [ "$ARCH" = powerpc ]; then
+ echo 1.95.0
else
echo 1.85.0
fi
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index a7b72a81d248..75374c64b8cc 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -74,7 +74,7 @@ static unsigned int nr_unresolved;
#define MODULE_NAME_LEN (64 - sizeof(Elf_Addr))
-void modpost_log(bool is_error, const char *fmt, ...)
+void modpost_log(bool is_error, struct module *mod, const char *fmt, ...)
{
va_list arglist;
@@ -87,11 +87,17 @@ void modpost_log(bool is_error, const char *fmt, ...)
fprintf(stderr, "modpost: ");
+ if (mod)
+ fprintf(stderr, "%s%s: ", mod->name, mod->is_vmlinux ? "" : ".ko");
+
va_start(arglist, fmt);
vfprintf(stderr, fmt, arglist);
va_end(arglist);
}
+#define mod_warn(mod, fmt, args...) modpost_log(false, mod, fmt, ##args)
+#define mod_error(mod, fmt, args...) modpost_log(true, mod, fmt, ##args)
+
static inline bool strends(const char *str, const char *postfix)
{
if (strlen(str) < strlen(postfix))
@@ -359,9 +365,8 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,
struct symbol *s = find_symbol(name);
if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) {
- error("%s: '%s' exported twice. Previous export was in %s%s\n",
- mod->name, name, s->module->name,
- s->module->is_vmlinux ? "" : ".ko");
+ mod_error(mod, "symbol '%s' exported twice. Previous export was in %s%s\n",
+ name, s->module->name, s->module->is_vmlinux ? "" : ".ko");
}
s = alloc_symbol(name);
@@ -632,7 +637,7 @@ static void handle_symbol(struct module *mod, struct elf_info *info,
if (strstarts(symname, "__gnu_lto_")) {
/* Should warn here, but modpost runs before the linker */
} else
- warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
+ mod_warn(mod, "'%s' is COMMON symbol\n", symname);
break;
case SHN_UNDEF:
/* undefined symbol */
@@ -767,6 +772,7 @@ static const char *const section_white_list[] =
".llvm.call-graph-profile", /* call graph */
"__llvm_covfun",
"__llvm_covmap",
+ ".klp.symid", /* objtool --klp-symids */
NULL
};
@@ -775,7 +781,7 @@ static const char *const section_white_list[] =
* The cause of this is often a section specified in assembler
* without "ax" / "aw".
*/
-static void check_section(const char *modname, struct elf_info *elf,
+static void check_section(struct module *mod, struct elf_info *elf,
Elf_Shdr *sechdr)
{
const char *sec = sech_name(elf, sechdr);
@@ -783,11 +789,11 @@ static void check_section(const char *modname, struct elf_info *elf,
if (sechdr->sh_type == SHT_PROGBITS &&
!(sechdr->sh_flags & SHF_ALLOC) &&
!match(sec, section_white_list)) {
- warn("%s (%s): unexpected non-allocatable section.\n"
- "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
- "Note that for example <linux/init.h> contains\n"
- "section definitions for use in .S files.\n\n",
- modname, sec);
+ mod_warn(mod, "unexpected non-allocatable section '%s'.\n"
+ "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
+ "Note that for example <linux/init.h> contains\n"
+ "section definitions for use in .S files.\n\n",
+ sec);
}
}
@@ -1021,7 +1027,7 @@ static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
return (elf->sechdrs[secndx].sh_flags & SHF_EXECINSTR) != 0;
}
-static void default_mismatch_handler(const char *modname, struct elf_info *elf,
+static void default_mismatch_handler(struct module *mod, struct elf_info *elf,
const struct sectioncheck* const mismatch,
Elf_Sym *tsym,
unsigned int fsecndx, const char *fromsec, Elf_Addr faddr,
@@ -1051,10 +1057,10 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
* The format for the reference source: <symbol_name>+<offset> or <address>
* The format for the reference destination: <symbol_name> or <address>
*/
- warn("%s: section mismatch in reference: %s%s0x%x (section: %s) -> %s (section: %s)\n",
- modname, fromsym, fromsym[0] ? "+" : "",
- (unsigned int)(faddr - (fromsym[0] ? from->st_value : 0)),
- fromsec, tosym[0] ? tosym : taddr_str, tosec);
+ mod_warn(mod, "section mismatch in reference: %s%s0x%x (section: %s) -> %s (section: %s)\n",
+ fromsym, fromsym[0] ? "+" : "",
+ (unsigned int)(faddr - (fromsym[0] ? from->st_value : 0)),
+ fromsec, tosym[0] ? tosym : taddr_str, tosec);
if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) {
if (match(tosec, mismatch->bad_tosec))
@@ -1063,7 +1069,7 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
"Something is seriously wrong and should be fixed.\n"
"You might get more information about where this is\n"
"coming from by using scripts/check_extable.sh %s\n",
- fromsec, (long)faddr, tosec, modname);
+ fromsec, (long)faddr, tosec, mod->name);
else if (is_executable_section(elf, get_secindex(elf, tsym)))
warn("The relocation at %s+0x%lx references\n"
"section \"%s\" which is not in the list of\n"
@@ -1093,22 +1099,22 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
label_name = sym_name(elf, label);
if (!strstarts(label_name, prefix)) {
- error("%s: .export_symbol section contains strange symbol '%s'\n",
- mod->name, label_name);
+ mod_error(mod, ".export_symbol section contains strange symbol '%s'\n",
+ label_name);
return;
}
if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
ELF_ST_BIND(sym->st_info) != STB_WEAK) {
- error("%s: local symbol '%s' was exported\n", mod->name,
- label_name + strlen(prefix));
+ mod_error(mod, "local symbol '%s' was exported\n",
+ label_name + strlen(prefix));
return;
}
name = sym_name(elf, sym);
if (strcmp(label_name + strlen(prefix), name)) {
- error("%s: .export_symbol section references '%s', but it does not seem to be an export symbol\n",
- mod->name, name);
+ mod_error(mod, ".export_symbol section references '%s', but it does not seem to be an export symbol\n",
+ name);
return;
}
@@ -1118,8 +1124,8 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
} else if (!strcmp(data, "")) {
is_gpl = false;
} else {
- error("%s: unknown license '%s' was specified for '%s'\n",
- mod->name, data, name);
+ mod_error(mod, "unknown license '%s' was specified for '%s'\n",
+ data, name);
return;
}
@@ -1142,11 +1148,11 @@ static void check_export_symbol(struct module *mod, struct elf_info *elf,
s->is_func = true;
if (match(secname, PATTERNS(ALL_INIT_SECTIONS)))
- warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n",
- mod->name, name);
+ mod_warn(mod, "EXPORT_SYMBOL used for init symbol '%s'. Remove __init or EXPORT_SYMBOL.\n",
+ name);
else if (match(secname, PATTERNS(ALL_EXIT_SECTIONS)))
- warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n",
- mod->name, name);
+ mod_warn(mod, "EXPORT_SYMBOL used for exit symbol '%s'. Remove __exit or EXPORT_SYMBOL.\n",
+ name);
}
static void check_section_mismatch(struct module *mod, struct elf_info *elf,
@@ -1166,7 +1172,7 @@ static void check_section_mismatch(struct module *mod, struct elf_info *elf,
if (!mismatch)
return;
- default_mismatch_handler(mod->name, elf, mismatch, sym,
+ default_mismatch_handler(mod, elf, mismatch, sym,
fsecndx, fromsec, faddr,
tosec, taddr);
}
@@ -1443,7 +1449,7 @@ static void check_sec_ref(struct module *mod, struct elf_info *elf)
for (i = 0; i < elf->num_sections; i++) {
Elf_Shdr *sechdr = &elf->sechdrs[i];
- check_section(mod->name, elf, sechdr);
+ check_section(mod, elf, sechdr);
/* We want to process only relocation sections and not .init */
if (sechdr->sh_type == SHT_REL || sechdr->sh_type == SHT_RELA) {
/* section to which the relocation applies */
@@ -1591,14 +1597,14 @@ static void read_symbols(const char *modname)
struct elf_info info = { };
Elf_Sym *sym;
- if (!parse_elf(&info, modname))
- return;
-
if (!strends(modname, ".o")) {
error("%s: filename must be suffixed with .o\n", modname);
return;
}
+ if (!parse_elf(&info, modname))
+ return;
+
/* strip trailing .o */
mod = new_module(modname, strlen(modname) - strlen(".o"));
@@ -1613,7 +1619,7 @@ static void read_symbols(const char *modname)
if (!mod->is_vmlinux) {
license = get_modinfo(&info, "license");
if (!license)
- error("missing MODULE_LICENSE() in %s\n", modname);
+ mod_error(mod, "missing MODULE_LICENSE()\n");
while (license) {
if (!license_is_gpl_compatible(license)) {
mod->is_gpl_compatible = false;
@@ -1626,14 +1632,14 @@ static void read_symbols(const char *modname)
namespace;
namespace = get_next_modinfo(&info, "import_ns", namespace)) {
if (strstarts(namespace, MODULE_NS_PREFIX))
- error("%s: explicitly importing namespace \"%s\" is not allowed.\n",
- mod->name, namespace);
+ mod_error(mod, "explicitly importing namespace '%s' is not allowed.\n",
+ namespace);
add_namespace(&mod->imported_namespaces, namespace);
}
if (!get_modinfo(&info, "description"))
- warn("missing MODULE_DESCRIPTION() in %s\n", modname);
+ mod_warn(mod, "missing MODULE_DESCRIPTION()\n");
}
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
@@ -1772,14 +1778,13 @@ static void check_exports(struct module *mod)
exp = find_symbol(s->name);
if (!exp) {
if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS)
- modpost_log(!warn_unresolved,
- "\"%s\" [%s.ko] undefined!\n",
- s->name, mod->name);
+ modpost_log(!warn_unresolved, mod,
+ "symbol '%s' undefined!\n",
+ s->name);
continue;
}
if (exp->module == mod) {
- error("\"%s\" [%s.ko] was exported without definition\n",
- s->name, mod->name);
+ mod_error(mod, "symbol '%s' was exported without definition\n", s->name);
continue;
}
@@ -1792,15 +1797,15 @@ static void check_exports(struct module *mod)
if (!verify_module_namespace(exp->namespace, basename) &&
!contains_namespace(&mod->imported_namespaces, exp->namespace)) {
- modpost_log(!allow_missing_ns_imports,
- "module %s uses symbol %s from namespace %s, but does not import it.\n",
- basename, exp->name, exp->namespace);
+ modpost_log(!allow_missing_ns_imports, mod,
+ "module uses symbol '%s' from namespace '%s', but does not import it.\n",
+ exp->name, exp->namespace);
add_namespace(&mod->missing_namespaces, exp->namespace);
}
if (!mod->is_gpl_compatible && exp->is_gpl_only)
- error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n",
- basename, exp->name);
+ mod_error(mod, "GPL-incompatible module uses GPL-only symbol '%s'\n",
+ exp->name);
}
}
@@ -1850,7 +1855,7 @@ static void check_modname_len(struct module *mod)
mod_name = get_basename(mod->name);
if (strlen(mod_name) >= MODULE_NAME_LEN)
- error("module name is too long [%s.ko]\n", mod->name);
+ mod_error(mod, "module name is too long\n");
}
/**
@@ -1914,10 +1919,9 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)
continue;
if (!sym->crc_valid)
- warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n"
- "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n",
- sym->name, mod->name, mod->is_vmlinux ? "" : ".ko",
- sym->name);
+ mod_warn(mod, "EXPORT symbol '%s' version generation failed, symbol will not be versioned.\n"
+ "Is '%s' prototyped in <asm/asm-prototypes.h>?\n",
+ sym->name, sym->name);
buf_printf(buf, "SYMBOL_CRC(%s, 0x%08x);\n",
sym->name, sym->crc);
@@ -1941,8 +1945,7 @@ static void add_extended_versions(struct buffer *b, struct module *mod)
if (!s->module)
continue;
if (!s->crc_valid) {
- warn("\"%s\" [%s.ko] has no CRC!\n",
- s->name, mod->name);
+ mod_warn(mod, "symbol '%s' has no CRC!\n", s->name);
continue;
}
buf_printf(b, "\t0x%08x,\n", s->crc);
@@ -1985,8 +1988,7 @@ static void add_versions(struct buffer *b, struct module *mod)
if (!s->module)
continue;
if (!s->crc_valid) {
- warn("\"%s\" [%s.ko] has no CRC!\n",
- s->name, mod->name);
+ mod_warn(mod, "symbol '%s' has no CRC!\n", s->name);
continue;
}
if (strlen(s->name) >= MODULE_NAME_LEN) {
@@ -1994,8 +1996,7 @@ static void add_versions(struct buffer *b, struct module *mod)
/* this symbol will only be in the extended info */
continue;
} else {
- error("too long symbol \"%s\" [%s.ko]\n",
- s->name, mod->name);
+ mod_error(mod, "too long symbol '%s'\n", s->name);
break;
}
}
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 2aecb8f25c87..d5f6d82837d5 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -223,8 +223,8 @@ char *read_text_file(const char *filename);
char *get_line(char **stringp);
void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym);
-void __attribute__((format(printf, 2, 3)))
-modpost_log(bool is_error, const char *fmt, ...);
+void __attribute__((format(printf, 3, 4)))
+modpost_log(bool is_error, struct module *mod, const char *fmt, ...);
/*
* warn - show the given message, then let modpost continue running, still
@@ -239,6 +239,6 @@ modpost_log(bool is_error, const char *fmt, ...);
* fatal - show the given message, and bail out immediately. This should be
* used when there is no point to continue running modpost.
*/
-#define warn(fmt, args...) modpost_log(false, fmt, ##args)
-#define error(fmt, args...) modpost_log(true, fmt, ##args)
+#define warn(fmt, args...) modpost_log(false, NULL, fmt, ##args)
+#define error(fmt, args...) modpost_log(true, NULL, fmt, ##args)
#define fatal(fmt, args...) do { error(fmt, ##args); exit(1); } while (1)
diff --git a/scripts/module.lds.S b/scripts/module.lds.S
index b62683061d79..d0f200428957 100644
--- a/scripts/module.lds.S
+++ b/scripts/module.lds.S
@@ -3,11 +3,6 @@
* Archs are free to supply their own linker scripts. ld will
* combine them automatically.
*/
-#ifdef CONFIG_UNWIND_TABLES
-#define DISCARD_EH_FRAME
-#else
-#define DISCARD_EH_FRAME *(.eh_frame)
-#endif
#include <asm-generic/codetag.lds.h>
diff --git a/scripts/nsdeps b/scripts/nsdeps
index a3372166ac01..d4b5ebcc2016 100644
--- a/scripts/nsdeps
+++ b/scripts/nsdeps
@@ -8,7 +8,7 @@ SPATCH_REQ_VERSION="1.0.4"
DIR="$(dirname $(readlink -f $0))/.."
SPATCH="`which ${SPATCH:=spatch}`"
if [ ! -x "$SPATCH" ]; then
- echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
+ echo 'spatch is part of the Coccinelle project and is available at https://coccinelle.gitlabpages.inria.fr/website'
exit 1
fi
diff --git a/scripts/package/kernel.spec b/scripts/package/kernel.spec
index c732415662ef..46e80970f723 100644
--- a/scripts/package/kernel.spec
+++ b/scripts/package/kernel.spec
@@ -67,7 +67,18 @@ This package provides debug information for the kernel image and modules from th
%undefine _unique_debug_srcs
%undefine _debugsource_packages
%undefine _debuginfo_subpackages
+
+# Preserve .BTF and .BTF.base sections in kernel modules during debuginfo
+# stripping. find-debuginfo.sh uses eu-strip which removes non-allocated ELF
+# sections like .BTF by default. .BTF.base is required for BTF distillation
+# support; without it, module BTF validation fails.
+%global with_keep_section %(%{__find_debuginfo} --help 2>&1 | grep -c keep-section)
+%if %{with_keep_section}
+%global _find_debuginfo_opts -r --keep-section .BTF --keep-section .BTF.base
+%else
%global _find_debuginfo_opts -r
+%endif
+
%global _missing_build_ids_terminate_build 1
%global _no_recompute_build_ids 1
%{debug_package}
diff --git a/scripts/rust_is_available.sh b/scripts/rust_is_available.sh
index 551f1ebd0dcb..c30983562a2f 100755
--- a/scripts/rust_is_available.sh
+++ b/scripts/rust_is_available.sh
@@ -208,6 +208,20 @@ if [ "$bindgen_libclang_cversion" -lt "$bindgen_libclang_min_cversion" ]; then
exit 1
fi
+if [ "$bindgen_libclang_cversion" -ge 2200000 ] &&
+ [ "$rust_bindings_generator_cversion" -lt 7201 ]; then
+ # Distributions may have patched the issue.
+ if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_libclang_22.h | grep -q 'pub foo'; then
+ echo >&2 "***"
+ echo >&2 "*** Rust bindings generator '$BINDGEN' < 0.72.1 together with libclang >= 22"
+ echo >&2 "*** may not work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/3278)."
+ echo >&2 "*** Your bindgen version: $rust_bindings_generator_version"
+ echo >&2 "*** Your libclang version: $bindgen_libclang_version"
+ echo >&2 "***"
+ warning=1
+ fi
+fi
+
# If the C compiler is Clang, then we can also check whether its version
# matches the `libclang` version used by the Rust bindings generator.
#
diff --git a/scripts/rust_is_available_bindgen_libclang_22.h b/scripts/rust_is_available_bindgen_libclang_22.h
new file mode 100644
index 000000000000..6b33544c14a8
--- /dev/null
+++ b/scripts/rust_is_available_bindgen_libclang_22.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+struct S;
+struct S {
+ int foo;
+};
diff --git a/scripts/rust_is_available_test.py b/scripts/rust_is_available_test.py
index d6d54b7ea42a..22bdff980c35 100755
--- a/scripts/rust_is_available_test.py
+++ b/scripts/rust_is_available_test.py
@@ -54,16 +54,23 @@ else:
""")
@classmethod
- def generate_bindgen(cls, version_stdout, libclang_stderr):
+ def generate_bindgen(cls, version_stdout, libclang_stderr, libclang_22_patched=False):
if libclang_stderr is None:
libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})"
else:
libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)"
+ if libclang_22_patched:
+ libclang_22_case = "print('pub foo: ::std::os::raw::c_int,')"
+ else:
+ libclang_22_case = "pass"
+
return cls.generate_executable(f"""#!/usr/bin/env python3
import sys
if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv):
{libclang_case}
+elif "rust_is_available_bindgen_libclang_22.h" in " ".join(sys.argv):
+ {libclang_22_case}
else:
print({repr(version_stdout)})
""")
@@ -177,7 +184,13 @@ else:
def test_rustc_nonexecutable(self):
result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.nonexecutable })
- self.assertIn(f"Running '{self.nonexecutable}' to check the Rust compiler version failed with", result.stderr)
+ self.assertTrue(
+ # `dash`.
+ f"Running '{self.nonexecutable}' to check the Rust compiler version failed with" in result.stderr or
+ # `bash`.
+ f"Rust compiler '{self.nonexecutable}' could not be found." in result.stderr,
+ f"Unexpected `stderr`:\n{result.stderr}"
+ )
def test_rustc_unexpected_binary(self):
result = self.run_script(self.Expected.FAILURE, { "RUSTC": self.unexpected_binary })
@@ -205,7 +218,13 @@ else:
def test_bindgen_nonexecutable(self):
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.nonexecutable })
- self.assertIn(f"Running '{self.nonexecutable}' to check the Rust bindings generator version failed with", result.stderr)
+ self.assertTrue(
+ # `dash`.
+ f"Running '{self.nonexecutable}' to check the Rust bindings generator version failed with" in result.stderr or
+ # `bash`.
+ f"Rust bindings generator '{self.nonexecutable}' could not be found." in result.stderr,
+ f"Unexpected `stderr`:\n{result.stderr}"
+ )
def test_bindgen_unexpected_binary(self):
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": self.unexpected_binary })
@@ -248,6 +267,27 @@ else:
result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen })
self.assertIn(f"libclang (used by the Rust bindings generator '{bindgen}') is too old.", result.stderr)
+ def test_bindgen_bad_libclang_22(self):
+ for (bindgen_version, libclang_version, expected_not_patched) in (
+ ("0.71.1", "21.1.0", self.Expected.SUCCESS),
+ ("0.71.1", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS),
+ ("0.71.1", "22.1.0", self.Expected.SUCCESS_WITH_WARNINGS),
+
+ ("0.72.0", "22.0.0", self.Expected.SUCCESS_WITH_WARNINGS),
+
+ ("0.72.1", "22.0.0", self.Expected.SUCCESS),
+ ):
+ with self.subTest(bindgen_version=bindgen_version, libclang_version=libclang_version):
+ cc = self.generate_clang(f"clang version {libclang_version}")
+ libclang_stderr = f"scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version {libclang_version} [-W#pragma-messages], err: false"
+ bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr)
+ result = self.run_script(expected_not_patched, { "BINDGEN": bindgen, "CC": cc })
+ if expected_not_patched == self.Expected.SUCCESS_WITH_WARNINGS:
+ self.assertIn(f"Rust bindings generator '{bindgen}' < 0.72.1 together with libclang >= 22", result.stderr)
+
+ bindgen = self.generate_bindgen(f"bindgen {bindgen_version}", libclang_stderr, libclang_22_patched=True)
+ result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen, "CC": cc })
+
def test_clang_matches_bindgen_libclang_different_bindgen(self):
bindgen = self.generate_bindgen_libclang("scripts/rust_is_available_bindgen_libclang.h:2:9: warning: clang version 999.0.0 [-W#pragma-messages], err: false")
result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen })
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index d61a77219a8c..d087c0d9fcb3 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -31,8 +31,15 @@
use std::{
fs,
fs::File,
- io::{BufWriter, Read, Write},
- path::{Path, PathBuf},
+ io::{
+ BufWriter,
+ Read,
+ Write, //
+ },
+ path::{
+ Path,
+ PathBuf, //
+ }, //
};
/// Find the real path to the original file based on the `file` portion of the test name.
@@ -232,6 +239,24 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut ::kernel::bindings::kunit) {{
const __LOG_PREFIX: &[u8] = b"rust_doctests_kernel\0";
+/// Dummy module type for doctest context.
+struct LocalModule;
+
+use kernel::{{
+ str::CStr,
+ ModuleMetadata,
+ ThisModule, //
+}};
+use core::ptr::null_mut;
+
+impl ModuleMetadata for LocalModule {{
+ const NAME: &'static CStr = c"rust_doctests_kernel";
+ const THIS_MODULE: ThisModule = {{
+ // SAFETY: `try_module_get`/`module_put` handle null module pointers gracefully.
+ unsafe {{ ThisModule::from_ptr(null_mut()) }}
+ }};
+}}
+
{rust_tests}
"#
)
diff --git a/scripts/sbom/sbom/cmd_graph/savedcmd_parser/savedcmd_parser.py b/scripts/sbom/sbom/cmd_graph/savedcmd_parser/savedcmd_parser.py
index 6a7ea4787aa1..d2ca842a7849 100644
--- a/scripts/sbom/sbom/cmd_graph/savedcmd_parser/savedcmd_parser.py
+++ b/scripts/sbom/sbom/cmd_graph/savedcmd_parser/savedcmd_parser.py
@@ -57,7 +57,7 @@ def parse_inputs_from_commands(
try:
inputs = matched_parser(single_command)
input_files.extend(inputs)
- except (CmdParsingError, IndexError) as e:
+ except (CmdParsingError, IndexError, ValueError) as e:
log_error_or_warning(
"Skipped parsing command {single_command} because of command parsing error: {error_message}",
single_command=single_command,
diff --git a/scripts/sbom/tests/cmd_graph/test_savedcmd_parser.py b/scripts/sbom/tests/cmd_graph/test_savedcmd_parser.py
index a061a748e1bf..d7776f072e03 100644
--- a/scripts/sbom/tests/cmd_graph/test_savedcmd_parser.py
+++ b/scripts/sbom/tests/cmd_graph/test_savedcmd_parser.py
@@ -19,6 +19,31 @@ class TestSavedCmdParser(unittest.TestCase):
errors = sbom_logging._error_logger._message_counts # type: ignore
self.assertEqual(errors, {})
+ # Error handling tests
+ def test_malformed_shell_quoting(self):
+ command = 'gcc "unterminated'
+ with patch.object(sbom_logging, "warning") as warning:
+ parsed = parse_inputs_from_commands(command, fail_on_unknown_build_command=False)
+
+ self.assertEqual(parsed, [])
+ warning.assert_called_once_with(
+ "Skipped parsing command {single_command} because of command parsing error: {error_message}",
+ single_command=command,
+ error_message="No closing quotation",
+ )
+
+ def test_missing_positional_argument(self):
+ command = "objcopy"
+ with patch.object(sbom_logging, "warning") as warning:
+ parsed = parse_inputs_from_commands(command, fail_on_unknown_build_command=False)
+
+ self.assertEqual(parsed, [])
+ warning.assert_called_once_with(
+ "Skipped parsing command {single_command} because of command parsing error: {error_message}",
+ single_command=command,
+ error_message="list index out of range",
+ )
+
# Compound command tests
def test_dd_cat(self):
cmd = "(dd if=arch/x86/boot/setup.bin bs=4k conv=sync status=none; cat arch/x86/boot/vmlinux.bin) >arch/x86/boot/bzImage"
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index e8ed11c680c6..d8dc2a1b7c31 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -891,17 +891,22 @@ static int do_file(char const *const fname, void *addr)
table_sort_t custom_sort = NULL;
switch (elf_map_machine(ehdr)) {
- case EM_AARCH64:
#ifdef MCOUNT_SORT_ENABLED
+ case EM_AARCH64:
+ /* arm64 also needs RELA-based weak-function fixups. */
sort_reloc = true;
rela_type = 0x403;
- /* arm64 uses patchable function entry placing before function */
+ /* fallthrough */
+ case EM_RISCV:
+ /* arm64 and RISC-V place patchable entries before the function. */
before_func = 8;
+#else
+ case EM_AARCH64:
+ case EM_RISCV:
#endif
/* fallthrough */
case EM_386:
case EM_LOONGARCH:
- case EM_RISCV:
case EM_S390:
case EM_X86_64:
custom_sort = sort_relative_table_with_data;
diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl
index 7a42b32b6577..0ab531605120 100644
--- a/scripts/syscall.tbl
+++ b/scripts/syscall.tbl
@@ -412,3 +412,4 @@
469 common file_setattr sys_file_setattr
470 common listns sys_listns
471 common rseq_slice_yield sys_rseq_slice_yield
+472 common fchroot sys_fchroot
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 243373683f98..41e38df96984 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -46,13 +46,31 @@ elif [ "${ALLSOURCE_ARCHS}" = "all" ]; then
ALLSOURCE_ARCHS=$(find ${tree}arch/ -mindepth 1 -maxdepth 1 -type d -printf '%f ')
fi
+setup_name_pattern()
+{
+ pattern=()
+ for ext; do
+ if [ ${#pattern[@]} -gt 0 ]; then
+ pattern+=("-o" "-name" "$ext")
+ else
+ pattern+=("(" "-name" "$ext")
+ fi
+ done
+ if [ ${#pattern[@]} -gt 0 ]; then
+ pattern+=(")")
+ fi
+}
+
# find sources in arch/$1
find_arch_sources()
{
for i in $archincludedir; do
local prune="$prune ( -path $i ) -prune -o"
done
- find ${tree}arch/$1 $ignore $prune -name "$2" -not -type l -print;
+ local src=${tree}arch/$1
+ shift
+ setup_name_pattern "$@"
+ find $src $ignore $prune "${pattern[@]}" -not -type l -print;
}
# find sources in arch/$1/include
@@ -61,14 +79,17 @@ find_arch_include_sources()
local include=$(find ${tree}arch/$1/ -name include -type d -print);
if [ -n "$include" ]; then
archincludedir="$archincludedir $include"
- find $include $ignore -name "$2" -not -type l -print;
+ shift
+ setup_name_pattern "$@"
+ find $include $ignore "${pattern[@]}" -not -type l -print;
fi
}
# find sources in include/
find_include_sources()
{
- find ${tree}include $ignore -name config -prune -o -name "$1" \
+ setup_name_pattern "$@"
+ find ${tree}include $ignore -name config -prune -o "${pattern[@]}" \
-not -type l -print;
}
@@ -76,23 +97,24 @@ find_include_sources()
# we could benefit from a list of dirs to search in here
find_other_sources()
{
+ setup_name_pattern "$@"
find ${tree}* $ignore \
\( -path ${tree}include -o -path ${tree}arch -o -name '.tmp_*' \) -prune -o \
- -name "$1" -not -type l -print;
+ "${pattern[@]}" -not -type l -print;
}
all_sources()
{
- find_arch_include_sources ${SRCARCH} '*.[chS]'
+ find_arch_include_sources ${SRCARCH} '*.[chS]' '*.rs'
if [ -n "$archinclude" ]; then
- find_arch_include_sources $archinclude '*.[chS]'
+ find_arch_include_sources $archinclude '*.[chS]' '*.rs'
fi
- find_include_sources '*.[chS]'
+ find_include_sources '*.[chS]' '*.rs'
for arch in $ALLSOURCE_ARCHS
do
- find_arch_sources $arch '*.[chS]'
+ find_arch_sources $arch '*.[chS]' '*.rs'
done
- find_other_sources '*.[chS]'
+ find_other_sources '*.[chS]' '*.rs'
}
all_compiled_sources()
@@ -100,7 +122,7 @@ all_compiled_sources()
{
echo include/generated/autoconf.h
find $ignore -name "*.cmd" -exec \
- grep -Poh '(?<=^ )\S+|(?<== )\S+[^\\](?=$)' {} \+ |
+ grep -Poh '(?<=^ )\S+\.([chS]|rs)(?=\s)|(?<== )\S+\.(?1)(?=$)' {} \+ |
awk '!a[$0]++'
} | xargs realpath -esq $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) |
sort -u