hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/xfs/xfs_attr_list.c
....@@ -6,25 +6,20 @@
66 */
77 #include "xfs.h"
88 #include "xfs_fs.h"
9
+#include "xfs_shared.h"
910 #include "xfs_format.h"
1011 #include "xfs_log_format.h"
1112 #include "xfs_trans_resv.h"
12
-#include "xfs_bit.h"
1313 #include "xfs_mount.h"
1414 #include "xfs_da_format.h"
15
-#include "xfs_da_btree.h"
1615 #include "xfs_inode.h"
1716 #include "xfs_trans.h"
18
-#include "xfs_inode_item.h"
1917 #include "xfs_bmap.h"
2018 #include "xfs_attr.h"
2119 #include "xfs_attr_sf.h"
22
-#include "xfs_attr_remote.h"
2320 #include "xfs_attr_leaf.h"
2421 #include "xfs_error.h"
2522 #include "xfs_trace.h"
26
-#include "xfs_buf_item.h"
27
-#include "xfs_cksum.h"
2823 #include "xfs_dir2.h"
2924
3025 STATIC int
....@@ -49,30 +44,27 @@
4944 /*
5045 * Copy out entries of shortform attribute lists for attr_list().
5146 * Shortform attribute lists are not stored in hashval sorted order.
52
- * If the output buffer is not large enough to hold them all, then we
47
+ * If the output buffer is not large enough to hold them all, then
5348 * we have to calculate each entries' hashvalue and sort them before
5449 * we can begin returning them to the user.
5550 */
5651 static int
57
-xfs_attr_shortform_list(xfs_attr_list_context_t *context)
52
+xfs_attr_shortform_list(
53
+ struct xfs_attr_list_context *context)
5854 {
59
- attrlist_cursor_kern_t *cursor;
60
- xfs_attr_sf_sort_t *sbuf, *sbp;
61
- xfs_attr_shortform_t *sf;
62
- xfs_attr_sf_entry_t *sfe;
63
- xfs_inode_t *dp;
64
- int sbsize, nsbuf, count, i;
55
+ struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
56
+ struct xfs_inode *dp = context->dp;
57
+ struct xfs_attr_sf_sort *sbuf, *sbp;
58
+ struct xfs_attr_shortform *sf;
59
+ struct xfs_attr_sf_entry *sfe;
60
+ int sbsize, nsbuf, count, i;
61
+ int error = 0;
6562
66
- ASSERT(context != NULL);
67
- dp = context->dp;
68
- ASSERT(dp != NULL);
6963 ASSERT(dp->i_afp != NULL);
70
- sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
64
+ sf = (struct xfs_attr_shortform *)dp->i_afp->if_u1.if_data;
7165 ASSERT(sf != NULL);
7266 if (!sf->hdr.count)
7367 return 0;
74
- cursor = context->cursor;
75
- ASSERT(cursor != NULL);
7668
7769 trace_xfs_attr_list_sf(context);
7870
....@@ -89,6 +81,10 @@
8981 (XFS_ISRESET_CURSOR(cursor) &&
9082 (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
9183 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
84
+ if (XFS_IS_CORRUPT(context->dp->i_mount,
85
+ !xfs_attr_namecheck(sfe->nameval,
86
+ sfe->namelen)))
87
+ return -EFSCORRUPTED;
9288 context->put_listent(context,
9389 sfe->flags,
9490 sfe->nameval,
....@@ -100,7 +96,7 @@
10096 */
10197 if (context->seen_enough)
10298 break;
103
- sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
99
+ sfe = xfs_attr_sf_nextentry(sfe);
104100 }
105101 trace_xfs_attr_list_sf_all(context);
106102 return 0;
....@@ -114,7 +110,7 @@
114110 * It didn't all fit, so we have to sort everything on hashval.
115111 */
116112 sbsize = sf->hdr.count * sizeof(*sbuf);
117
- sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP | KM_NOFS);
113
+ sbp = sbuf = kmem_alloc(sbsize, KM_NOFS);
118114
119115 /*
120116 * Scan the attribute list for the rest of the entries, storing
....@@ -140,7 +136,7 @@
140136 /* These are bytes, and both on-disk, don't endian-flip */
141137 sbp->valuelen = sfe->valuelen;
142138 sbp->flags = sfe->flags;
143
- sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
139
+ sfe = xfs_attr_sf_nextentry(sfe);
144140 sbp++;
145141 nsbuf++;
146142 }
....@@ -166,10 +162,8 @@
166162 break;
167163 }
168164 }
169
- if (i == nsbuf) {
170
- kmem_free(sbuf);
171
- return 0;
172
- }
165
+ if (i == nsbuf)
166
+ goto out;
173167
174168 /*
175169 * Loop putting entries into the user buffer.
....@@ -178,6 +172,12 @@
178172 if (cursor->hashval != sbp->hash) {
179173 cursor->hashval = sbp->hash;
180174 cursor->offset = 0;
175
+ }
176
+ if (XFS_IS_CORRUPT(context->dp->i_mount,
177
+ !xfs_attr_namecheck(sbp->name,
178
+ sbp->namelen))) {
179
+ error = -EFSCORRUPTED;
180
+ goto out;
181181 }
182182 context->put_listent(context,
183183 sbp->flags,
....@@ -188,9 +188,9 @@
188188 break;
189189 cursor->offset++;
190190 }
191
-
191
+out:
192192 kmem_free(sbuf);
193
- return 0;
193
+ return error;
194194 }
195195
196196 /*
....@@ -200,7 +200,7 @@
200200 STATIC int
201201 xfs_attr_node_list_lookup(
202202 struct xfs_attr_list_context *context,
203
- struct attrlist_cursor_kern *cursor,
203
+ struct xfs_attrlist_cursor_kern *cursor,
204204 struct xfs_buf **pbp)
205205 {
206206 struct xfs_da3_icnode_hdr nodehdr;
....@@ -218,7 +218,7 @@
218218 ASSERT(*pbp == NULL);
219219 cursor->blkno = 0;
220220 for (;;) {
221
- error = xfs_da3_node_read(tp, dp, cursor->blkno, -1, &bp,
221
+ error = xfs_da3_node_read(tp, dp, cursor->blkno, &bp,
222222 XFS_ATTR_FORK);
223223 if (error)
224224 return error;
....@@ -234,7 +234,7 @@
234234 goto out_corruptbuf;
235235 }
236236
237
- dp->d_ops->node_hdr_from_disk(&nodehdr, node);
237
+ xfs_da3_node_hdr_from_disk(mp, &nodehdr, node);
238238
239239 /* Tree taller than we can handle; bail out! */
240240 if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
....@@ -248,7 +248,7 @@
248248 else
249249 expected_level--;
250250
251
- btree = dp->d_ops->node_tree_p(node);
251
+ btree = nodehdr.btree;
252252 for (i = 0; i < nodehdr.count; btree++, i++) {
253253 if (cursor->hashval <= be32_to_cpu(btree->hashval)) {
254254 cursor->blkno = be32_to_cpu(btree->before);
....@@ -263,7 +263,7 @@
263263 return 0;
264264
265265 /* We can't point back to the root. */
266
- if (cursor->blkno == 0)
266
+ if (XFS_IS_CORRUPT(mp, cursor->blkno == 0))
267267 return -EFSCORRUPTED;
268268 }
269269
....@@ -274,6 +274,7 @@
274274 return 0;
275275
276276 out_corruptbuf:
277
+ xfs_buf_mark_corrupt(bp);
277278 xfs_trans_brelse(tp, bp);
278279 return -EFSCORRUPTED;
279280 }
....@@ -282,18 +283,17 @@
282283 xfs_attr_node_list(
283284 struct xfs_attr_list_context *context)
284285 {
286
+ struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
285287 struct xfs_attr3_icleaf_hdr leafhdr;
286
- struct attrlist_cursor_kern *cursor;
287288 struct xfs_attr_leafblock *leaf;
288289 struct xfs_da_intnode *node;
289290 struct xfs_buf *bp;
290291 struct xfs_inode *dp = context->dp;
291292 struct xfs_mount *mp = dp->i_mount;
292
- int error;
293
+ int error = 0;
293294
294295 trace_xfs_attr_node_list(context);
295296
296
- cursor = context->cursor;
297297 cursor->initted = 1;
298298
299299 /*
....@@ -303,8 +303,8 @@
303303 */
304304 bp = NULL;
305305 if (cursor->blkno > 0) {
306
- error = xfs_da3_node_read(context->tp, dp, cursor->blkno, -1,
307
- &bp, XFS_ATTR_FORK);
306
+ error = xfs_da3_node_read(context->tp, dp, cursor->blkno, &bp,
307
+ XFS_ATTR_FORK);
308308 if ((error != 0) && (error != -EFSCORRUPTED))
309309 return error;
310310 if (bp) {
....@@ -363,29 +363,32 @@
363363 */
364364 for (;;) {
365365 leaf = bp->b_addr;
366
- xfs_attr3_leaf_list_int(bp, context);
366
+ error = xfs_attr3_leaf_list_int(bp, context);
367
+ if (error)
368
+ break;
367369 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
368370 if (context->seen_enough || leafhdr.forw == 0)
369371 break;
370372 cursor->blkno = leafhdr.forw;
371373 xfs_trans_brelse(context->tp, bp);
372
- error = xfs_attr3_leaf_read(context->tp, dp, cursor->blkno, -1, &bp);
374
+ error = xfs_attr3_leaf_read(context->tp, dp, cursor->blkno,
375
+ &bp);
373376 if (error)
374377 return error;
375378 }
376379 xfs_trans_brelse(context->tp, bp);
377
- return 0;
380
+ return error;
378381 }
379382
380383 /*
381384 * Copy out attribute list entries for attr_list(), for leaf attribute lists.
382385 */
383
-void
386
+int
384387 xfs_attr3_leaf_list_int(
385388 struct xfs_buf *bp,
386389 struct xfs_attr_list_context *context)
387390 {
388
- struct attrlist_cursor_kern *cursor;
391
+ struct xfs_attrlist_cursor_kern *cursor = &context->cursor;
389392 struct xfs_attr_leafblock *leaf;
390393 struct xfs_attr3_icleaf_hdr ichdr;
391394 struct xfs_attr_leaf_entry *entries;
....@@ -399,7 +402,6 @@
399402 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
400403 entries = xfs_attr3_leaf_entryp(leaf);
401404
402
- cursor = context->cursor;
403405 cursor->initted = 1;
404406
405407 /*
....@@ -422,7 +424,7 @@
422424 }
423425 if (i == ichdr.count) {
424426 trace_xfs_attr_list_notfound(context);
425
- return;
427
+ return 0;
426428 }
427429 } else {
428430 entry = &entries[0];
....@@ -443,8 +445,8 @@
443445 }
444446
445447 if ((entry->flags & XFS_ATTR_INCOMPLETE) &&
446
- !(context->flags & ATTR_INCOMPLETE))
447
- continue; /* skip incomplete entries */
448
+ !context->allow_incomplete)
449
+ continue;
448450
449451 if (entry->flags & XFS_ATTR_LOCAL) {
450452 xfs_attr_leaf_name_local_t *name_loc;
....@@ -462,6 +464,9 @@
462464 valuelen = be32_to_cpu(name_rmt->valuelen);
463465 }
464466
467
+ if (XFS_IS_CORRUPT(context->dp->i_mount,
468
+ !xfs_attr_namecheck(name, namelen)))
469
+ return -EFSCORRUPTED;
465470 context->put_listent(context, entry->flags,
466471 name, namelen, valuelen);
467472 if (context->seen_enough)
....@@ -469,32 +474,33 @@
469474 cursor->offset++;
470475 }
471476 trace_xfs_attr_list_leaf_end(context);
472
- return;
477
+ return 0;
473478 }
474479
475480 /*
476481 * Copy out attribute entries for attr_list(), for leaf attribute lists.
477482 */
478483 STATIC int
479
-xfs_attr_leaf_list(xfs_attr_list_context_t *context)
484
+xfs_attr_leaf_list(
485
+ struct xfs_attr_list_context *context)
480486 {
481
- int error;
482
- struct xfs_buf *bp;
487
+ struct xfs_buf *bp;
488
+ int error;
483489
484490 trace_xfs_attr_leaf_list(context);
485491
486
- context->cursor->blkno = 0;
487
- error = xfs_attr3_leaf_read(context->tp, context->dp, 0, -1, &bp);
492
+ context->cursor.blkno = 0;
493
+ error = xfs_attr3_leaf_read(context->tp, context->dp, 0, &bp);
488494 if (error)
489495 return error;
490496
491
- xfs_attr3_leaf_list_int(bp, context);
497
+ error = xfs_attr3_leaf_list_int(bp, context);
492498 xfs_trans_brelse(context->tp, bp);
493
- return 0;
499
+ return error;
494500 }
495501
496502 int
497
-xfs_attr_list_int_ilocked(
503
+xfs_attr_list_ilocked(
498504 struct xfs_attr_list_context *context)
499505 {
500506 struct xfs_inode *dp = context->dp;
....@@ -506,20 +512,20 @@
506512 */
507513 if (!xfs_inode_hasattr(dp))
508514 return 0;
509
- else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
515
+ if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
510516 return xfs_attr_shortform_list(context);
511
- else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
517
+ if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
512518 return xfs_attr_leaf_list(context);
513519 return xfs_attr_node_list(context);
514520 }
515521
516522 int
517
-xfs_attr_list_int(
518
- xfs_attr_list_context_t *context)
523
+xfs_attr_list(
524
+ struct xfs_attr_list_context *context)
519525 {
520
- int error;
521
- xfs_inode_t *dp = context->dp;
522
- uint lock_mode;
526
+ struct xfs_inode *dp = context->dp;
527
+ uint lock_mode;
528
+ int error;
523529
524530 XFS_STATS_INC(dp->i_mount, xs_attr_list);
525531
....@@ -527,130 +533,7 @@
527533 return -EIO;
528534
529535 lock_mode = xfs_ilock_attr_map_shared(dp);
530
- error = xfs_attr_list_int_ilocked(context);
536
+ error = xfs_attr_list_ilocked(context);
531537 xfs_iunlock(dp, lock_mode);
532
- return error;
533
-}
534
-
535
-#define ATTR_ENTBASESIZE /* minimum bytes used by an attr */ \
536
- (((struct attrlist_ent *) 0)->a_name - (char *) 0)
537
-#define ATTR_ENTSIZE(namelen) /* actual bytes used by an attr */ \
538
- ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(uint32_t)-1) \
539
- & ~(sizeof(uint32_t)-1))
540
-
541
-/*
542
- * Format an attribute and copy it out to the user's buffer.
543
- * Take care to check values and protect against them changing later,
544
- * we may be reading them directly out of a user buffer.
545
- */
546
-STATIC void
547
-xfs_attr_put_listent(
548
- xfs_attr_list_context_t *context,
549
- int flags,
550
- unsigned char *name,
551
- int namelen,
552
- int valuelen)
553
-{
554
- struct attrlist *alist = (struct attrlist *)context->alist;
555
- attrlist_ent_t *aep;
556
- int arraytop;
557
-
558
- ASSERT(!context->seen_enough);
559
- ASSERT(!(context->flags & ATTR_KERNOVAL));
560
- ASSERT(context->count >= 0);
561
- ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
562
- ASSERT(context->firstu >= sizeof(*alist));
563
- ASSERT(context->firstu <= context->bufsize);
564
-
565
- /*
566
- * Only list entries in the right namespace.
567
- */
568
- if (((context->flags & ATTR_SECURE) == 0) !=
569
- ((flags & XFS_ATTR_SECURE) == 0))
570
- return;
571
- if (((context->flags & ATTR_ROOT) == 0) !=
572
- ((flags & XFS_ATTR_ROOT) == 0))
573
- return;
574
-
575
- arraytop = sizeof(*alist) +
576
- context->count * sizeof(alist->al_offset[0]);
577
- context->firstu -= ATTR_ENTSIZE(namelen);
578
- if (context->firstu < arraytop) {
579
- trace_xfs_attr_list_full(context);
580
- alist->al_more = 1;
581
- context->seen_enough = 1;
582
- return;
583
- }
584
-
585
- aep = (attrlist_ent_t *)&context->alist[context->firstu];
586
- aep->a_valuelen = valuelen;
587
- memcpy(aep->a_name, name, namelen);
588
- aep->a_name[namelen] = 0;
589
- alist->al_offset[context->count++] = context->firstu;
590
- alist->al_count = context->count;
591
- trace_xfs_attr_list_add(context);
592
- return;
593
-}
594
-
595
-/*
596
- * Generate a list of extended attribute names and optionally
597
- * also value lengths. Positive return value follows the XFS
598
- * convention of being an error, zero or negative return code
599
- * is the length of the buffer returned (negated), indicating
600
- * success.
601
- */
602
-int
603
-xfs_attr_list(
604
- xfs_inode_t *dp,
605
- char *buffer,
606
- int bufsize,
607
- int flags,
608
- attrlist_cursor_kern_t *cursor)
609
-{
610
- xfs_attr_list_context_t context;
611
- struct attrlist *alist;
612
- int error;
613
-
614
- /*
615
- * Validate the cursor.
616
- */
617
- if (cursor->pad1 || cursor->pad2)
618
- return -EINVAL;
619
- if ((cursor->initted == 0) &&
620
- (cursor->hashval || cursor->blkno || cursor->offset))
621
- return -EINVAL;
622
-
623
- /* Only internal consumers can retrieve incomplete attrs. */
624
- if (flags & ATTR_INCOMPLETE)
625
- return -EINVAL;
626
-
627
- /*
628
- * Check for a properly aligned buffer.
629
- */
630
- if (((long)buffer) & (sizeof(int)-1))
631
- return -EFAULT;
632
- if (flags & ATTR_KERNOVAL)
633
- bufsize = 0;
634
-
635
- /*
636
- * Initialize the output buffer.
637
- */
638
- memset(&context, 0, sizeof(context));
639
- context.dp = dp;
640
- context.cursor = cursor;
641
- context.resynch = 1;
642
- context.flags = flags;
643
- context.alist = buffer;
644
- context.bufsize = (bufsize & ~(sizeof(int)-1)); /* align */
645
- context.firstu = context.bufsize;
646
- context.put_listent = xfs_attr_put_listent;
647
-
648
- alist = (struct attrlist *)context.alist;
649
- alist->al_count = 0;
650
- alist->al_more = 0;
651
- alist->al_offset[0] = context.bufsize;
652
-
653
- error = xfs_attr_list_int(&context);
654
- ASSERT(error <= 0);
655538 return error;
656539 }