diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-09-01 05:12:00 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-09-01 05:12:00 -0400 |
commit | 7cb35119d067191ce9ebc380a599db0b03cbd9d9 (patch) | |
tree | 15168c61d1f884399b4acdb81eb19092e43b453b /fs/overlayfs | |
parent | 0eb45fc3bb7a2cf9c9c93d9e95986a841e5f4625 (diff) |
ovl: listxattr: use strnlen()
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>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/inode.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 1878591f6a2d..c75625c1efa3 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -255,7 +255,8 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | |||
255 | { | 255 | { |
256 | struct dentry *realdentry = ovl_dentry_real(dentry); | 256 | struct dentry *realdentry = ovl_dentry_real(dentry); |
257 | ssize_t res; | 257 | ssize_t res; |
258 | int off; | 258 | size_t len; |
259 | char *s; | ||
259 | const struct cred *old_cred; | 260 | const struct cred *old_cred; |
260 | 261 | ||
261 | old_cred = ovl_override_creds(dentry->d_sb); | 262 | old_cred = ovl_override_creds(dentry->d_sb); |
@@ -265,17 +266,19 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) | |||
265 | return res; | 266 | return res; |
266 | 267 | ||
267 | /* filter out private xattrs */ | 268 | /* filter out private xattrs */ |
268 | for (off = 0; off < res;) { | 269 | for (s = list, len = res; len;) { |
269 | char *s = list + off; | 270 | size_t slen = strnlen(s, len) + 1; |
270 | size_t slen = strlen(s) + 1; | ||
271 | 271 | ||
272 | BUG_ON(off + slen > res); | 272 | /* underlying fs providing us with an broken xattr list? */ |
273 | if (WARN_ON(slen > len)) | ||
274 | return -EIO; | ||
273 | 275 | ||
276 | len -= slen; | ||
274 | if (ovl_is_private_xattr(s)) { | 277 | if (ovl_is_private_xattr(s)) { |
275 | res -= slen; | 278 | res -= slen; |
276 | memmove(s, s + slen, res - off); | 279 | memmove(s, s + slen, len); |
277 | } else { | 280 | } else { |
278 | off += slen; | 281 | s += slen; |
279 | } | 282 | } |
280 | } | 283 | } |
281 | 284 | ||