From: Alan Cox 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 Signed-off-by: Andrew Morton --- 25-akpm/drivers/char/vc_screen.c | 31 ++++++++++++++++++------------- 1 files changed, 18 insertions(+), 13 deletions(-) diff -puN drivers/char/vc_screen.c~vc-locking drivers/char/vc_screen.c --- 25/drivers/char/vc_screen.c~vc-locking Fri Jun 25 14:21:44 2004 +++ 25-akpm/drivers/char/vc_screen.c Fri Jun 25 14:21:44 2004 @@ -66,15 +66,23 @@ vcs_size(struct inode *inode) return size; } +/* 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 loff_t vcs_lseek(struct file *file, loff_t offset, int orig) { int size; - lock_kernel(); + down(&con_buf_sem); size = vcs_size(file->f_dentry->d_inode); switch (orig) { default: - unlock_kernel(); + up(&con_buf_sem); return -EINVAL; case 2: offset += size; @@ -85,28 +93,21 @@ static loff_t vcs_lseek(struct file *fil break; } if (offset < 0 || offset > size) { - unlock_kernel(); + up(&con_buf_sem); return -EINVAL; } file->f_pos = offset; - unlock_kernel(); + up(&con_buf_sem); 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 vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); - long pos = *ppos; + long pos; long viewed, attr, read; int col, maxcol; unsigned short *org = NULL; @@ -114,6 +115,8 @@ vcs_read(struct file *file, char __user down(&con_buf_sem); + pos = *ppos; + /* Select the proper current console and verify * sanity of the situation under the console lock. */ @@ -275,7 +278,7 @@ vcs_write(struct file *file, const char { struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); - long pos = *ppos; + long pos; long viewed, attr, size, written; char *con_buf0; int col, maxcol; @@ -284,6 +287,8 @@ vcs_write(struct file *file, const char down(&con_buf_sem); + pos = *ppos; + /* Select the proper current console and verify * sanity of the situation under the console lock. */ _