Подробности
        
                          [В начало]
Проблема в реализации № L0011
Краткое описание
drivers/hid/hidraw.c: Двойной mutex_lock
Подробное описание
В драйвере drivers/hid/hidraw.c в функции hidraw_read может быть двойной mutex_lock:
Путь:
  45        struct hidraw_list *list = file->private_data;
  46        int ret = 0, len;
  47        char *report;
  48        DECLARE_WAITQUEUE(wait, current);
  49
  50        while (ret == 0) {
  51
  52                mutex_lock(&list->read_mutex);
  53
  54                if (list->head == list->tail) {
  55                        add_wait_queue(&list->hidraw->wait, &wait);
  56                        set_current_state(TASK_INTERRUPTIBLE);
  57
  58                        while (list->head == list->tail) {
  59                                if (file->f_flags & O_NONBLOCK) {
  60                                        ret = -EAGAIN;
  61                                        break;
  62                                }
  63                                if (signal_pending(current)) {
  64                                        ret = -ERESTARTSYS;
  65                                        break;
  66                                }
  67                                if (!list->hidraw->exist) {
  68                                        ret = -EIO;
  69                                        break;
  70                                }
  71
  72                                /* allow O_NONBLOCK to work well from other threads */
  73                                mutex_unlock(&list->read_mutex);
  74                                schedule();
  75                                mutex_lock(&list->read_mutex);
  76                                set_current_state(TASK_INTERRUPTIBLE);
  77                        }
  78
  79                        set_current_state(TASK_RUNNING);
  80                        remove_wait_queue(&list->hidraw->wait, &wait);
  81                }
  82
  83                if (ret)
  84                        goto out;
  85
  86                report = list->buffer[list->tail].value;
  87                len = list->buffer[list->tail].len > count ?
  88                        count : list->buffer[list->tail].len;
  89
  90                if (copy_to_user(buffer, list->buffer[list->tail].value, len)) {
  91                        ret = -EFAULT;
  92                        goto out;
  93                }
  94                ret += len;
  95
  96                kfree(list->buffer[list->tail].value);
  97                list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
  98        }
  99out:
 100        mutex_unlock(&list->read_mutex);
 101        return ret;
                    Компонент
linux-kernel 2.6.31
Принято
http://lkml.org/lkml/2009/10/12/101
commit
Статус
Исправлено в ядре 2.6.35
[В начало]