aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsandeen@sandeen.net <sandeen@sandeen.net>2008-11-25 22:20:12 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-12-02 01:16:03 -0500
commit65fbaf2489c667bf79ae1f20403f30c66568d445 (patch)
tree9694dd8017f997730755dec5e58a2324361cf577
parent2ee4fa5cb716eba104a4ef8efe159e1007a2aef6 (diff)
[XFS] Fix xfs_bulkstat_one size checks & error handling
The 32-bit xfs_blkstat_one handler was failing because a size check checked whether the remaining (32-bit) user buffer was less than the (64-bit) bulkstat buffer, and failed with ENOMEM if so. Move this check into the respective handlers so that they check the correct sizes. Also, the formatters were returning negative errors or positive bytes copied; this was odd in the positive error value world of xfs, and handled wrong by at least some of the callers, which treated the bytes returned as an error value. Move the bytes-used assignment into the formatters. Signed-off-by: Eric Sandeen <sandeen@sandeen.net> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c44
-rw-r--r--fs/xfs/xfs_itable.c21
-rw-r--r--fs/xfs/xfs_itable.h2
3 files changed, 39 insertions, 28 deletions
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index a97022f2d9b0..2d336062831d 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -192,35 +192,43 @@ xfs_bstime_store_compat(
192 return 0; 192 return 0;
193} 193}
194 194
195/* Return 0 on success or positive error (to xfs_bulkstat()) */
195STATIC int 196STATIC int
196xfs_bulkstat_one_fmt_compat( 197xfs_bulkstat_one_fmt_compat(
197 void __user *ubuffer, 198 void __user *ubuffer,
199 int ubsize,
200 int *ubused,
198 const xfs_bstat_t *buffer) 201 const xfs_bstat_t *buffer)
199{ 202{
200 compat_xfs_bstat_t __user *p32 = ubuffer; 203 compat_xfs_bstat_t __user *p32 = ubuffer;
201 204
202 if (put_user(buffer->bs_ino, &p32->bs_ino) || 205 if (ubsize < sizeof(*p32))
203 put_user(buffer->bs_mode, &p32->bs_mode) || 206 return XFS_ERROR(ENOMEM);
204 put_user(buffer->bs_nlink, &p32->bs_nlink) || 207
205 put_user(buffer->bs_uid, &p32->bs_uid) || 208 if (put_user(buffer->bs_ino, &p32->bs_ino) ||
206 put_user(buffer->bs_gid, &p32->bs_gid) || 209 put_user(buffer->bs_mode, &p32->bs_mode) ||
207 put_user(buffer->bs_rdev, &p32->bs_rdev) || 210 put_user(buffer->bs_nlink, &p32->bs_nlink) ||
208 put_user(buffer->bs_blksize, &p32->bs_blksize) || 211 put_user(buffer->bs_uid, &p32->bs_uid) ||
209 put_user(buffer->bs_size, &p32->bs_size) || 212 put_user(buffer->bs_gid, &p32->bs_gid) ||
213 put_user(buffer->bs_rdev, &p32->bs_rdev) ||
214 put_user(buffer->bs_blksize, &p32->bs_blksize) ||
215 put_user(buffer->bs_size, &p32->bs_size) ||
210 xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) || 216 xfs_bstime_store_compat(&p32->bs_atime, &buffer->bs_atime) ||
211 xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) || 217 xfs_bstime_store_compat(&p32->bs_mtime, &buffer->bs_mtime) ||
212 xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) || 218 xfs_bstime_store_compat(&p32->bs_ctime, &buffer->bs_ctime) ||
213 put_user(buffer->bs_blocks, &p32->bs_blocks) || 219 put_user(buffer->bs_blocks, &p32->bs_blocks) ||
214 put_user(buffer->bs_xflags, &p32->bs_xflags) || 220 put_user(buffer->bs_xflags, &p32->bs_xflags) ||
215 put_user(buffer->bs_extsize, &p32->bs_extsize) || 221 put_user(buffer->bs_extsize, &p32->bs_extsize) ||
216 put_user(buffer->bs_extents, &p32->bs_extents) || 222 put_user(buffer->bs_extents, &p32->bs_extents) ||
217 put_user(buffer->bs_gen, &p32->bs_gen) || 223 put_user(buffer->bs_gen, &p32->bs_gen) ||
218 put_user(buffer->bs_projid, &p32->bs_projid) || 224 put_user(buffer->bs_projid, &p32->bs_projid) ||
219 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) || 225 put_user(buffer->bs_dmevmask, &p32->bs_dmevmask) ||
220 put_user(buffer->bs_dmstate, &p32->bs_dmstate) || 226 put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
221 put_user(buffer->bs_aextents, &p32->bs_aextents)) 227 put_user(buffer->bs_aextents, &p32->bs_aextents))
222 return -XFS_ERROR(EFAULT); 228 return XFS_ERROR(EFAULT);
223 return sizeof(*p32); 229 if (ubused)
230 *ubused = sizeof(*p32);
231 return 0;
224} 232}
225 233
226STATIC int 234STATIC int
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 7bd49b87160c..e19d0a8d5618 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -188,14 +188,21 @@ xfs_bulkstat_one_dinode(
188 } 188 }
189} 189}
190 190
191/* Return 0 on success or positive error */
191STATIC int 192STATIC int
192xfs_bulkstat_one_fmt( 193xfs_bulkstat_one_fmt(
193 void __user *ubuffer, 194 void __user *ubuffer,
195 int ubsize,
196 int *ubused,
194 const xfs_bstat_t *buffer) 197 const xfs_bstat_t *buffer)
195{ 198{
199 if (ubsize < sizeof(*buffer))
200 return XFS_ERROR(ENOMEM);
196 if (copy_to_user(ubuffer, buffer, sizeof(*buffer))) 201 if (copy_to_user(ubuffer, buffer, sizeof(*buffer)))
197 return -EFAULT; 202 return XFS_ERROR(EFAULT);
198 return sizeof(*buffer); 203 if (ubused)
204 *ubused = sizeof(*buffer);
205 return 0;
199} 206}
200 207
201/* 208/*
@@ -223,8 +230,6 @@ xfs_bulkstat_one_int(
223 230
224 if (!buffer || xfs_internal_inum(mp, ino)) 231 if (!buffer || xfs_internal_inum(mp, ino))
225 return XFS_ERROR(EINVAL); 232 return XFS_ERROR(EINVAL);
226 if (ubsize < sizeof(*buf))
227 return XFS_ERROR(ENOMEM);
228 233
229 buf = kmem_alloc(sizeof(*buf), KM_SLEEP); 234 buf = kmem_alloc(sizeof(*buf), KM_SLEEP);
230 235
@@ -239,15 +244,11 @@ xfs_bulkstat_one_int(
239 xfs_bulkstat_one_dinode(mp, ino, dip, buf); 244 xfs_bulkstat_one_dinode(mp, ino, dip, buf);
240 } 245 }
241 246
242 error = formatter(buffer, buf); 247 error = formatter(buffer, ubsize, ubused, buf);
243 if (error < 0) { 248 if (error)
244 error = EFAULT;
245 goto out_free; 249 goto out_free;
246 }
247 250
248 *stat = BULKSTAT_RV_DIDONE; 251 *stat = BULKSTAT_RV_DIDONE;
249 if (ubused)
250 *ubused = error;
251 252
252 out_free: 253 out_free:
253 kmem_free(buf); 254 kmem_free(buf);
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index e210a4c06569..1fb04e7deb61 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -71,6 +71,8 @@ xfs_bulkstat_single(
71 71
72typedef int (*bulkstat_one_fmt_pf)( /* used size in bytes or negative error */ 72typedef int (*bulkstat_one_fmt_pf)( /* used size in bytes or negative error */
73 void __user *ubuffer, /* buffer to write to */ 73 void __user *ubuffer, /* buffer to write to */
74 int ubsize, /* remaining user buffer sz */
75 int *ubused, /* bytes used by formatter */
74 const xfs_bstat_t *buffer); /* buffer to read from */ 76 const xfs_bstat_t *buffer); /* buffer to read from */
75 77
76int 78int