summaryrefslogtreecommitdiffstats
path: root/scripts/diffconfig
diff options
context:
space:
mode:
authorFedor Pchelkin <pchelkin@ispras.ru>2026-08-31 10:58:09 +0300
committerMika Westerberg <mika.westerberg@linux.intel.com>2026-09-02 09:07:46 +0200
commit4310c6b8e75d6a47f7548e5948fbe6318aa4440a (patch)
tree0032b584d8e218681a48126eb91f57091c351b83 /scripts/diffconfig
downloadlinux-stable-4310c6b8e75d6a47f7548e5948fbe6318aa4440a.tar.gz
linux-stable-4310c6b8e75d6a47f7548e5948fbe6318aa4440a.zip
thunderbolt: Fix NULL dereference in tb_remove_work()grafted
There is a slight race between tb_remove_work() and tb_domain_remove() which leads to dereferencing a NULL tb->root_switch pointer inside tb_free_unplugged_xdomains(): Thread A Thread B tb_remove_work() tb_domain_remove() mutex_lock(&tb->lock) tb_stop() /* doesn't cancel a running callback */ cancel_delayed_work(&tcm->remove_work) ... tb_switch_remove(tb->root_switch) tb->root_switch = NULL mutex_unlock(&tb->lock) mutex_lock(&tb->lock) ... /* without checking ->root_switch */ tb_free_unplugged_xdomains(tb->root_switch) mutex_unlock(&tb->lock) Commit a8937f35cf39 ("thunderbolt: Remove XDomain from the bus without holding tb->lock") doesn't seem right to move tb_free_unplugged_xdomains() out of the &tb->lock section and the check for tb->root_switch, in particular. It states: For this reason separate removing the XDomain from the topology data structures (where we need the lock) from unregistering the device from the bus (where remove callbacks of the drivers are being called). tb_free_unplugged_xdomains() belongs to the former group of functions requiring the lock. And it also calls tb_xdomain_remove() which should only be called with &tb->lock held. Found by Linux Verification Center (linuxtesting.org) with Svace static analysis tool. Fixes: a8937f35cf39 ("thunderbolt: Remove XDomain from the bus without holding tb->lock") Cc: stable@vger.kernel.org Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'scripts/diffconfig')
-rwxr-xr-xscripts/diffconfig144
1 files changed, 144 insertions, 0 deletions
diff --git a/scripts/diffconfig b/scripts/diffconfig
new file mode 100755
index 000000000..43f0f3d27
--- /dev/null
+++ b/scripts/diffconfig
@@ -0,0 +1,144 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# diffconfig - a tool to compare .config files.
+#
+# originally written in 2006 by Matt Mackall
+# (at least, this was in his bloatwatch source code)
+# last worked on 2008 by Tim Bird
+#
+
+import sys, os
+
+def usage():
+ print("""Usage: diffconfig [-h] [-m] [<config1> <config2>]
+
+Diffconfig is a simple utility for comparing two .config files.
+Using standard diff to compare .config files often includes extraneous and
+distracting information. This utility produces sorted output with only the
+changes in configuration values between the two files.
+
+Added and removed items are shown with a leading plus or minus, respectively.
+Changed items show the old and new values on a single line.
+
+If -m is specified, then output will be in "merge" style, which has the
+changed and new values in kernel config option format.
+
+If no config files are specified, .config and .config.old are used.
+
+Example usage:
+ $ diffconfig .config config-with-some-changes
+-EXT2_FS_XATTR n
+ CRAMFS n -> y
+ EXT2_FS y -> n
+ LOG_BUF_SHIFT 14 -> 16
+ PRINTK_TIME n -> y
+""")
+ sys.exit(0)
+
+# returns a dictionary of name/value pairs for config items in the file
+def readconfig(config_file):
+ d = {}
+ for line in config_file:
+ line = line[:-1]
+ if line[:7] == "CONFIG_":
+ name, val = line[7:].split("=", 1)
+ d[name] = val
+ if line[-11:] == " is not set":
+ d[line[9:-11]] = "n"
+ return d
+
+def print_config(op, config, value, new_value):
+ global merge_style
+
+ if merge_style:
+ if new_value:
+ if new_value=="n":
+ print("# CONFIG_%s is not set" % config)
+ else:
+ print("CONFIG_%s=%s" % (config, new_value))
+ else:
+ if op=="-":
+ print("-%s %s" % (config, value))
+ elif op=="+":
+ print("+%s %s" % (config, new_value))
+ else:
+ print(" %s %s -> %s" % (config, value, new_value))
+
+def show_diff():
+ global merge_style
+
+ # parse command line args
+ if ("-h" in sys.argv or "--help" in sys.argv):
+ usage()
+
+ merge_style = 0
+ if "-m" in sys.argv:
+ merge_style = 1
+ sys.argv.remove("-m")
+
+ argc = len(sys.argv)
+ if not (argc==1 or argc == 3):
+ print("Error: incorrect number of arguments or unrecognized option")
+ usage()
+
+ if argc == 1:
+ # if no filenames given, assume .config and .config.old
+ build_dir=""
+ if "KBUILD_OUTPUT" in os.environ:
+ build_dir = os.environ["KBUILD_OUTPUT"]+"/"
+ configa_filename = build_dir + ".config.old"
+ configb_filename = build_dir + ".config"
+ else:
+ configa_filename = sys.argv[1]
+ configb_filename = sys.argv[2]
+
+ try:
+ a = readconfig(open(configa_filename))
+ b = readconfig(open(configb_filename))
+ except (IOError):
+ e = sys.exc_info()[1]
+ print("I/O error[%s]: %s\n" % (e.args[0],e.args[1]))
+ usage()
+
+ # print items in a but not b (accumulate, sort and print)
+ old = []
+ for config in a:
+ if config not in b:
+ old.append(config)
+ old.sort()
+ for config in old:
+ print_config("-", config, a[config], None)
+ del a[config]
+
+ # print items that changed (accumulate, sort, and print)
+ changed = []
+ for config in a:
+ if a[config] != b[config]:
+ changed.append(config)
+ else:
+ del b[config]
+ changed.sort()
+ for config in changed:
+ print_config("->", config, a[config], b[config])
+ del b[config]
+
+ # now print items in b but not in a
+ # (items from b that were in a were removed above)
+ new = sorted(b.keys())
+ for config in new:
+ print_config("+", config, None, b[config])
+
+def main():
+ try:
+ show_diff()
+ except BrokenPipeError:
+ # Python flushes standard streams on exit; redirect remaining output
+ # to devnull to avoid another BrokenPipeError at shutdown
+ devnull = os.open(os.devnull, os.O_WRONLY)
+ os.dup2(devnull, sys.stdout.fileno())
+ sys.exit(1) # Python exits with error code 1 on EPIPE
+
+
+if __name__ == '__main__':
+ main()