hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/xfs/xfs_ioctl32.c
....@@ -3,23 +3,19 @@
33 * Copyright (c) 2004-2005 Silicon Graphics, Inc.
44 * All Rights Reserved.
55 */
6
-#include <linux/compat.h>
7
-#include <linux/ioctl.h>
86 #include <linux/mount.h>
9
-#include <linux/slab.h>
10
-#include <linux/uaccess.h>
117 #include <linux/fsmap.h>
128 #include "xfs.h"
139 #include "xfs_fs.h"
10
+#include "xfs_shared.h"
1411 #include "xfs_format.h"
1512 #include "xfs_log_format.h"
1613 #include "xfs_trans_resv.h"
1714 #include "xfs_mount.h"
1815 #include "xfs_inode.h"
16
+#include "xfs_iwalk.h"
1917 #include "xfs_itable.h"
20
-#include "xfs_error.h"
2118 #include "xfs_fsops.h"
22
-#include "xfs_alloc.h"
2319 #include "xfs_rtalloc.h"
2420 #include "xfs_attr.h"
2521 #include "xfs_ioctl.h"
....@@ -52,12 +48,9 @@
5248 struct xfs_mount *mp,
5349 compat_xfs_fsop_geom_v1_t __user *arg32)
5450 {
55
- xfs_fsop_geom_t fsgeo;
56
- int error;
51
+ struct xfs_fsop_geom fsgeo;
5752
58
- error = xfs_fs_geometry(&mp->m_sb, &fsgeo, 3);
59
- if (error)
60
- return error;
53
+ xfs_fs_geometry(&mp->m_sb, &fsgeo, 3);
6154 /* The 32-bit variant simply has some padding at the end */
6255 if (copy_to_user(arg32, &fsgeo, sizeof(struct compat_xfs_fsop_geom_v1)))
6356 return -EFAULT;
....@@ -87,27 +80,26 @@
8780 }
8881
8982 STATIC int
90
-xfs_inumbers_fmt_compat(
91
- void __user *ubuffer,
92
- const struct xfs_inogrp *buffer,
93
- long count,
94
- long *written)
83
+xfs_fsinumbers_fmt_compat(
84
+ struct xfs_ibulk *breq,
85
+ const struct xfs_inumbers *ig)
9586 {
96
- compat_xfs_inogrp_t __user *p32 = ubuffer;
97
- long i;
87
+ struct compat_xfs_inogrp __user *p32 = breq->ubuffer;
88
+ struct xfs_inogrp ig1;
89
+ struct xfs_inogrp *igrp = &ig1;
9890
99
- for (i = 0; i < count; i++) {
100
- if (put_user(buffer[i].xi_startino, &p32[i].xi_startino) ||
101
- put_user(buffer[i].xi_alloccount, &p32[i].xi_alloccount) ||
102
- put_user(buffer[i].xi_allocmask, &p32[i].xi_allocmask))
103
- return -EFAULT;
104
- }
105
- *written = count * sizeof(*p32);
106
- return 0;
91
+ xfs_inumbers_to_inogrp(&ig1, ig);
92
+
93
+ if (put_user(igrp->xi_startino, &p32->xi_startino) ||
94
+ put_user(igrp->xi_alloccount, &p32->xi_alloccount) ||
95
+ put_user(igrp->xi_allocmask, &p32->xi_allocmask))
96
+ return -EFAULT;
97
+
98
+ return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_inogrp));
10799 }
108100
109101 #else
110
-#define xfs_inumbers_fmt_compat xfs_inumbers_fmt
102
+#define xfs_fsinumbers_fmt_compat xfs_fsinumbers_fmt
111103 #endif /* BROKEN_X86_ALIGNMENT */
112104
113105 STATIC int
....@@ -115,7 +107,7 @@
115107 xfs_bstime_t *bstime,
116108 compat_xfs_bstime_t __user *bstime32)
117109 {
118
- compat_time_t sec32; /* tv_sec differs on 64 vs. 32 */
110
+ old_time32_t sec32; /* tv_sec differs on 64 vs. 32 */
119111
120112 if (get_user(sec32, &bstime32->tv_sec) ||
121113 get_user(bstime->tv_nsec, &bstime32->tv_nsec))
....@@ -124,11 +116,14 @@
124116 return 0;
125117 }
126118
127
-/* xfs_bstat_t has differing alignment on intel, & bstime_t sizes everywhere */
119
+/*
120
+ * struct xfs_bstat has differing alignment on intel, & bstime_t sizes
121
+ * everywhere
122
+ */
128123 STATIC int
129124 xfs_ioctl32_bstat_copyin(
130
- xfs_bstat_t *bstat,
131
- compat_xfs_bstat_t __user *bstat32)
125
+ struct xfs_bstat *bstat,
126
+ struct compat_xfs_bstat __user *bstat32)
132127 {
133128 if (get_user(bstat->bs_ino, &bstat32->bs_ino) ||
134129 get_user(bstat->bs_mode, &bstat32->bs_mode) ||
....@@ -174,16 +169,15 @@
174169
175170 /* Return 0 on success or positive error (to xfs_bulkstat()) */
176171 STATIC int
177
-xfs_bulkstat_one_fmt_compat(
178
- void __user *ubuffer,
179
- int ubsize,
180
- int *ubused,
181
- const xfs_bstat_t *buffer)
172
+xfs_fsbulkstat_one_fmt_compat(
173
+ struct xfs_ibulk *breq,
174
+ const struct xfs_bulkstat *bstat)
182175 {
183
- compat_xfs_bstat_t __user *p32 = ubuffer;
176
+ struct compat_xfs_bstat __user *p32 = breq->ubuffer;
177
+ struct xfs_bstat bs1;
178
+ struct xfs_bstat *buffer = &bs1;
184179
185
- if (ubsize < sizeof(*p32))
186
- return -ENOMEM;
180
+ xfs_bulkstat_to_bstat(breq->mp, &bs1, bstat);
187181
188182 if (put_user(buffer->bs_ino, &p32->bs_ino) ||
189183 put_user(buffer->bs_mode, &p32->bs_mode) ||
....@@ -208,37 +202,24 @@
208202 put_user(buffer->bs_dmstate, &p32->bs_dmstate) ||
209203 put_user(buffer->bs_aextents, &p32->bs_aextents))
210204 return -EFAULT;
211
- if (ubused)
212
- *ubused = sizeof(*p32);
213
- return 0;
214
-}
215205
216
-STATIC int
217
-xfs_bulkstat_one_compat(
218
- xfs_mount_t *mp, /* mount point for filesystem */
219
- xfs_ino_t ino, /* inode number to get data for */
220
- void __user *buffer, /* buffer to place output in */
221
- int ubsize, /* size of buffer */
222
- int *ubused, /* bytes used by me */
223
- int *stat) /* BULKSTAT_RV_... */
224
-{
225
- return xfs_bulkstat_one_int(mp, ino, buffer, ubsize,
226
- xfs_bulkstat_one_fmt_compat,
227
- ubused, stat);
206
+ return xfs_ibulk_advance(breq, sizeof(struct compat_xfs_bstat));
228207 }
229208
230209 /* copied from xfs_ioctl.c */
231210 STATIC int
232
-xfs_compat_ioc_bulkstat(
211
+xfs_compat_ioc_fsbulkstat(
233212 xfs_mount_t *mp,
234213 unsigned int cmd,
235
- compat_xfs_fsop_bulkreq_t __user *p32)
214
+ struct compat_xfs_fsop_bulkreq __user *p32)
236215 {
237216 u32 addr;
238
- xfs_fsop_bulkreq_t bulkreq;
239
- int count; /* # of records returned */
240
- xfs_ino_t inlast; /* last inode number */
241
- int done;
217
+ struct xfs_fsop_bulkreq bulkreq;
218
+ struct xfs_ibulk breq = {
219
+ .mp = mp,
220
+ .ocount = 0,
221
+ };
222
+ xfs_ino_t lastino;
242223 int error;
243224
244225 /*
....@@ -247,9 +228,8 @@
247228 * to userpace memory via bulkreq.ubuffer. Normally the compat
248229 * functions and structure size are the correct ones to use ...
249230 */
250
- inumbers_fmt_pf inumbers_func = xfs_inumbers_fmt_compat;
251
- bulkstat_one_pf bs_one_func = xfs_bulkstat_one_compat;
252
- size_t bs_one_size = sizeof(struct compat_xfs_bstat);
231
+ inumbers_fmt_pf inumbers_func = xfs_fsinumbers_fmt_compat;
232
+ bulkstat_one_fmt_pf bs_one_func = xfs_fsbulkstat_one_fmt_compat;
253233
254234 #ifdef CONFIG_X86_X32
255235 if (in_x32_syscall()) {
....@@ -261,9 +241,8 @@
261241 * the data written out in compat layout will not match what
262242 * x32 userspace expects.
263243 */
264
- inumbers_func = xfs_inumbers_fmt;
265
- bs_one_func = xfs_bulkstat_one;
266
- bs_one_size = sizeof(struct xfs_bstat);
244
+ inumbers_func = xfs_fsinumbers_fmt;
245
+ bs_one_func = xfs_fsbulkstat_one_fmt;
267246 }
268247 #endif
269248
....@@ -287,40 +266,55 @@
287266 return -EFAULT;
288267 bulkreq.ocount = compat_ptr(addr);
289268
290
- if (copy_from_user(&inlast, bulkreq.lastip, sizeof(__s64)))
269
+ if (copy_from_user(&lastino, bulkreq.lastip, sizeof(__s64)))
291270 return -EFAULT;
292271
293
- if ((count = bulkreq.icount) <= 0)
272
+ if (bulkreq.icount <= 0)
294273 return -EINVAL;
295274
296275 if (bulkreq.ubuffer == NULL)
297276 return -EINVAL;
298277
299
- if (cmd == XFS_IOC_FSINUMBERS_32) {
300
- error = xfs_inumbers(mp, &inlast, &count,
301
- bulkreq.ubuffer, inumbers_func);
302
- } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
303
- int res;
278
+ breq.ubuffer = bulkreq.ubuffer;
279
+ breq.icount = bulkreq.icount;
304280
305
- error = bs_one_func(mp, inlast, bulkreq.ubuffer,
306
- bs_one_size, NULL, &res);
281
+ /*
282
+ * FSBULKSTAT_SINGLE expects that *lastip contains the inode number
283
+ * that we want to stat. However, FSINUMBERS and FSBULKSTAT expect
284
+ * that *lastip contains either zero or the number of the last inode to
285
+ * be examined by the previous call and return results starting with
286
+ * the next inode after that. The new bulk request back end functions
287
+ * take the inode to start with, so we have to compute the startino
288
+ * parameter from lastino to maintain correct function. lastino == 0
289
+ * is a special case because it has traditionally meant "first inode
290
+ * in filesystem".
291
+ */
292
+ if (cmd == XFS_IOC_FSINUMBERS_32) {
293
+ breq.startino = lastino ? lastino + 1 : 0;
294
+ error = xfs_inumbers(&breq, inumbers_func);
295
+ lastino = breq.startino - 1;
296
+ } else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE_32) {
297
+ breq.startino = lastino;
298
+ breq.icount = 1;
299
+ error = xfs_bulkstat_one(&breq, bs_one_func);
300
+ lastino = breq.startino;
307301 } else if (cmd == XFS_IOC_FSBULKSTAT_32) {
308
- error = xfs_bulkstat(mp, &inlast, &count,
309
- bs_one_func, bs_one_size,
310
- bulkreq.ubuffer, &done);
311
- } else
302
+ breq.startino = lastino ? lastino + 1 : 0;
303
+ error = xfs_bulkstat(&breq, bs_one_func);
304
+ lastino = breq.startino - 1;
305
+ } else {
312306 error = -EINVAL;
307
+ }
313308 if (error)
314309 return error;
315310
316
- if (bulkreq.ocount != NULL) {
317
- if (copy_to_user(bulkreq.lastip, &inlast,
318
- sizeof(xfs_ino_t)))
319
- return -EFAULT;
311
+ if (bulkreq.lastip != NULL &&
312
+ copy_to_user(bulkreq.lastip, &lastino, sizeof(xfs_ino_t)))
313
+ return -EFAULT;
320314
321
- if (copy_to_user(bulkreq.ocount, &count, sizeof(count)))
322
- return -EFAULT;
323
- }
315
+ if (bulkreq.ocount != NULL &&
316
+ copy_to_user(bulkreq.ocount, &breq.ocount, sizeof(__s32)))
317
+ return -EFAULT;
324318
325319 return 0;
326320 }
....@@ -358,56 +352,24 @@
358352 STATIC int
359353 xfs_compat_attrlist_by_handle(
360354 struct file *parfilp,
361
- void __user *arg)
355
+ compat_xfs_fsop_attrlist_handlereq_t __user *p)
362356 {
363
- int error;
364
- attrlist_cursor_kern_t *cursor;
365
- compat_xfs_fsop_attrlist_handlereq_t __user *p = arg;
366357 compat_xfs_fsop_attrlist_handlereq_t al_hreq;
367358 struct dentry *dentry;
368
- char *kbuf;
359
+ int error;
369360
370361 if (!capable(CAP_SYS_ADMIN))
371362 return -EPERM;
372
- if (copy_from_user(&al_hreq, arg,
373
- sizeof(compat_xfs_fsop_attrlist_handlereq_t)))
363
+ if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
374364 return -EFAULT;
375
- if (al_hreq.buflen < sizeof(struct attrlist) ||
376
- al_hreq.buflen > XFS_XATTR_LIST_MAX)
377
- return -EINVAL;
378
-
379
- /*
380
- * Reject flags, only allow namespaces.
381
- */
382
- if (al_hreq.flags & ~(ATTR_ROOT | ATTR_SECURE))
383
- return -EINVAL;
384365
385366 dentry = xfs_compat_handlereq_to_dentry(parfilp, &al_hreq.hreq);
386367 if (IS_ERR(dentry))
387368 return PTR_ERR(dentry);
388369
389
- error = -ENOMEM;
390
- kbuf = kmem_zalloc_large(al_hreq.buflen, KM_SLEEP);
391
- if (!kbuf)
392
- goto out_dput;
393
-
394
- cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
395
- error = xfs_attr_list(XFS_I(d_inode(dentry)), kbuf, al_hreq.buflen,
396
- al_hreq.flags, cursor);
397
- if (error)
398
- goto out_kfree;
399
-
400
- if (copy_to_user(&p->pos, cursor, sizeof(attrlist_cursor_kern_t))) {
401
- error = -EFAULT;
402
- goto out_kfree;
403
- }
404
-
405
- if (copy_to_user(compat_ptr(al_hreq.buffer), kbuf, al_hreq.buflen))
406
- error = -EFAULT;
407
-
408
-out_kfree:
409
- kmem_free(kbuf);
410
-out_dput:
370
+ error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)),
371
+ compat_ptr(al_hreq.buffer), al_hreq.buflen,
372
+ al_hreq.flags, &p->pos);
411373 dput(dentry);
412374 return error;
413375 }
....@@ -422,7 +384,6 @@
422384 compat_xfs_fsop_attrmulti_handlereq_t am_hreq;
423385 struct dentry *dentry;
424386 unsigned int i, size;
425
- unsigned char *attr_name;
426387
427388 if (!capable(CAP_SYS_ADMIN))
428389 return -EPERM;
....@@ -449,97 +410,20 @@
449410 goto out_dput;
450411 }
451412
452
- error = -ENOMEM;
453
- attr_name = kmalloc(MAXNAMELEN, GFP_KERNEL);
454
- if (!attr_name)
455
- goto out_kfree_ops;
456
-
457413 error = 0;
458414 for (i = 0; i < am_hreq.opcount; i++) {
459
- ops[i].am_error = strncpy_from_user((char *)attr_name,
415
+ ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
416
+ d_inode(dentry), ops[i].am_opcode,
460417 compat_ptr(ops[i].am_attrname),
461
- MAXNAMELEN);
462
- if (ops[i].am_error == 0 || ops[i].am_error == MAXNAMELEN)
463
- error = -ERANGE;
464
- if (ops[i].am_error < 0)
465
- break;
466
-
467
- switch (ops[i].am_opcode) {
468
- case ATTR_OP_GET:
469
- ops[i].am_error = xfs_attrmulti_attr_get(
470
- d_inode(dentry), attr_name,
471
- compat_ptr(ops[i].am_attrvalue),
472
- &ops[i].am_length, ops[i].am_flags);
473
- break;
474
- case ATTR_OP_SET:
475
- ops[i].am_error = mnt_want_write_file(parfilp);
476
- if (ops[i].am_error)
477
- break;
478
- ops[i].am_error = xfs_attrmulti_attr_set(
479
- d_inode(dentry), attr_name,
480
- compat_ptr(ops[i].am_attrvalue),
481
- ops[i].am_length, ops[i].am_flags);
482
- mnt_drop_write_file(parfilp);
483
- break;
484
- case ATTR_OP_REMOVE:
485
- ops[i].am_error = mnt_want_write_file(parfilp);
486
- if (ops[i].am_error)
487
- break;
488
- ops[i].am_error = xfs_attrmulti_attr_remove(
489
- d_inode(dentry), attr_name,
490
- ops[i].am_flags);
491
- mnt_drop_write_file(parfilp);
492
- break;
493
- default:
494
- ops[i].am_error = -EINVAL;
495
- }
418
+ compat_ptr(ops[i].am_attrvalue),
419
+ &ops[i].am_length, ops[i].am_flags);
496420 }
497421
498422 if (copy_to_user(compat_ptr(am_hreq.ops), ops, size))
499423 error = -EFAULT;
500424
501
- kfree(attr_name);
502
- out_kfree_ops:
503425 kfree(ops);
504426 out_dput:
505
- dput(dentry);
506
- return error;
507
-}
508
-
509
-STATIC int
510
-xfs_compat_fssetdm_by_handle(
511
- struct file *parfilp,
512
- void __user *arg)
513
-{
514
- int error;
515
- struct fsdmidata fsd;
516
- compat_xfs_fsop_setdm_handlereq_t dmhreq;
517
- struct dentry *dentry;
518
-
519
- if (!capable(CAP_MKNOD))
520
- return -EPERM;
521
- if (copy_from_user(&dmhreq, arg,
522
- sizeof(compat_xfs_fsop_setdm_handlereq_t)))
523
- return -EFAULT;
524
-
525
- dentry = xfs_compat_handlereq_to_dentry(parfilp, &dmhreq.hreq);
526
- if (IS_ERR(dentry))
527
- return PTR_ERR(dentry);
528
-
529
- if (IS_IMMUTABLE(d_inode(dentry)) || IS_APPEND(d_inode(dentry))) {
530
- error = -EPERM;
531
- goto out;
532
- }
533
-
534
- if (copy_from_user(&fsd, compat_ptr(dmhreq.data), sizeof(fsd))) {
535
- error = -EFAULT;
536
- goto out;
537
- }
538
-
539
- error = xfs_set_dmattrs(XFS_I(d_inode(dentry)), fsd.fsd_dmevmask,
540
- fsd.fsd_dmstate);
541
-
542
-out:
543427 dput(dentry);
544428 return error;
545429 }
....@@ -553,63 +437,23 @@
553437 struct inode *inode = file_inode(filp);
554438 struct xfs_inode *ip = XFS_I(inode);
555439 struct xfs_mount *mp = ip->i_mount;
556
- void __user *arg = (void __user *)p;
440
+ void __user *arg = compat_ptr(p);
557441 int error;
558442
559443 trace_xfs_file_compat_ioctl(ip);
560444
561445 switch (cmd) {
562
- /* No size or alignment issues on any arch */
563
- case XFS_IOC_DIOINFO:
564
- case XFS_IOC_FSGEOMETRY:
565
- case XFS_IOC_FSGETXATTR:
566
- case XFS_IOC_FSSETXATTR:
567
- case XFS_IOC_FSGETXATTRA:
568
- case XFS_IOC_FSSETDM:
569
- case XFS_IOC_GETBMAP:
570
- case XFS_IOC_GETBMAPA:
571
- case XFS_IOC_GETBMAPX:
572
- case XFS_IOC_FSCOUNTS:
573
- case XFS_IOC_SET_RESBLKS:
574
- case XFS_IOC_GET_RESBLKS:
575
- case XFS_IOC_FSGROWFSLOG:
576
- case XFS_IOC_GOINGDOWN:
577
- case XFS_IOC_ERROR_INJECTION:
578
- case XFS_IOC_ERROR_CLEARALL:
579
- case FS_IOC_GETFSMAP:
580
- case XFS_IOC_SCRUB_METADATA:
581
- return xfs_file_ioctl(filp, cmd, p);
582
-#ifndef BROKEN_X86_ALIGNMENT
583
- /* These are handled fine if no alignment issues */
584
- case XFS_IOC_ALLOCSP:
585
- case XFS_IOC_FREESP:
586
- case XFS_IOC_RESVSP:
587
- case XFS_IOC_UNRESVSP:
588
- case XFS_IOC_ALLOCSP64:
589
- case XFS_IOC_FREESP64:
590
- case XFS_IOC_RESVSP64:
591
- case XFS_IOC_UNRESVSP64:
592
- case XFS_IOC_FSGEOMETRY_V1:
593
- case XFS_IOC_FSGROWFSDATA:
594
- case XFS_IOC_FSGROWFSRT:
595
- case XFS_IOC_ZERO_RANGE:
596
- return xfs_file_ioctl(filp, cmd, p);
597
-#else
446
+#if defined(BROKEN_X86_ALIGNMENT)
598447 case XFS_IOC_ALLOCSP_32:
599448 case XFS_IOC_FREESP_32:
600449 case XFS_IOC_ALLOCSP64_32:
601
- case XFS_IOC_FREESP64_32:
602
- case XFS_IOC_RESVSP_32:
603
- case XFS_IOC_UNRESVSP_32:
604
- case XFS_IOC_RESVSP64_32:
605
- case XFS_IOC_UNRESVSP64_32:
606
- case XFS_IOC_ZERO_RANGE_32: {
450
+ case XFS_IOC_FREESP64_32: {
607451 struct xfs_flock64 bf;
608452
609453 if (xfs_compat_flock64_copyin(&bf, arg))
610454 return -EFAULT;
611455 cmd = _NATIVE_IOC(cmd, struct xfs_flock64);
612
- return xfs_ioc_space(filp, cmd, &bf);
456
+ return xfs_ioc_space(filp, &bf);
613457 }
614458 case XFS_IOC_FSGEOMETRY_V1_32:
615459 return xfs_compat_ioc_fsgeometry_v1(mp, arg);
....@@ -663,7 +507,7 @@
663507 case XFS_IOC_FSBULKSTAT_32:
664508 case XFS_IOC_FSBULKSTAT_SINGLE_32:
665509 case XFS_IOC_FSINUMBERS_32:
666
- return xfs_compat_ioc_bulkstat(mp, cmd, arg);
510
+ return xfs_compat_ioc_fsbulkstat(mp, cmd, arg);
667511 case XFS_IOC_FD_TO_HANDLE_32:
668512 case XFS_IOC_PATH_TO_HANDLE_32:
669513 case XFS_IOC_PATH_TO_FSHANDLE_32: {
....@@ -692,9 +536,8 @@
692536 return xfs_compat_attrlist_by_handle(filp, arg);
693537 case XFS_IOC_ATTRMULTI_BY_HANDLE_32:
694538 return xfs_compat_attrmulti_by_handle(filp, arg);
695
- case XFS_IOC_FSSETDM_BY_HANDLE_32:
696
- return xfs_compat_fssetdm_by_handle(filp, arg);
697539 default:
698
- return -ENOIOCTLCMD;
540
+ /* try the native version */
541
+ return xfs_file_ioctl(filp, cmd, (unsigned long)arg);
699542 }
700543 }