dlmfs_file_write(): fix the bogosity in handling non-zero *ppos

'count' is how much you want written, not the final position.
Moreover, it can legitimately be less than the current position...

Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2020-04-23 13:45:27 -04:00
parent 8f3d9f3542
commit 3815f1be54

View File

@ -275,7 +275,6 @@ static ssize_t dlmfs_file_write(struct file *filp,
loff_t *ppos) loff_t *ppos)
{ {
int bytes_left; int bytes_left;
ssize_t writelen;
char *lvb_buf; char *lvb_buf;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
@ -285,32 +284,30 @@ static ssize_t dlmfs_file_write(struct file *filp,
if (*ppos >= i_size_read(inode)) if (*ppos >= i_size_read(inode))
return -ENOSPC; return -ENOSPC;
/* don't write past the lvb */
if (count > i_size_read(inode) - *ppos)
count = i_size_read(inode) - *ppos;
if (!count) if (!count)
return 0; return 0;
if (!access_ok(buf, count)) if (!access_ok(buf, count))
return -EFAULT; return -EFAULT;
/* don't write past the lvb */ lvb_buf = kmalloc(count, GFP_NOFS);
if ((count + *ppos) > i_size_read(inode))
writelen = i_size_read(inode) - *ppos;
else
writelen = count - *ppos;
lvb_buf = kmalloc(writelen, GFP_NOFS);
if (!lvb_buf) if (!lvb_buf)
return -ENOMEM; return -ENOMEM;
bytes_left = copy_from_user(lvb_buf, buf, writelen); bytes_left = copy_from_user(lvb_buf, buf, count);
writelen -= bytes_left; count -= bytes_left;
if (writelen) if (count)
user_dlm_write_lvb(inode, lvb_buf, writelen); user_dlm_write_lvb(inode, lvb_buf, count);
kfree(lvb_buf); kfree(lvb_buf);
*ppos = *ppos + writelen; *ppos = *ppos + count;
mlog(0, "wrote %zd bytes\n", writelen); mlog(0, "wrote %zu bytes\n", count);
return writelen; return count;
} }
static void dlmfs_init_once(void *foo) static void dlmfs_init_once(void *foo)