Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs fix from Al Viro:
 "Don't put symlink bodies in pagecache into highmem"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  Make sure that highmem pages are not added to symlink page cache
This commit is contained in:
Linus Torvalds 2016-01-14 16:03:57 -08:00
commit 63f729cb4a
3 changed files with 8 additions and 5 deletions

View File

@ -508,7 +508,11 @@ in your dentry operations instead.
[mandatory] [mandatory]
any symlink that might use page_follow_link_light/page_put_link() must any symlink that might use page_follow_link_light/page_put_link() must
have inode_nohighmem(inode) called before anything might start playing with have inode_nohighmem(inode) called before anything might start playing with
its pagecache. its pagecache. No highmem pages should end up in the pagecache of such
symlinks. That includes any preseeding that might be done during symlink
creation. __page_symlink() will honour the mapping gfp flags, so once
you've done inode_nohighmem() it's safe to use, but if you allocate and
insert the page manually, make sure to use the right gfp flags.
-- --
[mandatory] [mandatory]
->follow_link() is replaced with ->get_link(); same API, except that ->follow_link() is replaced with ->get_link(); same API, except that

View File

@ -1894,15 +1894,14 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
attr.ia_mode = S_IFLNK | S_IRWXUGO; attr.ia_mode = S_IFLNK | S_IRWXUGO;
attr.ia_valid = ATTR_MODE; attr.ia_valid = ATTR_MODE;
page = alloc_page(GFP_HIGHUSER); page = alloc_page(GFP_USER);
if (!page) if (!page)
return -ENOMEM; return -ENOMEM;
kaddr = kmap_atomic(page); kaddr = page_address(page);
memcpy(kaddr, symname, pathlen); memcpy(kaddr, symname, pathlen);
if (pathlen < PAGE_SIZE) if (pathlen < PAGE_SIZE)
memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
kunmap_atomic(kaddr);
trace_nfs_symlink_enter(dir, dentry); trace_nfs_symlink_enter(dir, dentry);
error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);

View File

@ -2469,6 +2469,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
inode->i_op = &shmem_short_symlink_operations; inode->i_op = &shmem_short_symlink_operations;
inode->i_link = info->symlink; inode->i_link = info->symlink;
} else { } else {
inode_nohighmem(inode);
error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
if (error) { if (error) {
iput(inode); iput(inode);
@ -2476,7 +2477,6 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
} }
inode->i_mapping->a_ops = &shmem_aops; inode->i_mapping->a_ops = &shmem_aops;
inode->i_op = &shmem_symlink_inode_operations; inode->i_op = &shmem_symlink_inode_operations;
inode_nohighmem(inode);
memcpy(page_address(page), symname, len); memcpy(page_address(page), symname, len);
SetPageUptodate(page); SetPageUptodate(page);
set_page_dirty(page); set_page_dirty(page);