Commit b4df268d authored by Linus Torvalds's avatar Linus Torvalds

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

Pull capabilities fix from James Morris.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  capabilities: fix buffer overread on very short xattr
parents e816c201 dc32b5c3
...@@ -348,21 +348,18 @@ static __u32 sansflags(__u32 m) ...@@ -348,21 +348,18 @@ static __u32 sansflags(__u32 m)
return m & ~VFS_CAP_FLAGS_EFFECTIVE; return m & ~VFS_CAP_FLAGS_EFFECTIVE;
} }
static bool is_v2header(size_t size, __le32 magic) static bool is_v2header(size_t size, const struct vfs_cap_data *cap)
{ {
__u32 m = le32_to_cpu(magic);
if (size != XATTR_CAPS_SZ_2) if (size != XATTR_CAPS_SZ_2)
return false; return false;
return sansflags(m) == VFS_CAP_REVISION_2; return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2;
} }
static bool is_v3header(size_t size, __le32 magic) static bool is_v3header(size_t size, const struct vfs_cap_data *cap)
{ {
__u32 m = le32_to_cpu(magic);
if (size != XATTR_CAPS_SZ_3) if (size != XATTR_CAPS_SZ_3)
return false; return false;
return sansflags(m) == VFS_CAP_REVISION_3; return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3;
} }
/* /*
...@@ -405,7 +402,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, ...@@ -405,7 +402,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
fs_ns = inode->i_sb->s_user_ns; fs_ns = inode->i_sb->s_user_ns;
cap = (struct vfs_cap_data *) tmpbuf; cap = (struct vfs_cap_data *) tmpbuf;
if (is_v2header((size_t) ret, cap->magic_etc)) { if (is_v2header((size_t) ret, cap)) {
/* If this is sizeof(vfs_cap_data) then we're ok with the /* If this is sizeof(vfs_cap_data) then we're ok with the
* on-disk value, so return that. */ * on-disk value, so return that. */
if (alloc) if (alloc)
...@@ -413,7 +410,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, ...@@ -413,7 +410,7 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer,
else else
kfree(tmpbuf); kfree(tmpbuf);
return ret; return ret;
} else if (!is_v3header((size_t) ret, cap->magic_etc)) { } else if (!is_v3header((size_t) ret, cap)) {
kfree(tmpbuf); kfree(tmpbuf);
return -EINVAL; return -EINVAL;
} }
...@@ -470,9 +467,9 @@ static kuid_t rootid_from_xattr(const void *value, size_t size, ...@@ -470,9 +467,9 @@ static kuid_t rootid_from_xattr(const void *value, size_t size,
return make_kuid(task_ns, rootid); return make_kuid(task_ns, rootid);
} }
static bool validheader(size_t size, __le32 magic) static bool validheader(size_t size, const struct vfs_cap_data *cap)
{ {
return is_v2header(size, magic) || is_v3header(size, magic); return is_v2header(size, cap) || is_v3header(size, cap);
} }
/* /*
...@@ -495,7 +492,7 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size) ...@@ -495,7 +492,7 @@ int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size)
if (!*ivalue) if (!*ivalue)
return -EINVAL; return -EINVAL;
if (!validheader(size, cap->magic_etc)) if (!validheader(size, cap))
return -EINVAL; return -EINVAL;
if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP)) if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
return -EPERM; return -EPERM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment