[pso] [T2 Linux] Race conditions in exemplul de char device din enuntul temei

Stefan Bucur stefan.bucur at gmail.com
Wed Aug 20 21:11:22 EEST 2008


Salut!

Poate nu am luat in considerare toate aspectele, insa am impresia ca
exemplul de char device de conversie upper-case dat ca punct de
pornire este gresit pentru ca permite situatii de race (nu neaparat
pt. sisteme SMP). Structura:

struct case_dev {
    struct cdev cdev;
    char buffer[BUFFER_SIZE];
    unsigned put, get;
    atomic_t fill;
    wait_queue_head_t wq_reads, wq_writes;
} devs[CASE_MAX_MINORS];

este sincronizata doar la nivelul campului fill, incat codul urmator
poate genera o situatie de race:

static int case_read(struct file *file, char *user_buffer,
        size_t size, loff_t *offset)
{
        int i=0;
	struct case_dev *dev=(struct case_dev*)file->private_data;


	if (file->f_mode&O_NONBLOCK) {
		if (atomic_read(&dev->fill) == 0)
			return -EAGAIN;
	} else {
		if (wait_event_interruptible(dev->wq_reads, atomic_read(&dev->fill) > 0))
                        return -ERESTARTSYS;
        }

        while ((atomic_read(&dev->fill)>0) && size) {
                if (put_user(dev->buffer[dev->get], &user_buffer[i]))
                        return -EFAULT;
                dev->get++; dev->get%=BUFFER_SIZE;
                i++; size--; atomic_dec(&dev->fill);
        }

        if (atomic_read(&dev->fill) < BUFFER_SIZE)
                wake_up(&dev->wq_writes);

        return i;
}

Aici, presupunem ca sunt 2 procese care citesc simultan din device si
dev->fill = 1. Primul proces reuseste sa intre in bucla while, apoi
pp. ca kernel-ul este preemptat, si al doilea proces intra in while
(faptul ca dev->fill este atomica nu ne ajuta cu nimic aici), si
rezultatul net este ca se va citi de 2 ori din buffer si
atomic_dec(&dev->fill) va fi executat de doua ori, starea device-ului
devenind una invalida.

Acesta e doar un exemplu de race - si dev->get++ poate genera un race
daca preemptarea are loc in mijlocul incrementarii.

Solutia evidenta mi se pare folosirea unui spinlock care sa protejeze
buffer-ul si variabilele de stare asociate, insa as dori sa stiu daca
exista ceva ce-mi scapa mie si rationamentul de mai sus e gresit.

Multumesc,
Stefan Bucur


More information about the pso mailing list