diff options
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r-- | fs/ioctl.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index d6cc16476620..1d9b9fcb2db4 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -86,7 +86,7 @@ int fiemap_fill_next_extent(struct fiemap_extent_info *fieinfo, u64 logical, | |||
86 | u64 phys, u64 len, u32 flags) | 86 | u64 phys, u64 len, u32 flags) |
87 | { | 87 | { |
88 | struct fiemap_extent extent; | 88 | struct fiemap_extent extent; |
89 | struct fiemap_extent *dest = fieinfo->fi_extents_start; | 89 | struct fiemap_extent __user *dest = fieinfo->fi_extents_start; |
90 | 90 | ||
91 | /* only count the extents */ | 91 | /* only count the extents */ |
92 | if (fieinfo->fi_extents_max == 0) { | 92 | if (fieinfo->fi_extents_max == 0) { |
@@ -173,6 +173,7 @@ static int fiemap_check_ranges(struct super_block *sb, | |||
173 | static int ioctl_fiemap(struct file *filp, unsigned long arg) | 173 | static int ioctl_fiemap(struct file *filp, unsigned long arg) |
174 | { | 174 | { |
175 | struct fiemap fiemap; | 175 | struct fiemap fiemap; |
176 | struct fiemap __user *ufiemap = (struct fiemap __user *) arg; | ||
176 | struct fiemap_extent_info fieinfo = { 0, }; | 177 | struct fiemap_extent_info fieinfo = { 0, }; |
177 | struct inode *inode = filp->f_path.dentry->d_inode; | 178 | struct inode *inode = filp->f_path.dentry->d_inode; |
178 | struct super_block *sb = inode->i_sb; | 179 | struct super_block *sb = inode->i_sb; |
@@ -182,8 +183,7 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
182 | if (!inode->i_op->fiemap) | 183 | if (!inode->i_op->fiemap) |
183 | return -EOPNOTSUPP; | 184 | return -EOPNOTSUPP; |
184 | 185 | ||
185 | if (copy_from_user(&fiemap, (struct fiemap __user *)arg, | 186 | if (copy_from_user(&fiemap, ufiemap, sizeof(fiemap))) |
186 | sizeof(struct fiemap))) | ||
187 | return -EFAULT; | 187 | return -EFAULT; |
188 | 188 | ||
189 | if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) | 189 | if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS) |
@@ -196,7 +196,7 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
196 | 196 | ||
197 | fieinfo.fi_flags = fiemap.fm_flags; | 197 | fieinfo.fi_flags = fiemap.fm_flags; |
198 | fieinfo.fi_extents_max = fiemap.fm_extent_count; | 198 | fieinfo.fi_extents_max = fiemap.fm_extent_count; |
199 | fieinfo.fi_extents_start = (struct fiemap_extent *)(arg + sizeof(fiemap)); | 199 | fieinfo.fi_extents_start = ufiemap->fm_extents; |
200 | 200 | ||
201 | if (fiemap.fm_extent_count != 0 && | 201 | if (fiemap.fm_extent_count != 0 && |
202 | !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start, | 202 | !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start, |
@@ -209,7 +209,7 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
209 | error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start, len); | 209 | error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start, len); |
210 | fiemap.fm_flags = fieinfo.fi_flags; | 210 | fiemap.fm_flags = fieinfo.fi_flags; |
211 | fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped; | 211 | fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped; |
212 | if (copy_to_user((char *)arg, &fiemap, sizeof(fiemap))) | 212 | if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap))) |
213 | error = -EFAULT; | 213 | error = -EFAULT; |
214 | 214 | ||
215 | return error; | 215 | return error; |
@@ -273,6 +273,13 @@ int __generic_block_fiemap(struct inode *inode, | |||
273 | len = isize; | 273 | len = isize; |
274 | } | 274 | } |
275 | 275 | ||
276 | /* | ||
277 | * Some filesystems can't deal with being asked to map less than | ||
278 | * blocksize, so make sure our len is at least block length. | ||
279 | */ | ||
280 | if (logical_to_blk(inode, len) == 0) | ||
281 | len = blk_to_logical(inode, 1); | ||
282 | |||
276 | start_blk = logical_to_blk(inode, start); | 283 | start_blk = logical_to_blk(inode, start); |
277 | last_blk = logical_to_blk(inode, start + len - 1); | 284 | last_blk = logical_to_blk(inode, start + len - 1); |
278 | 285 | ||
@@ -541,6 +548,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
541 | { | 548 | { |
542 | int error = 0; | 549 | int error = 0; |
543 | int __user *argp = (int __user *)arg; | 550 | int __user *argp = (int __user *)arg; |
551 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
544 | 552 | ||
545 | switch (cmd) { | 553 | switch (cmd) { |
546 | case FIOCLEX: | 554 | case FIOCLEX: |
@@ -560,13 +568,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
560 | break; | 568 | break; |
561 | 569 | ||
562 | case FIOQSIZE: | 570 | case FIOQSIZE: |
563 | if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || | 571 | if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || |
564 | S_ISREG(filp->f_path.dentry->d_inode->i_mode) || | 572 | S_ISLNK(inode->i_mode)) { |
565 | S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { | 573 | loff_t res = inode_get_bytes(inode); |
566 | loff_t res = | 574 | error = copy_to_user(argp, &res, sizeof(res)) ? |
567 | inode_get_bytes(filp->f_path.dentry->d_inode); | 575 | -EFAULT : 0; |
568 | error = copy_to_user((loff_t __user *)arg, &res, | ||
569 | sizeof(res)) ? -EFAULT : 0; | ||
570 | } else | 576 | } else |
571 | error = -ENOTTY; | 577 | error = -ENOTTY; |
572 | break; | 578 | break; |
@@ -583,14 +589,10 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
583 | return ioctl_fiemap(filp, arg); | 589 | return ioctl_fiemap(filp, arg); |
584 | 590 | ||
585 | case FIGETBSZ: | 591 | case FIGETBSZ: |
586 | { | 592 | return put_user(inode->i_sb->s_blocksize, argp); |
587 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
588 | int __user *p = (int __user *)arg; | ||
589 | return put_user(inode->i_sb->s_blocksize, p); | ||
590 | } | ||
591 | 593 | ||
592 | default: | 594 | default: |
593 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | 595 | if (S_ISREG(inode->i_mode)) |
594 | error = file_ioctl(filp, cmd, arg); | 596 | error = file_ioctl(filp, cmd, arg); |
595 | else | 597 | else |
596 | error = vfs_ioctl(filp, cmd, arg); | 598 | error = vfs_ioctl(filp, cmd, arg); |