Commit 8092895f authored by Al Viro's avatar Al Viro Committed by Mike Marshall

orangefs: validate the response in decode_dirents()

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent ade1d48b
...@@ -17,13 +17,17 @@ struct readdir_handle_s { ...@@ -17,13 +17,17 @@ struct readdir_handle_s {
/* /*
* decode routine needed by kmod to make sense of the shared page for readdirs. * decode routine needed by kmod to make sense of the shared page for readdirs.
*/ */
static long decode_dirents(char *ptr, struct pvfs2_readdir_response_s *readdir) static long decode_dirents(char *ptr, size_t size,
struct pvfs2_readdir_response_s *readdir)
{ {
int i; int i;
struct pvfs2_readdir_response_s *rd = struct pvfs2_readdir_response_s *rd =
(struct pvfs2_readdir_response_s *) ptr; (struct pvfs2_readdir_response_s *) ptr;
char *buf = ptr; char *buf = ptr;
if (size < offsetof(struct pvfs2_readdir_response_s, dirent_array))
return -EINVAL;
readdir->token = rd->token; readdir->token = rd->token;
readdir->pvfs_dirent_outcount = rd->pvfs_dirent_outcount; readdir->pvfs_dirent_outcount = rd->pvfs_dirent_outcount;
readdir->dirent_array = kcalloc(readdir->pvfs_dirent_outcount, readdir->dirent_array = kcalloc(readdir->pvfs_dirent_outcount,
...@@ -31,21 +35,43 @@ static long decode_dirents(char *ptr, struct pvfs2_readdir_response_s *readdir) ...@@ -31,21 +35,43 @@ static long decode_dirents(char *ptr, struct pvfs2_readdir_response_s *readdir)
GFP_KERNEL); GFP_KERNEL);
if (readdir->dirent_array == NULL) if (readdir->dirent_array == NULL)
return -ENOMEM; return -ENOMEM;
buf += offsetof(struct pvfs2_readdir_response_s, dirent_array); buf += offsetof(struct pvfs2_readdir_response_s, dirent_array);
size -= offsetof(struct pvfs2_readdir_response_s, dirent_array);
for (i = 0; i < readdir->pvfs_dirent_outcount; i++) { for (i = 0; i < readdir->pvfs_dirent_outcount; i++) {
__u32 len = *(__u32 *)buf; __u32 len;
if (size < 4)
goto Einval;
len = *(__u32 *)buf;
if (len >= (unsigned)-24)
goto Einval;
readdir->dirent_array[i].d_name = buf + 4; readdir->dirent_array[i].d_name = buf + 4;
buf += roundup8(4 + len + 1);
readdir->dirent_array[i].d_length = len; readdir->dirent_array[i].d_length = len;
len = roundup8(4 + len + 1);
if (size < len + 16)
goto Einval;
size -= len + 16;
buf += len;
readdir->dirent_array[i].khandle = readdir->dirent_array[i].khandle =
*(struct pvfs2_khandle *) buf; *(struct pvfs2_khandle *) buf;
buf += 16; buf += 16;
} }
return buf - ptr; return buf - ptr;
Einval:
kfree(readdir->dirent_array);
readdir->dirent_array = NULL;
return -EINVAL;
} }
static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf, static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf,
int buffer_index) size_t size, int buffer_index)
{ {
long ret; long ret;
...@@ -61,7 +87,7 @@ static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf, ...@@ -61,7 +87,7 @@ static long readdir_handle_ctor(struct readdir_handle_s *rhandle, void *buf,
} }
rhandle->buffer_index = buffer_index; rhandle->buffer_index = buffer_index;
rhandle->dents_buf = buf; rhandle->dents_buf = buf;
ret = decode_dirents(buf, &rhandle->readdir_response); ret = decode_dirents(buf, size, &rhandle->readdir_response);
if (ret < 0) { if (ret < 0) {
gossip_err("Could not decode readdir from buffer %ld\n", ret); gossip_err("Could not decode readdir from buffer %ld\n", ret);
rhandle->buffer_index = -1; rhandle->buffer_index = -1;
...@@ -209,6 +235,7 @@ static int pvfs2_readdir(struct file *file, struct dir_context *ctx) ...@@ -209,6 +235,7 @@ static int pvfs2_readdir(struct file *file, struct dir_context *ctx)
bytes_decoded = bytes_decoded =
readdir_handle_ctor(&rhandle, readdir_handle_ctor(&rhandle,
new_op->downcall.trailer_buf, new_op->downcall.trailer_buf,
new_op->downcall.trailer_size,
buffer_index); buffer_index);
if (bytes_decoded < 0) { if (bytes_decoded < 0) {
gossip_err("pvfs2_readdir: Could not decode trailer buffer into a readdir response %d\n", gossip_err("pvfs2_readdir: Could not decode trailer buffer into a readdir response %d\n",
......
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