diff options
Diffstat (limited to 'fs/readdir.c')
-rw-r--r-- | fs/readdir.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/readdir.c b/fs/readdir.c index b6109329b607..bff3ee58e2f8 100644 --- a/fs/readdir.c +++ b/fs/readdir.c | |||
@@ -69,20 +69,24 @@ struct readdir_callback { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, | 71 | static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, |
72 | ino_t ino, unsigned int d_type) | 72 | u64 ino, unsigned int d_type) |
73 | { | 73 | { |
74 | struct readdir_callback * buf = (struct readdir_callback *) __buf; | 74 | struct readdir_callback * buf = (struct readdir_callback *) __buf; |
75 | struct old_linux_dirent __user * dirent; | 75 | struct old_linux_dirent __user * dirent; |
76 | unsigned long d_ino; | ||
76 | 77 | ||
77 | if (buf->result) | 78 | if (buf->result) |
78 | return -EINVAL; | 79 | return -EINVAL; |
80 | d_ino = ino; | ||
81 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | ||
82 | return -EOVERFLOW; | ||
79 | buf->result++; | 83 | buf->result++; |
80 | dirent = buf->dirent; | 84 | dirent = buf->dirent; |
81 | if (!access_ok(VERIFY_WRITE, dirent, | 85 | if (!access_ok(VERIFY_WRITE, dirent, |
82 | (unsigned long)(dirent->d_name + namlen + 1) - | 86 | (unsigned long)(dirent->d_name + namlen + 1) - |
83 | (unsigned long)dirent)) | 87 | (unsigned long)dirent)) |
84 | goto efault; | 88 | goto efault; |
85 | if ( __put_user(ino, &dirent->d_ino) || | 89 | if ( __put_user(d_ino, &dirent->d_ino) || |
86 | __put_user(offset, &dirent->d_offset) || | 90 | __put_user(offset, &dirent->d_offset) || |
87 | __put_user(namlen, &dirent->d_namlen) || | 91 | __put_user(namlen, &dirent->d_namlen) || |
88 | __copy_to_user(dirent->d_name, name, namlen) || | 92 | __copy_to_user(dirent->d_name, name, namlen) || |
@@ -138,22 +142,26 @@ struct getdents_callback { | |||
138 | }; | 142 | }; |
139 | 143 | ||
140 | static int filldir(void * __buf, const char * name, int namlen, loff_t offset, | 144 | static int filldir(void * __buf, const char * name, int namlen, loff_t offset, |
141 | ino_t ino, unsigned int d_type) | 145 | u64 ino, unsigned int d_type) |
142 | { | 146 | { |
143 | struct linux_dirent __user * dirent; | 147 | struct linux_dirent __user * dirent; |
144 | struct getdents_callback * buf = (struct getdents_callback *) __buf; | 148 | struct getdents_callback * buf = (struct getdents_callback *) __buf; |
149 | unsigned long d_ino; | ||
145 | int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2); | 150 | int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2); |
146 | 151 | ||
147 | buf->error = -EINVAL; /* only used if we fail.. */ | 152 | buf->error = -EINVAL; /* only used if we fail.. */ |
148 | if (reclen > buf->count) | 153 | if (reclen > buf->count) |
149 | return -EINVAL; | 154 | return -EINVAL; |
155 | d_ino = ino; | ||
156 | if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) | ||
157 | return -EOVERFLOW; | ||
150 | dirent = buf->previous; | 158 | dirent = buf->previous; |
151 | if (dirent) { | 159 | if (dirent) { |
152 | if (__put_user(offset, &dirent->d_off)) | 160 | if (__put_user(offset, &dirent->d_off)) |
153 | goto efault; | 161 | goto efault; |
154 | } | 162 | } |
155 | dirent = buf->current_dir; | 163 | dirent = buf->current_dir; |
156 | if (__put_user(ino, &dirent->d_ino)) | 164 | if (__put_user(d_ino, &dirent->d_ino)) |
157 | goto efault; | 165 | goto efault; |
158 | if (__put_user(reclen, &dirent->d_reclen)) | 166 | if (__put_user(reclen, &dirent->d_reclen)) |
159 | goto efault; | 167 | goto efault; |
@@ -222,7 +230,7 @@ struct getdents_callback64 { | |||
222 | }; | 230 | }; |
223 | 231 | ||
224 | static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, | 232 | static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, |
225 | ino_t ino, unsigned int d_type) | 233 | u64 ino, unsigned int d_type) |
226 | { | 234 | { |
227 | struct linux_dirent64 __user *dirent; | 235 | struct linux_dirent64 __user *dirent; |
228 | struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; | 236 | struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf; |