On Thu, Apr 28, 2022 at 03:49:11PM -0500, Eric W. Biederman wrote:

> static void lock_parents_siglocks(bool lock_tracer)
>       __releases(&current->sighand->siglock)
>       __acquires(&current->sighand->siglock)
>       __acquires(&current->real_parent->sighand->siglock)
>       __acquires(&current->parent->sighand->siglock)
> {
>       struct task_struct *me = current;
>       struct sighand_struct *m_sighand = me->sighand;
> 
>       lockdep_assert_held(&m_sighand->siglock);
> 
>       rcu_read_lock();
>       for (;;) {
>               struct task_struct *parent, *tracer;
>               struct sighand_struct *p_sighand, *t_sighand, *s1, *s2, *s3;
> 
>               parent = me->real_parent;
>               tracer = lock_tracer? me->parent : parent;
> 
>               p_sighand = rcu_dereference(parent->sighand);
>               t_sighand = rcu_dereference(tracer->sighand);
> 
>               /* Sort the sighands so that s1 >= s2 >= s3 */
>               s1 = m_sighand;
>               s2 = p_sighand;
>               s3 = t_sighand;
>               if (s1 > s2)
>                       swap(s1, s2);
>               if (s1 > s3)
>                       swap(s1, s3);
>               if (s2 > s3)
>                       swap(s2, s3);
> 
>               if (s1 != m_sighand) {
>                       spin_unlock(&m_sighand->siglock);
>                       spin_lock(&s1->siglock);
>               }
> 
>               if (s1 != s2)
>                       spin_lock_nested(&s2->siglock, SIGLOCK_LOCK_SECOND);
>               if (s2 != s3)
>                       spin_lock_nested(&s3->siglock, SIGLOCK_LOCK_THIRD);
> 

Might as well just use 1 and 2 for subclass at this point, or use
SIGLOCK_LOCK_FIRST below.

>               if (likely((me->real_parent == parent) &&
>                          (me->parent == tracer) &&
>                          (parent->sighand == p_sighand) &&
>                          (tracer->sighand == t_sighand))) {
>                       break;
>               }
>               spin_unlock(&p_sighand->siglock);
>                 if (t_sighand != p_sighand)
>                       spin_unlock(&t_sighand->siglock);

Indent fail above ^, also you likey need this:

                /*
                 * Since [pt]_sighand will likely change if we go
                 * around, and m_sighand is the only one held, make sure
                 * it is subclass-0, since the above 's1 != m_sighand'
                 * clause very much relies on that.
                 */
                lock_set_subclass(&m_sighand->siglock, 0, _RET_IP_);

>               continue;
>       }
>       rcu_read_unlock();
> }
> 
> Eric

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

Reply via email to