check ATTR_SIZE contraints in inode_change_ok
Make sure we check the truncate constraints early on in ->setattr by adding those checks to inode_change_ok. Also clean up and document inode_change_ok to make this obvious. As a fallout we don't have to call inode_newsize_ok from simple_setsize and simplify it down to a truncate_setsize which doesn't return an error. This simplifies a lot of setattr implementations and means we use truncate_setsize almost everywhere. Get rid of fat_setsize now that it's trivial and mark ext2_setsize static to make the calling convention obvious. Keep the inode_newsize_ok in vmtruncate for now as all callers need an audit for its removal anyway. Note: setattr code in ecryptfs doesn't call inode_change_ok at all and needs a deeper audit, but that is left for later. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:

committed by
Al Viro

parent
db78b877f7
commit
2c27c65ed0
@@ -540,29 +540,49 @@ void truncate_pagecache(struct inode *inode, loff_t old, loff_t new)
|
||||
}
|
||||
EXPORT_SYMBOL(truncate_pagecache);
|
||||
|
||||
/**
|
||||
* truncate_setsize - update inode and pagecache for a new file size
|
||||
* @inode: inode
|
||||
* @newsize: new file size
|
||||
*
|
||||
* truncate_setsize updastes i_size update and performs pagecache
|
||||
* truncation (if necessary) for a file size updates. It will be
|
||||
* typically be called from the filesystem's setattr function when
|
||||
* ATTR_SIZE is passed in.
|
||||
*
|
||||
* Must be called with inode_mutex held and after all filesystem
|
||||
* specific block truncation has been performed.
|
||||
*/
|
||||
void truncate_setsize(struct inode *inode, loff_t newsize)
|
||||
{
|
||||
loff_t oldsize;
|
||||
|
||||
oldsize = inode->i_size;
|
||||
i_size_write(inode, newsize);
|
||||
|
||||
truncate_pagecache(inode, oldsize, newsize);
|
||||
}
|
||||
EXPORT_SYMBOL(truncate_setsize);
|
||||
|
||||
/**
|
||||
* vmtruncate - unmap mappings "freed" by truncate() syscall
|
||||
* @inode: inode of the file used
|
||||
* @offset: file offset to start truncating
|
||||
*
|
||||
* NOTE! We have to be ready to update the memory sharing
|
||||
* between the file and the memory map for a potential last
|
||||
* incomplete page. Ugly, but necessary.
|
||||
*
|
||||
* This function is deprecated and simple_setsize or truncate_pagecache
|
||||
* should be used instead.
|
||||
* This function is deprecated and truncate_setsize or truncate_pagecache
|
||||
* should be used instead, together with filesystem specific block truncation.
|
||||
*/
|
||||
int vmtruncate(struct inode *inode, loff_t offset)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = simple_setsize(inode, offset);
|
||||
error = inode_newsize_ok(inode, offset);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
truncate_setsize(inode, offset);
|
||||
if (inode->i_op->truncate)
|
||||
inode->i_op->truncate(inode);
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(vmtruncate);
|
||||
|
Reference in New Issue
Block a user