aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-09-01 11:12:00 +0200
committerSasha Levin <alexander.levin@verizon.com>2016-09-15 18:54:06 -0400
commitf45724343a4a5399386f8df3e548445fc9056c48 (patch)
treeab78f542d1c9e9600079f3c6a3fd11533f3a812d /fs
parentcc318bc6819922ad17dbcbb5e0ac5164bcbb60d2 (diff)
ovl: listxattr: use strnlen()
[ Upstream commit 7cb35119d067191ce9ebc380a599db0b03cbd9d9 ] Be defensive about what underlying fs provides us in the returned xattr list buffer. If it's not properly null terminated, bail out with a warning insead of BUG. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/inode.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 5403ba628bde..6d52041d13cf 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -263,7 +263,8 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
struct path realpath;
enum ovl_path_type type = ovl_path_real(dentry, &realpath);
ssize_t res;
- int off;
+ size_t len;
+ char *s;
res = vfs_listxattr(realpath.dentry, list, size);
if (res <= 0 || size == 0)
@@ -273,17 +274,19 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
return res;
/* filter out private xattrs */
- for (off = 0; off < res;) {
- char *s = list + off;
- size_t slen = strlen(s) + 1;
+ for (s = list, len = res; len;) {
+ size_t slen = strnlen(s, len) + 1;
- BUG_ON(off + slen > res);
+ /* underlying fs providing us with an broken xattr list? */
+ if (WARN_ON(slen > len))
+ return -EIO;
+ len -= slen;
if (ovl_is_private_xattr(s)) {
res -= slen;
- memmove(s, s + slen, res - off);
+ memmove(s, s + slen, len);
} else {
- off += slen;
+ s += slen;
}
}