# git rev-parse -q --verify b4b27b9eed8ebdbf9f3046197d29d733c8c944f3^{commit} b4b27b9eed8ebdbf9f3046197d29d733c8c944f3 already have revision, skipping fetch # git checkout -q -f -B kisskb b4b27b9eed8ebdbf9f3046197d29d733c8c944f3 # git clean -qxdf # < git log -1 # commit b4b27b9eed8ebdbf9f3046197d29d733c8c944f3 # Author: Linus Torvalds # Date: Sun Jun 27 13:32:54 2021 -0700 # # Revert "signal: Allow tasks to cache one sigqueue struct" # # This reverts commits 4bad58ebc8bc4f20d89cff95417c9b4674769709 (and # 399f8dd9a866e107639eabd3c1979cd526ca3a98, which tried to fix it). # # I do not believe these are correct, and I'm about to release 5.13, so am # reverting them out of an abundance of caution. # # The locking is odd, and appears broken. # # On the allocation side (in __sigqueue_alloc()), the locking is somewhat # straightforward: it depends on sighand->siglock. Since one caller # doesn't hold that lock, it further then tests 'sigqueue_flags' to avoid # the case with no locks held. # # On the freeing side (in sigqueue_cache_or_free()), there is no locking # at all, and the logic instead depends on 'current' being a single # thread, and not able to race with itself. # # To make things more exciting, there's also the data race between freeing # a signal and allocating one, which is handled by using WRITE_ONCE() and # READ_ONCE(), and being mutually exclusive wrt the initial state (ie # freeing will only free if the old state was NULL, while allocating will # obviously only use the value if it was non-NULL, so only one or the # other will actually act on the value). # # However, while the free->alloc paths do seem mutually exclusive thanks # to just the data value dependency, it's not clear what the memory # ordering constraints are on it. Could writes from the previous # allocation possibly be delayed and seen by the new allocation later, # causing logical inconsistencies? # # So it's all very exciting and unusual. # # And in particular, it seems that the freeing side is incorrect in # depending on "current" being single-threaded. Yes, 'current' is a # single thread, but in the presense of asynchronous events even a single # thread can have data races. # # And such asynchronous events can and do happen, with interrupts causing # signals to be flushed and thus free'd (for example - sending a # SIGCONT/SIGSTOP can happen from interrupt context, and can flush # previously queued process control signals). # # So regardless of all the other questions about the memory ordering and # locking for this new cached allocation, the sigqueue_cache_or_free() # assumptions seem to be fundamentally incorrect. # # It may be that people will show me the errors of my ways, and tell me # why this is all safe after all. We can reinstate it if so. But my # current belief is that the WRITE_ONCE() that sets the cached entry needs # to be a smp_store_release(), and the READ_ONCE() that finds a cached # entry needs to be a smp_load_acquire() to handle memory ordering # correctly. # # And the sequence in sigqueue_cache_or_free() would need to either use a # lock or at least be interrupt-safe some way (perhaps by using something # like the percpu 'cmpxchg': it doesn't need to be SMP-safe, but like the # percpu operations it needs to be interrupt-safe). # # Fixes: 399f8dd9a866 ("signal: Prevent sigqueue caching after task got released") # Fixes: 4bad58ebc8bc ("signal: Allow tasks to cache one sigqueue struct") # Cc: Thomas Gleixner # Cc: Peter Zijlstra # Cc: Oleg Nesterov # Cc: Christian Brauner # Signed-off-by: Linus Torvalds # < /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-gcc --version # < /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-ld --version # < git log --format=%s --max-count=1 b4b27b9eed8ebdbf9f3046197d29d733c8c944f3 # < make -s -j 120 ARCH=arm O=/kisskb/build/linus_multi_v7_defconfig_arm-gcc4.9 CROSS_COMPILE=/opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi- multi_v7_defconfig # < make -s -j 120 ARCH=arm O=/kisskb/build/linus_multi_v7_defconfig_arm-gcc4.9 CROSS_COMPILE=/opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi- help # make -s -j 120 ARCH=arm O=/kisskb/build/linus_multi_v7_defconfig_arm-gcc4.9 CROSS_COMPILE=/opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi- olddefconfig # make -s -j 120 ARCH=arm O=/kisskb/build/linus_multi_v7_defconfig_arm-gcc4.9 CROSS_COMPILE=/opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi- In file included from /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabi/4.9.4/plugin/include/tm.h:23, from /kisskb/src/scripts/gcc-plugins/gcc-common.h:15, from /kisskb/src/scripts/gcc-plugins/arm_ssp_per_task_plugin.c:3: /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabi/4.9.4/plugin/include/config/elfos.h:102:21: warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix] fprintf ((FILE), "%s"HOST_WIDE_INT_PRINT_UNSIGNED"\n",\ ^ /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabi/4.9.4/plugin/include/config/elfos.h:170:24: warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix] fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \ ^ In file included from /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabi/4.9.4/plugin/include/tm.h:44, from /kisskb/src/scripts/gcc-plugins/gcc-common.h:15, from /kisskb/src/scripts/gcc-plugins/arm_ssp_per_task_plugin.c:3: /opt/cross/kisskb/korg/gcc-4.9.4-nolibc/arm-linux-gnueabi/bin/../lib/gcc/arm-linux-gnueabi/4.9.4/plugin/include/defaults.h:126:24: warning: invalid suffix on literal; C++11 requires a space between literal and string macro [-Wliteral-suffix] fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \ ^ cc1plus: warning: unrecognized command line option '-Wno-format-diag' /kisskb/src/arch/arm/crypto/ghash-ce-glue.c: In function 'ghash_do_update': /kisskb/src/arch/arm/crypto/ghash-ce-glue.c:67:44: warning: passing argument 4 of 'pmull_ghash_update_p64' from incompatible pointer type pmull_ghash_update_p64(blocks, dg, src, key->h, head); ^ /kisskb/src/arch/arm/crypto/ghash-ce-glue.c:45:17: note: expected 'const u64 (*)[2]' but argument is of type 'u64 (*)[2]' asmlinkage void pmull_ghash_update_p64(int blocks, u64 dg[], const char *src, ^ /kisskb/src/arch/arm/crypto/ghash-ce-glue.c:69:43: warning: passing argument 4 of 'pmull_ghash_update_p8' from incompatible pointer type pmull_ghash_update_p8(blocks, dg, src, key->h, head); ^ /kisskb/src/arch/arm/crypto/ghash-ce-glue.c:48:17: note: expected 'const u64 (*)[2]' but argument is of type 'u64 (*)[2]' asmlinkage void pmull_ghash_update_p8(int blocks, u64 dg[], const char *src, ^ /kisskb/src/net/sched/sch_frag.c: In function 'sch_fragment': /kisskb/src/net/sched/sch_frag.c:93:10: warning: missing braces around initializer [-Wmissing-braces] struct rtable sch_frag_rt = { 0 }; ^ /kisskb/src/net/sched/sch_frag.c:93:10: warning: (near initialization for 'sch_frag_rt.dst') [-Wmissing-braces] /kisskb/src/drivers/firmware/qcom_scm-legacy.c: In function 'scm_legacy_call': /kisskb/src/drivers/firmware/qcom_scm-legacy.c:139:9: warning: missing braces around initializer [-Wmissing-braces] struct arm_smccc_args smc = {0}; ^ /kisskb/src/drivers/firmware/qcom_scm-legacy.c:139:9: warning: (near initialization for 'smc.args') [-Wmissing-braces] /kisskb/src/drivers/firmware/qcom_scm-smc.c: In function '__scm_smc_call': /kisskb/src/drivers/firmware/qcom_scm-smc.c:95:9: warning: missing braces around initializer [-Wmissing-braces] struct arm_smccc_args smc = {0}; ^ /kisskb/src/drivers/firmware/qcom_scm-smc.c:95:9: warning: (near initialization for 'smc.args') [-Wmissing-braces] Completed OK # rm -rf /kisskb/build/linus_multi_v7_defconfig_arm-gcc4.9 # Build took: 0:02:06.955277