tree: https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-5.14.y-rt-rebase head: 0eead4e5a60cb716ec911a552787a69332cf6943 commit: 7384201f9701c226cb1dd04cf76c12c33762bb30 [143/245] futex: Validate waiter correctly in futex_proxy_trylock_atomic() config: mips-randconfig-c004-20210816 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 44d0a99a12ec7ead4d2f5ef649ba05b40f6d463d) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu # https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git/commit/?id=7384201f9701c226cb1dd04cf76c12c33762bb30 git remote add linux-rt-devel https://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git git fetch --no-tags linux-rt-devel linux-5.14.y-rt-rebase git checkout 7384201f9701c226cb1dd04cf76c12c33762bb30 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=mips clang-analyzer If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot clang-analyzer warnings: (new ones prefixed by >>) ^ kernel/futex.c:3714:6: note: Assuming the condition is false if (op & FUTEX_CLOCK_REALTIME) { ^~~~~~~~~~~~~~~~~~~~~~~~~ kernel/futex.c:3714:2: note: Taking false branch if (op & FUTEX_CLOCK_REALTIME) { ^ kernel/futex.c:3721:2: note: 'Default' branch taken. Execution continues on line 3732 switch (cmd) { ^ kernel/futex.c:3732:2: note: Control jumps to 'case 5:' at line 3747 switch (cmd) { ^ kernel/futex.c:3748:10: note: Calling 'futex_wake_op' return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/futex.c:1699:2: note: Taking false branch if (unlikely(ret != 0)) ^ kernel/futex.c:1702:2: note: Taking false branch if (unlikely(ret != 0)) ^ kernel/futex.c:1710:11: note: Calling 'futex_atomic_op_inuser' op_ret = futex_atomic_op_inuser(op, uaddr2); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/futex.c:1643:6: note: 'oldval' declared without an initial value int oldval, ret; ^~~~~~ kernel/futex.c:1645:6: note: Assuming the condition is false if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/futex.c:1645:2: note: Taking false branch if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) { ^ kernel/futex.c:1660:8: note: Calling 'arch_futex_atomic_op_inuser' ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ arch/mips/include/asm/futex.h:92:7: note: Assuming the condition is false if (!access_ok(uaddr, sizeof(u32))) ^ arch/mips/include/asm/uaccess.h:88:2: note: expanded from macro 'access_ok' likely(__access_ok((addr), (size))) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:77:38: note: expanded from macro 'likely' # define likely(x) __builtin_expect(!!(x), 1) ^~~~ arch/mips/include/asm/futex.h:92:2: note: Taking false branch if (!access_ok(uaddr, sizeof(u32))) ^ arch/mips/include/asm/futex.h:95:2: note: Control jumps to 'case 3:' at line 108 switch (op) { ^ arch/mips/include/asm/futex.h:109:3: note: Left side of '&&' is true __futex_atomic_op("and $1, %1, %z5", ^ arch/mips/include/asm/futex.h:24:6: note: expanded from macro '__futex_atomic_op' if (cpu_has_llsc && IS_ENABLED(CONFIG_WAR_R10000_LLSC)) { \ ^ arch/mips/include/asm/mach-rc32434/cpu-feature-overrides.h:34:24: note: expanded from macro 'cpu_has_llsc' #define cpu_has_llsc 1 ^ arch/mips/include/asm/futex.h:109:3: note: Taking false branch __futex_atomic_op("and $1, %1, %z5", ^ arch/mips/include/asm/futex.h:24:2: note: expanded from macro '__futex_atomic_op' if (cpu_has_llsc && IS_ENABLED(CONFIG_WAR_R10000_LLSC)) { \ ^ arch/mips/include/asm/futex.h:109:3: note: Taking true branch __futex_atomic_op("and $1, %1, %z5", ^ arch/mips/include/asm/futex.h:53:9: note: expanded from macro '__futex_atomic_op' } else if (cpu_has_llsc) { \ ^ arch/mips/include/asm/futex.h:111:3: note: Execution continues on line 120 break; ^ arch/mips/include/asm/futex.h:120:6: note: Assuming 'ret' is not equal to 0 if (!ret) ^~~~ arch/mips/include/asm/futex.h:120:2: note: Taking false branch if (!ret) ^ arch/mips/include/asm/futex.h:123:2: note: Returning without writing to '*oval' return ret; ^ kernel/futex.c:1660:8: note: Returning from 'arch_futex_atomic_op_inuser' ret = arch_futex_atomic_op_inuser(op, oparg, &oldval, uaddr); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ kernel/futex.c:1662:6: note: Assuming 'ret' is 0 if (ret) ^~~ kernel/futex.c:1662:2: note: Taking false branch if (ret) ^ kernel/futex.c:1665:2: note: Control jumps to 'case 4:' at line 1676 switch (cmp) { ^ kernel/futex.c:1677:17: note: The left operand of '>' is a garbage value return oldval > cmparg; ~~~~~~ ^ >> kernel/futex.c:1887:3: warning: Value stored to 'ret' is never read [clang-analyzer-deadcode.DeadStores] ret = -EINVAL; ^ ~~~~~~~ kernel/futex.c:1887:3: note: Value stored to 'ret' is never read ret = -EINVAL; ^ ~~~~~~~ Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 3 warnings generated. Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 3 warnings generated. Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 5 warnings generated. drivers/soundwire/stream.c:847:10: warning: Use of memory after it is freed [clang-analyzer-unix.Malloc] kfree(bus->defer_msg.msg->buf); ^ drivers/soundwire/stream.c:1755:6: note: Assuming 'stream' is non-null if (!stream) { ^~~~~~~ drivers/soundwire/stream.c:1755:2: note: Taking false branch if (!stream) { ^ drivers/soundwire/stream.c:1762:6: note: Assuming field 'state' is equal to SDW_STREAM_ENABLED if (stream->state != SDW_STREAM_ENABLED) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/soundwire/stream.c:1762:2: note: Taking false branch if (stream->state != SDW_STREAM_ENABLED) { ^ drivers/soundwire/stream.c:1769:8: note: Calling '_sdw_disable_stream' ret = _sdw_disable_stream(stream); ^~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/soundwire/stream.c:1700:2: note: Left side of '&&' is false list_for_each_entry(m_rt, &stream->master_list, stream_node) { ^ include/linux/list.h:628:13: note: expanded from macro 'list_for_each_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^ include/linux/list.h:522:2: note: expanded from macro 'list_first_entry' list_entry((ptr)->next, type, member) ^ include/linux/list.h:511:2: note: expanded from macro 'list_entry' container_of(ptr, type, member) ^ include/linux/kernel.h:495:61: note: expanded from macro 'container_of' BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ^ drivers/soundwire/stream.c:1700:2: note: Taking false branch list_for_each_entry(m_rt, &stream->master_list, stream_node) { ^ include/linux/list.h:628:13: note: expanded from macro 'list_for_each_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^ include/linux/list.h:522:2: note: expanded from macro 'list_first_entry' list_entry((ptr)->next, type, member) ^ include/linux/list.h:511:2: note: expanded from macro 'list_entry' container_of(ptr, type, member) ^ note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) include/linux/compiler_types.h:328:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ include/linux/compiler_types.h:316:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ include/linux/compiler_types.h:308:3: note: expanded from macro '__compiletime_assert' if (!(condition)) \ ^ drivers/soundwire/stream.c:1700:2: note: Loop condition is false. Exiting loop list_for_each_entry(m_rt, &stream->master_list, stream_node) { ^ include/linux/list.h:628:13: note: expanded from macro 'list_for_each_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^ include/linux/list.h:522:2: note: expanded from macro 'list_first_entry' list_entry((ptr)->next, type, member) ^ include/linux/list.h:511:2: note: expanded from macro 'list_entry' container_of(ptr, type, member) ^ note: (skipping 2 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) include/linux/compiler_types.h:328:2: note: expanded from macro 'compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ include/linux/compiler_types.h:316:2: note: expanded from macro '_compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^ include/linux/compiler_types.h:306:2: note: expanded from macro '__compiletime_assert' do { \ ^ drivers/soundwire/stream.c:1700:2: note: Loop condition is false. Execution continues on line 1710 list_for_each_entry(m_rt, &stream->master_list, stream_node) { ^ include/linux/list.h:628:2: note: expanded from macro 'list_for_each_entry' for (pos = list_first_entry(head, typeof(*pos), member); \ ^ drivers/soundwire/stream.c:1712:2: note: Left side of '&&' is false list_for_each_entry(m_rt, &stream->master_list, stream_node) { ^ vim +/ret +1887 kernel/futex.c 1825 1826 /** 1827 * futex_proxy_trylock_atomic() - Attempt an atomic lock for the top waiter 1828 * @pifutex: the user address of the to futex 1829 * @hb1: the from futex hash bucket, must be locked by the caller 1830 * @hb2: the to futex hash bucket, must be locked by the caller 1831 * @key1: the from futex key 1832 * @key2: the to futex key 1833 * @ps: address to store the pi_state pointer 1834 * @exiting: Pointer to store the task pointer of the owner task 1835 * which is in the middle of exiting 1836 * @set_waiters: force setting the FUTEX_WAITERS bit (1) or not (0) 1837 * 1838 * Try and get the lock on behalf of the top waiter if we can do it atomically. 1839 * Wake the top waiter if we succeed. If the caller specified set_waiters, 1840 * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit. 1841 * hb1 and hb2 must be held by the caller. 1842 * 1843 * @exiting is only set when the return value is -EBUSY. If so, this holds 1844 * a refcount on the exiting task on return and the caller needs to drop it 1845 * after waiting for the exit to complete. 1846 * 1847 * Return: 1848 * - 0 - failed to acquire the lock atomically; 1849 * - >0 - acquired the lock, return value is vpid of the top_waiter 1850 * - <0 - error 1851 */ 1852 static int 1853 futex_proxy_trylock_atomic(u32 __user *pifutex, struct futex_hash_bucket *hb1, 1854 struct futex_hash_bucket *hb2, union futex_key *key1, 1855 union futex_key *key2, struct futex_pi_state **ps, 1856 struct task_struct **exiting, int set_waiters) 1857 { 1858 struct futex_q *top_waiter = NULL; 1859 u32 curval; 1860 int ret, vpid; 1861 1862 if (get_futex_value_locked(&curval, pifutex)) 1863 return -EFAULT; 1864 1865 if (unlikely(should_fail_futex(true))) 1866 return -EFAULT; 1867 1868 /* 1869 * Find the top_waiter and determine if there are additional waiters. 1870 * If the caller intends to requeue more than 1 waiter to pifutex, 1871 * force futex_lock_pi_atomic() to set the FUTEX_WAITERS bit now, 1872 * as we have means to handle the possible fault. If not, don't set 1873 * the bit unnecessarily as it will force the subsequent unlock to enter 1874 * the kernel. 1875 */ 1876 top_waiter = futex_top_waiter(hb1, key1); 1877 1878 /* There are no waiters, nothing for us to do. */ 1879 if (!top_waiter) 1880 return 0; 1881 1882 /* 1883 * Ensure that this is a waiter sitting in futex_wait_requeue_pi() 1884 * and waiting on the 'waitqueue' futex which is always !PI. 1885 */ 1886 if (!top_waiter->rt_waiter || top_waiter->pi_state) > 1887 ret = -EINVAL; 1888 1889 /* Ensure we requeue to the expected futex. */ 1890 if (!match_futex(top_waiter->requeue_pi_key, key2)) 1891 return -EINVAL; 1892 1893 /* 1894 * Try to take the lock for top_waiter. Set the FUTEX_WAITERS bit in 1895 * the contended case or if set_waiters is 1. The pi_state is returned 1896 * in ps in contended cases. 1897 */ 1898 vpid = task_pid_vnr(top_waiter->task); 1899 ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, 1900 exiting, set_waiters); 1901 if (ret == 1) { 1902 requeue_pi_wake_futex(top_waiter, key2, hb2); 1903 return vpid; 1904 } 1905 return ret; 1906 } 1907 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org