Skip to content

Commit

Permalink
Merge tag 'afs-fixes-20171201' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/dhowells/linux-fs

Pull AFS fixes from David Howells:
 "Two fix patches for the AFS filesystem:

   - Fix the refcounting on permit caching.

   - AFS inode (afs_vnode) fields need resetting after allocation
     because they're only initialised when slab pages are obtained from
     the page allocator"

* tag 'afs-fixes-20171201' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs:
  afs: Properly reset afs_vnode (inode) fields
  afs: Fix permit refcounting
  • Loading branch information
Linus Torvalds committed Dec 1, 2017
2 parents 3c1c4dd + f8de483 commit ae753ee
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
5 changes: 4 additions & 1 deletion fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,10 @@ enum afs_lock_state {
};

/*
* AFS inode private data
* AFS inode private data.
*
* Note that afs_alloc_inode() *must* reset anything that could incorrectly
* leak from one inode to another.
*/
struct afs_vnode {
struct inode vfs_inode; /* the VFS's inode record */
Expand Down
18 changes: 10 additions & 8 deletions fs/afs/security.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static void afs_hash_permits(struct afs_permits *permits)
void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
unsigned int cb_break)
{
struct afs_permits *permits, *xpermits, *replacement, *new = NULL;
struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL;
afs_access_t caller_access = READ_ONCE(vnode->status.caller_access);
size_t size = 0;
bool changed = false;
Expand Down Expand Up @@ -204,7 +204,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
new = kzalloc(sizeof(struct afs_permits) +
sizeof(struct afs_permit) * size, GFP_NOFS);
if (!new)
return;
goto out_put;

refcount_set(&new->usage, 1);
new->nr_permits = size;
Expand All @@ -229,8 +229,6 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,

afs_hash_permits(new);

afs_put_permits(permits);

/* Now see if the permit list we want is actually already available */
spin_lock(&afs_permits_lock);

Expand Down Expand Up @@ -262,11 +260,15 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
kfree(new);

spin_lock(&vnode->lock);
if (cb_break != (vnode->cb_break + vnode->cb_interest->server->cb_s_break) ||
permits != rcu_access_pointer(vnode->permit_cache))
goto someone_else_changed_it_unlock;
rcu_assign_pointer(vnode->permit_cache, replacement);
zap = rcu_access_pointer(vnode->permit_cache);
if (cb_break == (vnode->cb_break + vnode->cb_interest->server->cb_s_break) &&
zap == permits)
rcu_assign_pointer(vnode->permit_cache, replacement);
else
zap = replacement;
spin_unlock(&vnode->lock);
afs_put_permits(zap);
out_put:
afs_put_permits(permits);
return;

Expand Down
14 changes: 13 additions & 1 deletion fs/afs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,9 @@ static void afs_kill_super(struct super_block *sb)
}

/*
* initialise an inode cache slab element prior to any use
* Initialise an inode cache slab element prior to any use. Note that
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one
* inode to another.
*/
static void afs_i_init_once(void *_vnode)
{
Expand Down Expand Up @@ -568,11 +570,21 @@ static struct inode *afs_alloc_inode(struct super_block *sb)

atomic_inc(&afs_count_active_inodes);

/* Reset anything that shouldn't leak from one inode to the next. */
memset(&vnode->fid, 0, sizeof(vnode->fid));
memset(&vnode->status, 0, sizeof(vnode->status));

vnode->volume = NULL;
vnode->lock_key = NULL;
vnode->permit_cache = NULL;
vnode->cb_interest = NULL;
#ifdef CONFIG_AFS_FSCACHE
vnode->cache = NULL;
#endif

vnode->flags = 1 << AFS_VNODE_UNSET;
vnode->cb_type = 0;
vnode->lock_state = AFS_VNODE_LOCK_NONE;

_leave(" = %p", &vnode->vfs_inode);
return &vnode->vfs_inode;
Expand Down

0 comments on commit ae753ee

Please sign in to comment.