Skip to content

Commit

Permalink
um: convert count_lock to mutex, fix a race in line_open()
Browse files Browse the repository at this point in the history
If two processes are opening the same line, the second to get
into line_open() will decide that it doesn't need to do anything
(correctly) or wait for anything.  The latter, unfortunately,
is incorrect - the first opener might not be through yet.  We
need to have exclusion covering the entire line_init(), including
the blocking parts.  Moreover, the next patch will need to
widen the exclusion on mconsole side of things, also including
the blocking bits, so let's just convert that sucker to mutex...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>
  • Loading branch information
Al Viro authored and richardweinberger committed Mar 24, 2012
1 parent 43574c1 commit d8c215a
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 20 deletions.
26 changes: 9 additions & 17 deletions arch/um/drivers/line.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
struct line *line = &lines[tty->index];
int err = -ENODEV;

spin_lock(&line->count_lock);
mutex_lock(&line->count_lock);
if (!line->valid)
goto out_unlock;

Expand All @@ -421,10 +421,9 @@ int line_open(struct line *lines, struct tty_struct *tty)
tty->driver_data = line;
line->tty = tty;

spin_unlock(&line->count_lock);
err = enable_chan(line);
if (err) /* line_close() will be called by our caller */
return err;
goto out_unlock;

INIT_DELAYED_WORK(&line->task, line_timer_cb);

Expand All @@ -435,11 +434,8 @@ int line_open(struct line *lines, struct tty_struct *tty)

chan_window_size(&line->chan_list, &tty->winsize.ws_row,
&tty->winsize.ws_col);

return 0;

out_unlock:
spin_unlock(&line->count_lock);
mutex_unlock(&line->count_lock);
return err;
}

Expand All @@ -459,7 +455,7 @@ void line_close(struct tty_struct *tty, struct file * filp)
/* We ignore the error anyway! */
flush_buffer(line);

spin_lock(&line->count_lock);
mutex_lock(&line->count_lock);
BUG_ON(!line->valid);

if (--line->count)
Expand All @@ -468,17 +464,13 @@ void line_close(struct tty_struct *tty, struct file * filp)
line->tty = NULL;
tty->driver_data = NULL;

spin_unlock(&line->count_lock);

if (line->sigio) {
unregister_winch(tty);
line->sigio = 0;
}

return;

out_unlock:
spin_unlock(&line->count_lock);
mutex_unlock(&line->count_lock);
}

void close_lines(struct line *lines, int nlines)
Expand All @@ -495,7 +487,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
struct line *line = &lines[n];
int err = -EINVAL;

spin_lock(&line->count_lock);
mutex_lock(&line->count_lock);

if (line->count) {
*error_out = "Device is already open";
Expand All @@ -510,7 +502,7 @@ static int setup_one_line(struct line *lines, int n, char *init,
}
err = 0;
out:
spin_unlock(&line->count_lock);
mutex_unlock(&line->count_lock);
return err;
}

Expand Down Expand Up @@ -609,13 +601,13 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,

line = &lines[dev];

spin_lock(&line->count_lock);
mutex_lock(&line->count_lock);
if (!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
else if (line->tty == NULL)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
spin_unlock(&line->count_lock);
mutex_unlock(&line->count_lock);

return n;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/um/drivers/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct line_driver {

struct line {
struct tty_struct *tty;
spinlock_t count_lock;
struct mutex count_lock;
unsigned long count;
int valid;

Expand Down
2 changes: 1 addition & 1 deletion arch/um/drivers/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ static int ssl_init(void)
serial_lines[i].valid = 1;
}
spin_lock_init(&serial_lines[i].lock);
spin_lock_init(&serial_lines[i].count_lock);
mutex_init(&serial_lines[i].count_lock);
serial_lines[i].driver = &driver;
}
ssl_driver = register_lines(&driver, &ssl_ops, serial_lines,
Expand Down
2 changes: 1 addition & 1 deletion arch/um/drivers/stdio_console.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static int stdio_init(void)
vts[i].valid = 1;
}
spin_lock_init(&vts[i].lock);
spin_lock_init(&vts[i].count_lock);
mutex_init(&vts[i].count_lock);
vts[i].driver = &driver;
}
console_driver = register_lines(&driver, &console_ops, vts,
Expand Down

0 comments on commit d8c215a

Please sign in to comment.