hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/ioctl.c
....@@ -8,6 +8,7 @@
88 #include <linux/syscalls.h>
99 #include <linux/mm.h>
1010 #include <linux/capability.h>
11
+#include <linux/compat.h>
1112 #include <linux/file.h>
1213 #include <linux/fs.h>
1314 #include <linux/security.h>
....@@ -17,6 +18,7 @@
1718 #include <linux/buffer_head.h>
1819 #include <linux/falloc.h>
1920 #include <linux/sched/signal.h>
21
+#include <linux/fiemap.h>
2022
2123 #include "internal.h"
2224
....@@ -53,19 +55,40 @@
5355
5456 static int ioctl_fibmap(struct file *filp, int __user *p)
5557 {
56
- struct address_space *mapping = filp->f_mapping;
57
- int res, block;
58
+ struct inode *inode = file_inode(filp);
59
+ struct super_block *sb = inode->i_sb;
60
+ int error, ur_block;
61
+ sector_t block;
5862
59
- /* do we support this mess? */
60
- if (!mapping->a_ops->bmap)
61
- return -EINVAL;
6263 if (!capable(CAP_SYS_RAWIO))
6364 return -EPERM;
64
- res = get_user(block, p);
65
- if (res)
66
- return res;
67
- res = mapping->a_ops->bmap(mapping, block);
68
- return put_user(res, p);
65
+
66
+ error = get_user(ur_block, p);
67
+ if (error)
68
+ return error;
69
+
70
+ if (ur_block < 0)
71
+ return -EINVAL;
72
+
73
+ block = ur_block;
74
+ error = bmap(inode, &block);
75
+
76
+ if (block > INT_MAX) {
77
+ error = -ERANGE;
78
+ pr_warn_ratelimited("[%s/%d] FS: %s File: %pD4 would truncate fibmap result\n",
79
+ current->comm, task_pid_nr(current),
80
+ sb->s_id, filp);
81
+ }
82
+
83
+ if (error)
84
+ ur_block = 0;
85
+ else
86
+ ur_block = block;
87
+
88
+ if (put_user(ur_block, p))
89
+ error = -EFAULT;
90
+
91
+ return error;
6992 }
7093
7194 /**
....@@ -123,65 +146,58 @@
123146 return 1;
124147 return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
125148 }
126
-EXPORT_SYMBOL(fiemap_fill_next_extent);
149
+EXPORT_SYMBOL_NS(fiemap_fill_next_extent, ANDROID_GKI_VFS_EXPORT_ONLY);
127150
128151 /**
129
- * fiemap_check_flags - check validity of requested flags for fiemap
152
+ * fiemap_prep - check validity of requested flags for fiemap
153
+ * @inode: Inode to operate on
130154 * @fieinfo: Fiemap context passed into ->fiemap
131
- * @fs_flags: Set of fiemap flags that the file system understands
155
+ * @start: Start of the mapped range
156
+ * @len: Length of the mapped range, can be truncated by this function.
157
+ * @supported_flags: Set of fiemap flags that the file system understands
132158 *
133
- * Called from file system ->fiemap callback. This will compute the
134
- * intersection of valid fiemap flags and those that the fs supports. That
135
- * value is then compared against the user supplied flags. In case of bad user
136
- * flags, the invalid values will be written into the fieinfo structure, and
137
- * -EBADR is returned, which tells ioctl_fiemap() to return those values to
138
- * userspace. For this reason, a return code of -EBADR should be preserved.
159
+ * This function must be called from each ->fiemap instance to validate the
160
+ * fiemap request against the file system parameters.
139161 *
140
- * Returns 0 on success, -EBADR on bad flags.
162
+ * Returns 0 on success, or a negative error on failure.
141163 */
142
-int fiemap_check_flags(struct fiemap_extent_info *fieinfo, u32 fs_flags)
164
+int fiemap_prep(struct inode *inode, struct fiemap_extent_info *fieinfo,
165
+ u64 start, u64 *len, u32 supported_flags)
143166 {
167
+ u64 maxbytes = inode->i_sb->s_maxbytes;
144168 u32 incompat_flags;
169
+ int ret = 0;
145170
146
- incompat_flags = fieinfo->fi_flags & ~(FIEMAP_FLAGS_COMPAT & fs_flags);
147
- if (incompat_flags) {
148
- fieinfo->fi_flags = incompat_flags;
149
- return -EBADR;
150
- }
151
- return 0;
152
-}
153
-EXPORT_SYMBOL(fiemap_check_flags);
154
-
155
-static int fiemap_check_ranges(struct super_block *sb,
156
- u64 start, u64 len, u64 *new_len)
157
-{
158
- u64 maxbytes = (u64) sb->s_maxbytes;
159
-
160
- *new_len = len;
161
-
162
- if (len == 0)
171
+ if (*len == 0)
163172 return -EINVAL;
164
-
165
- if (start > maxbytes)
173
+ if (start >= maxbytes)
166174 return -EFBIG;
167175
168176 /*
169177 * Shrink request scope to what the fs can actually handle.
170178 */
171
- if (len > maxbytes || (maxbytes - len) < start)
172
- *new_len = maxbytes - start;
179
+ if (*len > maxbytes || (maxbytes - *len) < start)
180
+ *len = maxbytes - start;
173181
174
- return 0;
182
+ supported_flags |= FIEMAP_FLAG_SYNC;
183
+ supported_flags &= FIEMAP_FLAGS_COMPAT;
184
+ incompat_flags = fieinfo->fi_flags & ~supported_flags;
185
+ if (incompat_flags) {
186
+ fieinfo->fi_flags = incompat_flags;
187
+ return -EBADR;
188
+ }
189
+
190
+ if (fieinfo->fi_flags & FIEMAP_FLAG_SYNC)
191
+ ret = filemap_write_and_wait(inode->i_mapping);
192
+ return ret;
175193 }
194
+EXPORT_SYMBOL_NS(fiemap_prep, ANDROID_GKI_VFS_EXPORT_ONLY);
176195
177
-static int ioctl_fiemap(struct file *filp, unsigned long arg)
196
+static int ioctl_fiemap(struct file *filp, struct fiemap __user *ufiemap)
178197 {
179198 struct fiemap fiemap;
180
- struct fiemap __user *ufiemap = (struct fiemap __user *) arg;
181199 struct fiemap_extent_info fieinfo = { 0, };
182200 struct inode *inode = file_inode(filp);
183
- struct super_block *sb = inode->i_sb;
184
- u64 len;
185201 int error;
186202
187203 if (!inode->i_op->fiemap)
....@@ -193,24 +209,13 @@
193209 if (fiemap.fm_extent_count > FIEMAP_MAX_EXTENTS)
194210 return -EINVAL;
195211
196
- error = fiemap_check_ranges(sb, fiemap.fm_start, fiemap.fm_length,
197
- &len);
198
- if (error)
199
- return error;
200
-
201212 fieinfo.fi_flags = fiemap.fm_flags;
202213 fieinfo.fi_extents_max = fiemap.fm_extent_count;
203214 fieinfo.fi_extents_start = ufiemap->fm_extents;
204215
205
- if (fiemap.fm_extent_count != 0 &&
206
- !access_ok(VERIFY_WRITE, fieinfo.fi_extents_start,
207
- fieinfo.fi_extents_max * sizeof(struct fiemap_extent)))
208
- return -EFAULT;
216
+ error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start,
217
+ fiemap.fm_length);
209218
210
- if (fieinfo.fi_flags & FIEMAP_FLAG_SYNC)
211
- filemap_write_and_wait(inode->i_mapping);
212
-
213
- error = inode->i_op->fiemap(inode, &fieinfo, fiemap.fm_start, len);
214219 fiemap.fm_flags = fieinfo.fi_flags;
215220 fiemap.fm_mapped_extents = fieinfo.fi_extents_mapped;
216221 if (copy_to_user(ufiemap, &fiemap, sizeof(fiemap)))
....@@ -223,6 +228,7 @@
223228 u64 off, u64 olen, u64 destoff)
224229 {
225230 struct fd src_file = fdget(srcfd);
231
+ loff_t cloned;
226232 int ret;
227233
228234 if (!src_file.file)
....@@ -230,13 +236,21 @@
230236 ret = -EXDEV;
231237 if (src_file.file->f_path.mnt != dst_file->f_path.mnt)
232238 goto fdput;
233
- ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen);
239
+ cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff,
240
+ olen, 0);
241
+ if (cloned < 0)
242
+ ret = cloned;
243
+ else if (olen && cloned != olen)
244
+ ret = -EINVAL;
245
+ else
246
+ ret = 0;
234247 fdput:
235248 fdput(src_file);
236249 return ret;
237250 }
238251
239
-static long ioctl_file_clone_range(struct file *file, void __user *argp)
252
+static long ioctl_file_clone_range(struct file *file,
253
+ struct file_clone_range __user *argp)
240254 {
241255 struct file_clone_range args;
242256
....@@ -277,8 +291,7 @@
277291 * If you use this function directly, you need to do your own locking. Use
278292 * generic_block_fiemap if you want the locking done for you.
279293 */
280
-
281
-int __generic_block_fiemap(struct inode *inode,
294
+static int __generic_block_fiemap(struct inode *inode,
282295 struct fiemap_extent_info *fieinfo, loff_t start,
283296 loff_t len, get_block_t *get_block)
284297 {
....@@ -290,7 +303,7 @@
290303 bool past_eof = false, whole_file = false;
291304 int ret = 0;
292305
293
- ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC);
306
+ ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_SYNC);
294307 if (ret)
295308 return ret;
296309
....@@ -423,7 +436,6 @@
423436
424437 return ret;
425438 }
426
-EXPORT_SYMBOL(__generic_block_fiemap);
427439
428440 /**
429441 * generic_block_fiemap - FIEMAP for block based inodes
....@@ -458,7 +470,7 @@
458470 * Only the l_start, l_len and l_whence fields of the 'struct space_resv'
459471 * are used here, rest are ignored.
460472 */
461
-int ioctl_preallocate(struct file *filp, void __user *argp)
473
+static int ioctl_preallocate(struct file *filp, int mode, void __user *argp)
462474 {
463475 struct inode *inode = file_inode(filp);
464476 struct space_resv sr;
....@@ -479,26 +491,55 @@
479491 return -EINVAL;
480492 }
481493
482
- return vfs_fallocate(filp, FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
494
+ return vfs_fallocate(filp, mode | FALLOC_FL_KEEP_SIZE, sr.l_start,
495
+ sr.l_len);
483496 }
484497
485
-static int file_ioctl(struct file *filp, unsigned int cmd,
486
- unsigned long arg)
498
+/* on ia32 l_start is on a 32-bit boundary */
499
+#if defined CONFIG_COMPAT && defined(CONFIG_X86_64)
500
+/* just account for different alignment */
501
+static int compat_ioctl_preallocate(struct file *file, int mode,
502
+ struct space_resv_32 __user *argp)
487503 {
488
- struct inode *inode = file_inode(filp);
489
- int __user *p = (int __user *)arg;
504
+ struct inode *inode = file_inode(file);
505
+ struct space_resv_32 sr;
490506
507
+ if (copy_from_user(&sr, argp, sizeof(sr)))
508
+ return -EFAULT;
509
+
510
+ switch (sr.l_whence) {
511
+ case SEEK_SET:
512
+ break;
513
+ case SEEK_CUR:
514
+ sr.l_start += file->f_pos;
515
+ break;
516
+ case SEEK_END:
517
+ sr.l_start += i_size_read(inode);
518
+ break;
519
+ default:
520
+ return -EINVAL;
521
+ }
522
+
523
+ return vfs_fallocate(file, mode | FALLOC_FL_KEEP_SIZE, sr.l_start, sr.l_len);
524
+}
525
+#endif
526
+
527
+static int file_ioctl(struct file *filp, unsigned int cmd, int __user *p)
528
+{
491529 switch (cmd) {
492530 case FIBMAP:
493531 return ioctl_fibmap(filp, p);
494
- case FIONREAD:
495
- return put_user(i_size_read(inode) - filp->f_pos, p);
496532 case FS_IOC_RESVSP:
497533 case FS_IOC_RESVSP64:
498
- return ioctl_preallocate(filp, p);
534
+ return ioctl_preallocate(filp, 0, p);
535
+ case FS_IOC_UNRESVSP:
536
+ case FS_IOC_UNRESVSP64:
537
+ return ioctl_preallocate(filp, FALLOC_FL_PUNCH_HOLE, p);
538
+ case FS_IOC_ZERO_RANGE:
539
+ return ioctl_preallocate(filp, FALLOC_FL_ZERO_RANGE, p);
499540 }
500541
501
- return vfs_ioctl(filp, cmd, arg);
542
+ return -ENOIOCTLCMD;
502543 }
503544
504545 static int ioctl_fionbio(struct file *filp, int __user *argp)
....@@ -576,9 +617,9 @@
576617 return thaw_super(sb);
577618 }
578619
579
-static int ioctl_file_dedupe_range(struct file *file, void __user *arg)
620
+static int ioctl_file_dedupe_range(struct file *file,
621
+ struct file_dedupe_range __user *argp)
580622 {
581
- struct file_dedupe_range __user *argp = arg;
582623 struct file_dedupe_range *same = NULL;
583624 int ret;
584625 unsigned long size;
....@@ -617,62 +658,58 @@
617658 }
618659
619660 /*
620
- * When you add any new common ioctls to the switches above and below
621
- * please update compat_sys_ioctl() too.
622
- *
623661 * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
624662 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
663
+ *
664
+ * When you add any new common ioctls to the switches above and below,
665
+ * please ensure they have compatible arguments in compat mode.
625666 */
626
-int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
627
- unsigned long arg)
667
+static int do_vfs_ioctl(struct file *filp, unsigned int fd,
668
+ unsigned int cmd, unsigned long arg)
628669 {
629
- int error = 0;
630
- int __user *argp = (int __user *)arg;
670
+ void __user *argp = (void __user *)arg;
631671 struct inode *inode = file_inode(filp);
632672
633673 switch (cmd) {
634674 case FIOCLEX:
635675 set_close_on_exec(fd, 1);
636
- break;
676
+ return 0;
637677
638678 case FIONCLEX:
639679 set_close_on_exec(fd, 0);
640
- break;
680
+ return 0;
641681
642682 case FIONBIO:
643
- error = ioctl_fionbio(filp, argp);
644
- break;
683
+ return ioctl_fionbio(filp, argp);
645684
646685 case FIOASYNC:
647
- error = ioctl_fioasync(fd, filp, argp);
648
- break;
686
+ return ioctl_fioasync(fd, filp, argp);
649687
650688 case FIOQSIZE:
651689 if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
652690 S_ISLNK(inode->i_mode)) {
653691 loff_t res = inode_get_bytes(inode);
654
- error = copy_to_user(argp, &res, sizeof(res)) ?
655
- -EFAULT : 0;
656
- } else
657
- error = -ENOTTY;
658
- break;
692
+ return copy_to_user(argp, &res, sizeof(res)) ?
693
+ -EFAULT : 0;
694
+ }
695
+
696
+ return -ENOTTY;
659697
660698 case FIFREEZE:
661
- error = ioctl_fsfreeze(filp);
662
- break;
699
+ return ioctl_fsfreeze(filp);
663700
664701 case FITHAW:
665
- error = ioctl_fsthaw(filp);
666
- break;
702
+ return ioctl_fsthaw(filp);
667703
668704 case FS_IOC_FIEMAP:
669
- return ioctl_fiemap(filp, arg);
705
+ return ioctl_fiemap(filp, argp);
670706
671707 case FIGETBSZ:
672708 /* anon_bdev filesystems may not have a block size */
673709 if (!inode->i_sb->s_blocksize)
674710 return -EINVAL;
675
- return put_user(inode->i_sb->s_blocksize, argp);
711
+
712
+ return put_user(inode->i_sb->s_blocksize, (int __user *)argp);
676713
677714 case FICLONE:
678715 return ioctl_file_clone(filp, arg, 0, 0, 0);
....@@ -683,31 +720,134 @@
683720 case FIDEDUPERANGE:
684721 return ioctl_file_dedupe_range(filp, argp);
685722
723
+ case FIONREAD:
724
+ if (!S_ISREG(inode->i_mode))
725
+ return vfs_ioctl(filp, cmd, arg);
726
+
727
+ return put_user(i_size_read(inode) - filp->f_pos,
728
+ (int __user *)argp);
729
+
686730 default:
687731 if (S_ISREG(inode->i_mode))
688
- error = file_ioctl(filp, cmd, arg);
689
- else
690
- error = vfs_ioctl(filp, cmd, arg);
732
+ return file_ioctl(filp, cmd, argp);
691733 break;
692734 }
693
- return error;
694
-}
695735
696
-int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
697
-{
698
- int error;
699
- struct fd f = fdget(fd);
700
-
701
- if (!f.file)
702
- return -EBADF;
703
- error = security_file_ioctl(f.file, cmd, arg);
704
- if (!error)
705
- error = do_vfs_ioctl(f.file, fd, cmd, arg);
706
- fdput(f);
707
- return error;
736
+ return -ENOIOCTLCMD;
708737 }
709738
710739 SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
711740 {
712
- return ksys_ioctl(fd, cmd, arg);
741
+ struct fd f = fdget(fd);
742
+ int error;
743
+
744
+ if (!f.file)
745
+ return -EBADF;
746
+
747
+ error = security_file_ioctl(f.file, cmd, arg);
748
+ if (error)
749
+ goto out;
750
+
751
+ error = do_vfs_ioctl(f.file, fd, cmd, arg);
752
+ if (error == -ENOIOCTLCMD)
753
+ error = vfs_ioctl(f.file, cmd, arg);
754
+
755
+out:
756
+ fdput(f);
757
+ return error;
713758 }
759
+
760
+#ifdef CONFIG_COMPAT
761
+/**
762
+ * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
763
+ *
764
+ * This is not normally called as a function, but instead set in struct
765
+ * file_operations as
766
+ *
767
+ * .compat_ioctl = compat_ptr_ioctl,
768
+ *
769
+ * On most architectures, the compat_ptr_ioctl() just passes all arguments
770
+ * to the corresponding ->ioctl handler. The exception is arch/s390, where
771
+ * compat_ptr() clears the top bit of a 32-bit pointer value, so user space
772
+ * pointers to the second 2GB alias the first 2GB, as is the case for
773
+ * native 32-bit s390 user space.
774
+ *
775
+ * The compat_ptr_ioctl() function must therefore be used only with ioctl
776
+ * functions that either ignore the argument or pass a pointer to a
777
+ * compatible data type.
778
+ *
779
+ * If any ioctl command handled by fops->unlocked_ioctl passes a plain
780
+ * integer instead of a pointer, or any of the passed data types
781
+ * is incompatible between 32-bit and 64-bit architectures, a proper
782
+ * handler is required instead of compat_ptr_ioctl.
783
+ */
784
+long compat_ptr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
785
+{
786
+ if (!file->f_op->unlocked_ioctl)
787
+ return -ENOIOCTLCMD;
788
+
789
+ return file->f_op->unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
790
+}
791
+EXPORT_SYMBOL(compat_ptr_ioctl);
792
+
793
+COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
794
+ compat_ulong_t, arg)
795
+{
796
+ struct fd f = fdget(fd);
797
+ int error;
798
+
799
+ if (!f.file)
800
+ return -EBADF;
801
+
802
+ /* RED-PEN how should LSM module know it's handling 32bit? */
803
+ error = security_file_ioctl(f.file, cmd, arg);
804
+ if (error)
805
+ goto out;
806
+
807
+ switch (cmd) {
808
+ /* FICLONE takes an int argument, so don't use compat_ptr() */
809
+ case FICLONE:
810
+ error = ioctl_file_clone(f.file, arg, 0, 0, 0);
811
+ break;
812
+
813
+#if defined(CONFIG_X86_64)
814
+ /* these get messy on amd64 due to alignment differences */
815
+ case FS_IOC_RESVSP_32:
816
+ case FS_IOC_RESVSP64_32:
817
+ error = compat_ioctl_preallocate(f.file, 0, compat_ptr(arg));
818
+ break;
819
+ case FS_IOC_UNRESVSP_32:
820
+ case FS_IOC_UNRESVSP64_32:
821
+ error = compat_ioctl_preallocate(f.file, FALLOC_FL_PUNCH_HOLE,
822
+ compat_ptr(arg));
823
+ break;
824
+ case FS_IOC_ZERO_RANGE_32:
825
+ error = compat_ioctl_preallocate(f.file, FALLOC_FL_ZERO_RANGE,
826
+ compat_ptr(arg));
827
+ break;
828
+#endif
829
+
830
+ /*
831
+ * everything else in do_vfs_ioctl() takes either a compatible
832
+ * pointer argument or no argument -- call it with a modified
833
+ * argument.
834
+ */
835
+ default:
836
+ error = do_vfs_ioctl(f.file, fd, cmd,
837
+ (unsigned long)compat_ptr(arg));
838
+ if (error != -ENOIOCTLCMD)
839
+ break;
840
+
841
+ if (f.file->f_op->compat_ioctl)
842
+ error = f.file->f_op->compat_ioctl(f.file, cmd, arg);
843
+ if (error == -ENOIOCTLCMD)
844
+ error = -ENOTTY;
845
+ break;
846
+ }
847
+
848
+ out:
849
+ fdput(f);
850
+
851
+ return error;
852
+}
853
+#endif