Commit e7411c12 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] vc locking

Like a few other drivers the vc driver is doing unlocked careless
references to file offsets.  Its got kind of 2.2 locking that hasnt been
updated in the lseek function so someone at least tried. 

Fortunately we have a real lock for this and can just make lseek use that
too.

The 'assume 64bit load is atomic' bug seems to be very widely spread

akpm@osdl.org:

   Move declarations to vt_kern.h
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent ab04a6b1
...@@ -70,11 +70,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) ...@@ -70,11 +70,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
{ {
int size; int size;
lock_kernel(); down(&con_buf_sem);
size = vcs_size(file->f_dentry->d_inode); size = vcs_size(file->f_dentry->d_inode);
switch (orig) { switch (orig) {
default: default:
unlock_kernel(); up(&con_buf_sem);
return -EINVAL; return -EINVAL;
case 2: case 2:
offset += size; offset += size;
...@@ -85,28 +85,21 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) ...@@ -85,28 +85,21 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
break; break;
} }
if (offset < 0 || offset > size) { if (offset < 0 || offset > size) {
unlock_kernel(); up(&con_buf_sem);
return -EINVAL; return -EINVAL;
} }
file->f_pos = offset; file->f_pos = offset;
unlock_kernel(); up(&con_buf_sem);
return file->f_pos; return file->f_pos;
} }
/* We share this temporary buffer with the console write code
* so that we can easily avoid touching user space while holding the
* console spinlock.
*/
extern char con_buf[PAGE_SIZE];
#define CON_BUF_SIZE PAGE_SIZE
extern struct semaphore con_buf_sem;
static ssize_t static ssize_t
vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{ {
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
unsigned int currcons = iminor(inode); unsigned int currcons = iminor(inode);
long pos = *ppos; long pos;
long viewed, attr, read; long viewed, attr, read;
int col, maxcol; int col, maxcol;
unsigned short *org = NULL; unsigned short *org = NULL;
...@@ -114,6 +107,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ...@@ -114,6 +107,8 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
down(&con_buf_sem); down(&con_buf_sem);
pos = *ppos;
/* Select the proper current console and verify /* Select the proper current console and verify
* sanity of the situation under the console lock. * sanity of the situation under the console lock.
*/ */
...@@ -275,7 +270,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) ...@@ -275,7 +270,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{ {
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = file->f_dentry->d_inode;
unsigned int currcons = iminor(inode); unsigned int currcons = iminor(inode);
long pos = *ppos; long pos;
long viewed, attr, size, written; long viewed, attr, size, written;
char *con_buf0; char *con_buf0;
int col, maxcol; int col, maxcol;
...@@ -284,6 +279,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) ...@@ -284,6 +279,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
down(&con_buf_sem); down(&con_buf_sem);
pos = *ppos;
/* Select the proper current console and verify /* Select the proper current console and verify
* sanity of the situation under the console lock. * sanity of the situation under the console lock.
*/ */
......
...@@ -1865,7 +1865,6 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c) ...@@ -1865,7 +1865,6 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
* kernel memory allocation is available. * kernel memory allocation is available.
*/ */
char con_buf[PAGE_SIZE]; char con_buf[PAGE_SIZE];
#define CON_BUF_SIZE PAGE_SIZE
DECLARE_MUTEX(con_buf_sem); DECLARE_MUTEX(con_buf_sem);
/* acquires console_sem */ /* acquires console_sem */
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/kd.h> #include <linux/kd.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/console_struct.h> #include <linux/console_struct.h>
#include <linux/mm.h>
/* /*
* Presently, a lot of graphics programs do not restore the contents of * Presently, a lot of graphics programs do not restore the contents of
...@@ -84,4 +85,12 @@ int vt_waitactive(int vt); ...@@ -84,4 +85,12 @@ int vt_waitactive(int vt);
void change_console(unsigned int); void change_console(unsigned int);
void reset_vc(unsigned int new_console); void reset_vc(unsigned int new_console);
/*
* vc_screen.c shares this temporary buffer with the console write code so that
* we can easily avoid touching user space while holding the console spinlock.
*/
extern char con_buf[PAGE_SIZE];
#define CON_BUF_SIZE PAGE_SIZE
extern struct semaphore con_buf_sem;
#endif /* _VT_KERN_H */ #endif /* _VT_KERN_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment