CC: [email protected]
CC: [email protected]
TO: Peter Zijlstra <[email protected]>
CC: "AndrĂ© Almeida" <[email protected]>

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
master
head:   ee1703cda8dc777e937dec172da55beaf1a74919
commit: a046f1a0d3e320cfee6bdac336416a537f49e7c6 futex: Split out wait/wake
date:   6 weeks ago
:::::: branch date: 4 hours ago
:::::: commit date: 6 weeks ago
config: m68k-randconfig-m031-20211117 (attached as .config)
compiler: m68k-linux-gcc (GCC) 11.2.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>

smatch warnings:
kernel/futex/waitwake.c:281 futex_wake_op() warn: bitwise AND condition is 
false here
kernel/futex/waitwake.c:417 futex_wait_setup() warn: bitwise AND condition is 
false here

vim +281 kernel/futex/waitwake.c

a046f1a0d3e320 Peter Zijlstra 2021-09-23  233  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  234  /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  235   * Wake up all waiters hashed on 
the physical page that is mapped
a046f1a0d3e320 Peter Zijlstra 2021-09-23  236   * to this virtual address:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  237   */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  238  int futex_wake_op(u32 __user 
*uaddr1, unsigned int flags, u32 __user *uaddr2,
a046f1a0d3e320 Peter Zijlstra 2021-09-23  239             int nr_wake, int 
nr_wake2, int op)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  240  {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  241   union futex_key key1 = 
FUTEX_KEY_INIT, key2 = FUTEX_KEY_INIT;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  242   struct futex_hash_bucket *hb1, 
*hb2;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  243   struct futex_q *this, *next;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  244   int ret, op_ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  245   DEFINE_WAKE_Q(wake_q);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  246  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  247  retry:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  248   ret = get_futex_key(uaddr1, 
flags & FLAGS_SHARED, &key1, FUTEX_READ);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  249   if (unlikely(ret != 0))
a046f1a0d3e320 Peter Zijlstra 2021-09-23  250           return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  251   ret = get_futex_key(uaddr2, 
flags & FLAGS_SHARED, &key2, FUTEX_WRITE);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  252   if (unlikely(ret != 0))
a046f1a0d3e320 Peter Zijlstra 2021-09-23  253           return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  254  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  255   hb1 = futex_hash(&key1);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  256   hb2 = futex_hash(&key2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  257  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  258  retry_private:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  259   double_lock_hb(hb1, hb2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  260   op_ret = 
futex_atomic_op_inuser(op, uaddr2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  261   if (unlikely(op_ret < 0)) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  262           double_unlock_hb(hb1, 
hb2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  263  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  264           if 
(!IS_ENABLED(CONFIG_MMU) ||
a046f1a0d3e320 Peter Zijlstra 2021-09-23  265               unlikely(op_ret != 
-EFAULT && op_ret != -EAGAIN)) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  266                   /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  267                    * we don't get 
EFAULT from MMU faults if we don't have
a046f1a0d3e320 Peter Zijlstra 2021-09-23  268                    * an MMU, but 
we might get them from range checking
a046f1a0d3e320 Peter Zijlstra 2021-09-23  269                    */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  270                   ret = op_ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  271                   return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  272           }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  273  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  274           if (op_ret == -EFAULT) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  275                   ret = 
fault_in_user_writeable(uaddr2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  276                   if (ret)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  277                           return 
ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  278           }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  279  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  280           cond_resched();
a046f1a0d3e320 Peter Zijlstra 2021-09-23 @281           if (!(flags & 
FLAGS_SHARED))
a046f1a0d3e320 Peter Zijlstra 2021-09-23  282                   goto 
retry_private;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  283           goto retry;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  284   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  285  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  286   plist_for_each_entry_safe(this, 
next, &hb1->chain, list) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  287           if (futex_match 
(&this->key, &key1)) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  288                   if 
(this->pi_state || this->rt_waiter) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  289                           ret = 
-EINVAL;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  290                           goto 
out_unlock;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  291                   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  292                   
futex_wake_mark(&wake_q, this);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  293                   if (++ret >= 
nr_wake)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  294                           break;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  295           }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  296   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  297  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  298   if (op_ret > 0) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  299           op_ret = 0;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  300           
plist_for_each_entry_safe(this, next, &hb2->chain, list) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  301                   if (futex_match 
(&this->key, &key2)) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  302                           if 
(this->pi_state || this->rt_waiter) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  303                                   
ret = -EINVAL;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  304                                   
goto out_unlock;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  305                           }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  306                           
futex_wake_mark(&wake_q, this);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  307                           if 
(++op_ret >= nr_wake2)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  308                                   
break;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  309                   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  310           }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  311           ret += op_ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  312   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  313  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  314  out_unlock:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  315   double_unlock_hb(hb1, hb2);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  316   wake_up_q(&wake_q);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  317   return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  318  }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  319  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  320  static long 
futex_wait_restart(struct restart_block *restart);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  321  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  322  /**
a046f1a0d3e320 Peter Zijlstra 2021-09-23  323   * futex_wait_queue() - 
futex_queue() and wait for wakeup, timeout, or signal
a046f1a0d3e320 Peter Zijlstra 2021-09-23  324   * @hb:          the futex hash 
bucket, must be locked by the caller
a046f1a0d3e320 Peter Zijlstra 2021-09-23  325   * @q:           the futex_q to 
queue up on
a046f1a0d3e320 Peter Zijlstra 2021-09-23  326   * @timeout:     the prepared 
hrtimer_sleeper, or null for no timeout
a046f1a0d3e320 Peter Zijlstra 2021-09-23  327   */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  328  void futex_wait_queue(struct 
futex_hash_bucket *hb, struct futex_q *q,
a046f1a0d3e320 Peter Zijlstra 2021-09-23  329                       struct 
hrtimer_sleeper *timeout)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  330  {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  331   /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  332    * The task state is guaranteed 
to be set before another task can
a046f1a0d3e320 Peter Zijlstra 2021-09-23  333    * wake it. set_current_state() 
is implemented using smp_store_mb() and
a046f1a0d3e320 Peter Zijlstra 2021-09-23  334    * futex_queue() calls 
spin_unlock() upon completion, both serializing
a046f1a0d3e320 Peter Zijlstra 2021-09-23  335    * access to the hash list and 
forcing another memory barrier.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  336    */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  337   
set_current_state(TASK_INTERRUPTIBLE);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  338   futex_queue(q, hb);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  339  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  340   /* Arm the timer */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  341   if (timeout)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  342           
hrtimer_sleeper_start_expires(timeout, HRTIMER_MODE_ABS);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  343  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  344   /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  345    * If we have been removed from 
the hash list, then another task
a046f1a0d3e320 Peter Zijlstra 2021-09-23  346    * has tried to wake us, and we 
can skip the call to schedule().
a046f1a0d3e320 Peter Zijlstra 2021-09-23  347    */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  348   if 
(likely(!plist_node_empty(&q->list))) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  349           /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  350            * If the timer has 
already expired, current will already be
a046f1a0d3e320 Peter Zijlstra 2021-09-23  351            * flagged for 
rescheduling. Only call schedule if there
a046f1a0d3e320 Peter Zijlstra 2021-09-23  352            * is no timeout, or if 
it has yet to expire.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  353            */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  354           if (!timeout || 
timeout->task)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  355                   
freezable_schedule();
a046f1a0d3e320 Peter Zijlstra 2021-09-23  356   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  357   
__set_current_state(TASK_RUNNING);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  358  }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  359  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  360  /**
a046f1a0d3e320 Peter Zijlstra 2021-09-23  361   * futex_wait_setup() - Prepare 
to wait on a futex
a046f1a0d3e320 Peter Zijlstra 2021-09-23  362   * @uaddr:       the futex 
userspace address
a046f1a0d3e320 Peter Zijlstra 2021-09-23  363   * @val: the expected value
a046f1a0d3e320 Peter Zijlstra 2021-09-23  364   * @flags:       futex flags 
(FLAGS_SHARED, etc.)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  365   * @q:           the associated 
futex_q
a046f1a0d3e320 Peter Zijlstra 2021-09-23  366   * @hb:          storage for 
hash_bucket pointer to be returned to caller
a046f1a0d3e320 Peter Zijlstra 2021-09-23  367   *
a046f1a0d3e320 Peter Zijlstra 2021-09-23  368   * Setup the futex_q and locate 
the hash_bucket.  Get the futex value and
a046f1a0d3e320 Peter Zijlstra 2021-09-23  369   * compare it with the expected 
value.  Handle atomic faults internally.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  370   * Return with the hb lock held 
on success, and unlocked on failure.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  371   *
a046f1a0d3e320 Peter Zijlstra 2021-09-23  372   * Return:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  373   *  -  0 - uaddr contains val 
and hb has been locked;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  374   *  - <1 - -EFAULT or 
-EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
a046f1a0d3e320 Peter Zijlstra 2021-09-23  375   */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  376  int futex_wait_setup(u32 __user 
*uaddr, u32 val, unsigned int flags,
a046f1a0d3e320 Peter Zijlstra 2021-09-23  377                struct futex_q *q, 
struct futex_hash_bucket **hb)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  378  {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  379   u32 uval;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  380   int ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  381  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  382   /*
a046f1a0d3e320 Peter Zijlstra 2021-09-23  383    * Access the page AFTER the 
hash-bucket is locked.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  384    * Order is important:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  385    *
a046f1a0d3e320 Peter Zijlstra 2021-09-23  386    *   Userspace waiter: val = 
var; if (cond(val)) futex_wait(&var, val);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  387    *   Userspace waker:  if 
(cond(var)) { var = new; futex_wake(&var); }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  388    *
a046f1a0d3e320 Peter Zijlstra 2021-09-23  389    * The basic logical guarantee 
of a futex is that it blocks ONLY
a046f1a0d3e320 Peter Zijlstra 2021-09-23  390    * if cond(var) is known to be 
true at the time of blocking, for
a046f1a0d3e320 Peter Zijlstra 2021-09-23  391    * any cond.  If we locked the 
hash-bucket after testing *uaddr, that
a046f1a0d3e320 Peter Zijlstra 2021-09-23  392    * would open a race condition 
where we could block indefinitely with
a046f1a0d3e320 Peter Zijlstra 2021-09-23  393    * cond(var) false, which would 
violate the guarantee.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  394    *
a046f1a0d3e320 Peter Zijlstra 2021-09-23  395    * On the other hand, we insert 
q and release the hash-bucket only
a046f1a0d3e320 Peter Zijlstra 2021-09-23  396    * after testing *uaddr.  This 
guarantees that futex_wait() will NOT
a046f1a0d3e320 Peter Zijlstra 2021-09-23  397    * absorb a wakeup if *uaddr 
does not match the desired values
a046f1a0d3e320 Peter Zijlstra 2021-09-23  398    * while the syscall executes.
a046f1a0d3e320 Peter Zijlstra 2021-09-23  399    */
a046f1a0d3e320 Peter Zijlstra 2021-09-23  400  retry:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  401   ret = get_futex_key(uaddr, 
flags & FLAGS_SHARED, &q->key, FUTEX_READ);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  402   if (unlikely(ret != 0))
a046f1a0d3e320 Peter Zijlstra 2021-09-23  403           return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  404  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  405  retry_private:
a046f1a0d3e320 Peter Zijlstra 2021-09-23  406   *hb = futex_q_lock(q);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  407  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  408   ret = 
futex_get_value_locked(&uval, uaddr);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  409  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  410   if (ret) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  411           futex_q_unlock(*hb);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  412  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  413           ret = get_user(uval, 
uaddr);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  414           if (ret)
a046f1a0d3e320 Peter Zijlstra 2021-09-23  415                   return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  416  
a046f1a0d3e320 Peter Zijlstra 2021-09-23 @417           if (!(flags & 
FLAGS_SHARED))
a046f1a0d3e320 Peter Zijlstra 2021-09-23  418                   goto 
retry_private;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  419  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  420           goto retry;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  421   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  422  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  423   if (uval != val) {
a046f1a0d3e320 Peter Zijlstra 2021-09-23  424           futex_q_unlock(*hb);
a046f1a0d3e320 Peter Zijlstra 2021-09-23  425           ret = -EWOULDBLOCK;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  426   }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  427  
a046f1a0d3e320 Peter Zijlstra 2021-09-23  428   return ret;
a046f1a0d3e320 Peter Zijlstra 2021-09-23  429  }
a046f1a0d3e320 Peter Zijlstra 2021-09-23  430  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]

Attachment: .config.gz
Description: application/gzip

_______________________________________________
kbuild mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to