GNU Linux-libre 5.4.257-gnu1
[releases.git] / fs / xfs / xfs_attr_list.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2000-2005 Silicon Graphics, Inc.
4  * Copyright (c) 2013 Red Hat, Inc.
5  * All Rights Reserved.
6  */
7 #include "xfs.h"
8 #include "xfs_fs.h"
9 #include "xfs_shared.h"
10 #include "xfs_format.h"
11 #include "xfs_log_format.h"
12 #include "xfs_trans_resv.h"
13 #include "xfs_mount.h"
14 #include "xfs_da_format.h"
15 #include "xfs_inode.h"
16 #include "xfs_trans.h"
17 #include "xfs_bmap.h"
18 #include "xfs_attr.h"
19 #include "xfs_attr_sf.h"
20 #include "xfs_attr_leaf.h"
21 #include "xfs_error.h"
22 #include "xfs_trace.h"
23 #include "xfs_dir2.h"
24
25 STATIC int
26 xfs_attr_shortform_compare(const void *a, const void *b)
27 {
28         xfs_attr_sf_sort_t *sa, *sb;
29
30         sa = (xfs_attr_sf_sort_t *)a;
31         sb = (xfs_attr_sf_sort_t *)b;
32         if (sa->hash < sb->hash) {
33                 return -1;
34         } else if (sa->hash > sb->hash) {
35                 return 1;
36         } else {
37                 return sa->entno - sb->entno;
38         }
39 }
40
41 #define XFS_ISRESET_CURSOR(cursor) \
42         (!((cursor)->initted) && !((cursor)->hashval) && \
43          !((cursor)->blkno) && !((cursor)->offset))
44 /*
45  * Copy out entries of shortform attribute lists for attr_list().
46  * Shortform attribute lists are not stored in hashval sorted order.
47  * If the output buffer is not large enough to hold them all, then we
48  * we have to calculate each entries' hashvalue and sort them before
49  * we can begin returning them to the user.
50  */
51 static int
52 xfs_attr_shortform_list(xfs_attr_list_context_t *context)
53 {
54         attrlist_cursor_kern_t *cursor;
55         xfs_attr_sf_sort_t *sbuf, *sbp;
56         xfs_attr_shortform_t *sf;
57         xfs_attr_sf_entry_t *sfe;
58         xfs_inode_t *dp;
59         int sbsize, nsbuf, count, i;
60
61         ASSERT(context != NULL);
62         dp = context->dp;
63         ASSERT(dp != NULL);
64         ASSERT(dp->i_afp != NULL);
65         sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
66         ASSERT(sf != NULL);
67         if (!sf->hdr.count)
68                 return 0;
69         cursor = context->cursor;
70         ASSERT(cursor != NULL);
71
72         trace_xfs_attr_list_sf(context);
73
74         /*
75          * If the buffer is large enough and the cursor is at the start,
76          * do not bother with sorting since we will return everything in
77          * one buffer and another call using the cursor won't need to be
78          * made.
79          * Note the generous fudge factor of 16 overhead bytes per entry.
80          * If bufsize is zero then put_listent must be a search function
81          * and can just scan through what we have.
82          */
83         if (context->bufsize == 0 ||
84             (XFS_ISRESET_CURSOR(cursor) &&
85              (dp->i_afp->if_bytes + sf->hdr.count * 16) < context->bufsize)) {
86                 for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
87                         context->put_listent(context,
88                                              sfe->flags,
89                                              sfe->nameval,
90                                              (int)sfe->namelen,
91                                              (int)sfe->valuelen);
92                         /*
93                          * Either search callback finished early or
94                          * didn't fit it all in the buffer after all.
95                          */
96                         if (context->seen_enough)
97                                 break;
98                         sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
99                 }
100                 trace_xfs_attr_list_sf_all(context);
101                 return 0;
102         }
103
104         /* do no more for a search callback */
105         if (context->bufsize == 0)
106                 return 0;
107
108         /*
109          * It didn't all fit, so we have to sort everything on hashval.
110          */
111         sbsize = sf->hdr.count * sizeof(*sbuf);
112         sbp = sbuf = kmem_alloc(sbsize, KM_NOFS);
113
114         /*
115          * Scan the attribute list for the rest of the entries, storing
116          * the relevant info from only those that match into a buffer.
117          */
118         nsbuf = 0;
119         for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
120                 if (unlikely(
121                     ((char *)sfe < (char *)sf) ||
122                     ((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
123                         XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
124                                              XFS_ERRLEVEL_LOW,
125                                              context->dp->i_mount, sfe,
126                                              sizeof(*sfe));
127                         kmem_free(sbuf);
128                         return -EFSCORRUPTED;
129                 }
130
131                 sbp->entno = i;
132                 sbp->hash = xfs_da_hashname(sfe->nameval, sfe->namelen);
133                 sbp->name = sfe->nameval;
134                 sbp->namelen = sfe->namelen;
135                 /* These are bytes, and both on-disk, don't endian-flip */
136                 sbp->valuelen = sfe->valuelen;
137                 sbp->flags = sfe->flags;
138                 sfe = XFS_ATTR_SF_NEXTENTRY(sfe);
139                 sbp++;
140                 nsbuf++;
141         }
142
143         /*
144          * Sort the entries on hash then entno.
145          */
146         xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_attr_shortform_compare);
147
148         /*
149          * Re-find our place IN THE SORTED LIST.
150          */
151         count = 0;
152         cursor->initted = 1;
153         cursor->blkno = 0;
154         for (sbp = sbuf, i = 0; i < nsbuf; i++, sbp++) {
155                 if (sbp->hash == cursor->hashval) {
156                         if (cursor->offset == count) {
157                                 break;
158                         }
159                         count++;
160                 } else if (sbp->hash > cursor->hashval) {
161                         break;
162                 }
163         }
164         if (i == nsbuf) {
165                 kmem_free(sbuf);
166                 return 0;
167         }
168
169         /*
170          * Loop putting entries into the user buffer.
171          */
172         for ( ; i < nsbuf; i++, sbp++) {
173                 if (cursor->hashval != sbp->hash) {
174                         cursor->hashval = sbp->hash;
175                         cursor->offset = 0;
176                 }
177                 context->put_listent(context,
178                                      sbp->flags,
179                                      sbp->name,
180                                      sbp->namelen,
181                                      sbp->valuelen);
182                 if (context->seen_enough)
183                         break;
184                 cursor->offset++;
185         }
186
187         kmem_free(sbuf);
188         return 0;
189 }
190
191 /*
192  * We didn't find the block & hash mentioned in the cursor state, so
193  * walk down the attr btree looking for the hash.
194  */
195 STATIC int
196 xfs_attr_node_list_lookup(
197         struct xfs_attr_list_context    *context,
198         struct attrlist_cursor_kern     *cursor,
199         struct xfs_buf                  **pbp)
200 {
201         struct xfs_da3_icnode_hdr       nodehdr;
202         struct xfs_da_intnode           *node;
203         struct xfs_da_node_entry        *btree;
204         struct xfs_inode                *dp = context->dp;
205         struct xfs_mount                *mp = dp->i_mount;
206         struct xfs_trans                *tp = context->tp;
207         struct xfs_buf                  *bp;
208         int                             i;
209         int                             error = 0;
210         unsigned int                    expected_level = 0;
211         uint16_t                        magic;
212
213         ASSERT(*pbp == NULL);
214         cursor->blkno = 0;
215         for (;;) {
216                 error = xfs_da3_node_read(tp, dp, cursor->blkno, -1, &bp,
217                                 XFS_ATTR_FORK);
218                 if (error)
219                         return error;
220                 node = bp->b_addr;
221                 magic = be16_to_cpu(node->hdr.info.magic);
222                 if (magic == XFS_ATTR_LEAF_MAGIC ||
223                     magic == XFS_ATTR3_LEAF_MAGIC)
224                         break;
225                 if (magic != XFS_DA_NODE_MAGIC &&
226                     magic != XFS_DA3_NODE_MAGIC) {
227                         XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
228                                         node, sizeof(*node));
229                         goto out_corruptbuf;
230                 }
231
232                 dp->d_ops->node_hdr_from_disk(&nodehdr, node);
233
234                 /* Tree taller than we can handle; bail out! */
235                 if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH)
236                         goto out_corruptbuf;
237
238                 /* Check the level from the root node. */
239                 if (cursor->blkno == 0)
240                         expected_level = nodehdr.level - 1;
241                 else if (expected_level != nodehdr.level)
242                         goto out_corruptbuf;
243                 else
244                         expected_level--;
245
246                 btree = dp->d_ops->node_tree_p(node);
247                 for (i = 0; i < nodehdr.count; btree++, i++) {
248                         if (cursor->hashval <= be32_to_cpu(btree->hashval)) {
249                                 cursor->blkno = be32_to_cpu(btree->before);
250                                 trace_xfs_attr_list_node_descend(context,
251                                                 btree);
252                                 break;
253                         }
254                 }
255                 xfs_trans_brelse(tp, bp);
256
257                 if (i == nodehdr.count)
258                         return 0;
259
260                 /* We can't point back to the root. */
261                 if (cursor->blkno == 0) {
262                         XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, mp);
263                         return -EFSCORRUPTED;
264                 }
265         }
266
267         if (expected_level != 0)
268                 goto out_corruptbuf;
269
270         *pbp = bp;
271         return 0;
272
273 out_corruptbuf:
274         xfs_buf_mark_corrupt(bp);
275         xfs_trans_brelse(tp, bp);
276         return -EFSCORRUPTED;
277 }
278
279 STATIC int
280 xfs_attr_node_list(
281         struct xfs_attr_list_context    *context)
282 {
283         struct xfs_attr3_icleaf_hdr     leafhdr;
284         struct attrlist_cursor_kern     *cursor;
285         struct xfs_attr_leafblock       *leaf;
286         struct xfs_da_intnode           *node;
287         struct xfs_buf                  *bp;
288         struct xfs_inode                *dp = context->dp;
289         struct xfs_mount                *mp = dp->i_mount;
290         int                             error;
291
292         trace_xfs_attr_node_list(context);
293
294         cursor = context->cursor;
295         cursor->initted = 1;
296
297         /*
298          * Do all sorts of validation on the passed-in cursor structure.
299          * If anything is amiss, ignore the cursor and look up the hashval
300          * starting from the btree root.
301          */
302         bp = NULL;
303         if (cursor->blkno > 0) {
304                 error = xfs_da3_node_read(context->tp, dp, cursor->blkno, -1,
305                                               &bp, XFS_ATTR_FORK);
306                 if ((error != 0) && (error != -EFSCORRUPTED))
307                         return error;
308                 if (bp) {
309                         struct xfs_attr_leaf_entry *entries;
310
311                         node = bp->b_addr;
312                         switch (be16_to_cpu(node->hdr.info.magic)) {
313                         case XFS_DA_NODE_MAGIC:
314                         case XFS_DA3_NODE_MAGIC:
315                                 trace_xfs_attr_list_wrong_blk(context);
316                                 xfs_trans_brelse(context->tp, bp);
317                                 bp = NULL;
318                                 break;
319                         case XFS_ATTR_LEAF_MAGIC:
320                         case XFS_ATTR3_LEAF_MAGIC:
321                                 leaf = bp->b_addr;
322                                 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo,
323                                                              &leafhdr, leaf);
324                                 entries = xfs_attr3_leaf_entryp(leaf);
325                                 if (cursor->hashval > be32_to_cpu(
326                                                 entries[leafhdr.count - 1].hashval)) {
327                                         trace_xfs_attr_list_wrong_blk(context);
328                                         xfs_trans_brelse(context->tp, bp);
329                                         bp = NULL;
330                                 } else if (cursor->hashval <= be32_to_cpu(
331                                                 entries[0].hashval)) {
332                                         trace_xfs_attr_list_wrong_blk(context);
333                                         xfs_trans_brelse(context->tp, bp);
334                                         bp = NULL;
335                                 }
336                                 break;
337                         default:
338                                 trace_xfs_attr_list_wrong_blk(context);
339                                 xfs_trans_brelse(context->tp, bp);
340                                 bp = NULL;
341                         }
342                 }
343         }
344
345         /*
346          * We did not find what we expected given the cursor's contents,
347          * so we start from the top and work down based on the hash value.
348          * Note that start of node block is same as start of leaf block.
349          */
350         if (bp == NULL) {
351                 error = xfs_attr_node_list_lookup(context, cursor, &bp);
352                 if (error || !bp)
353                         return error;
354         }
355         ASSERT(bp != NULL);
356
357         /*
358          * Roll upward through the blocks, processing each leaf block in
359          * order.  As long as there is space in the result buffer, keep
360          * adding the information.
361          */
362         for (;;) {
363                 leaf = bp->b_addr;
364                 xfs_attr3_leaf_list_int(bp, context);
365                 xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &leafhdr, leaf);
366                 if (context->seen_enough || leafhdr.forw == 0)
367                         break;
368                 cursor->blkno = leafhdr.forw;
369                 xfs_trans_brelse(context->tp, bp);
370                 error = xfs_attr3_leaf_read(context->tp, dp, cursor->blkno, -1, &bp);
371                 if (error)
372                         return error;
373         }
374         xfs_trans_brelse(context->tp, bp);
375         return 0;
376 }
377
378 /*
379  * Copy out attribute list entries for attr_list(), for leaf attribute lists.
380  */
381 void
382 xfs_attr3_leaf_list_int(
383         struct xfs_buf                  *bp,
384         struct xfs_attr_list_context    *context)
385 {
386         struct attrlist_cursor_kern     *cursor;
387         struct xfs_attr_leafblock       *leaf;
388         struct xfs_attr3_icleaf_hdr     ichdr;
389         struct xfs_attr_leaf_entry      *entries;
390         struct xfs_attr_leaf_entry      *entry;
391         int                             i;
392         struct xfs_mount                *mp = context->dp->i_mount;
393
394         trace_xfs_attr_list_leaf(context);
395
396         leaf = bp->b_addr;
397         xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
398         entries = xfs_attr3_leaf_entryp(leaf);
399
400         cursor = context->cursor;
401         cursor->initted = 1;
402
403         /*
404          * Re-find our place in the leaf block if this is a new syscall.
405          */
406         if (context->resynch) {
407                 entry = &entries[0];
408                 for (i = 0; i < ichdr.count; entry++, i++) {
409                         if (be32_to_cpu(entry->hashval) == cursor->hashval) {
410                                 if (cursor->offset == context->dupcnt) {
411                                         context->dupcnt = 0;
412                                         break;
413                                 }
414                                 context->dupcnt++;
415                         } else if (be32_to_cpu(entry->hashval) >
416                                         cursor->hashval) {
417                                 context->dupcnt = 0;
418                                 break;
419                         }
420                 }
421                 if (i == ichdr.count) {
422                         trace_xfs_attr_list_notfound(context);
423                         return;
424                 }
425         } else {
426                 entry = &entries[0];
427                 i = 0;
428         }
429         context->resynch = 0;
430
431         /*
432          * We have found our place, start copying out the new attributes.
433          */
434         for (; i < ichdr.count; entry++, i++) {
435                 char *name;
436                 int namelen, valuelen;
437
438                 if (be32_to_cpu(entry->hashval) != cursor->hashval) {
439                         cursor->hashval = be32_to_cpu(entry->hashval);
440                         cursor->offset = 0;
441                 }
442
443                 if ((entry->flags & XFS_ATTR_INCOMPLETE) &&
444                     !(context->flags & ATTR_INCOMPLETE))
445                         continue;               /* skip incomplete entries */
446
447                 if (entry->flags & XFS_ATTR_LOCAL) {
448                         xfs_attr_leaf_name_local_t *name_loc;
449
450                         name_loc = xfs_attr3_leaf_name_local(leaf, i);
451                         name = name_loc->nameval;
452                         namelen = name_loc->namelen;
453                         valuelen = be16_to_cpu(name_loc->valuelen);
454                 } else {
455                         xfs_attr_leaf_name_remote_t *name_rmt;
456
457                         name_rmt = xfs_attr3_leaf_name_remote(leaf, i);
458                         name = name_rmt->name;
459                         namelen = name_rmt->namelen;
460                         valuelen = be32_to_cpu(name_rmt->valuelen);
461                 }
462
463                 context->put_listent(context, entry->flags,
464                                               name, namelen, valuelen);
465                 if (context->seen_enough)
466                         break;
467                 cursor->offset++;
468         }
469         trace_xfs_attr_list_leaf_end(context);
470         return;
471 }
472
473 /*
474  * Copy out attribute entries for attr_list(), for leaf attribute lists.
475  */
476 STATIC int
477 xfs_attr_leaf_list(xfs_attr_list_context_t *context)
478 {
479         int error;
480         struct xfs_buf *bp;
481
482         trace_xfs_attr_leaf_list(context);
483
484         context->cursor->blkno = 0;
485         error = xfs_attr3_leaf_read(context->tp, context->dp, 0, -1, &bp);
486         if (error)
487                 return error;
488
489         xfs_attr3_leaf_list_int(bp, context);
490         xfs_trans_brelse(context->tp, bp);
491         return 0;
492 }
493
494 int
495 xfs_attr_list_int_ilocked(
496         struct xfs_attr_list_context    *context)
497 {
498         struct xfs_inode                *dp = context->dp;
499
500         ASSERT(xfs_isilocked(dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
501
502         /*
503          * Decide on what work routines to call based on the inode size.
504          */
505         if (!xfs_inode_hasattr(dp))
506                 return 0;
507         else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL)
508                 return xfs_attr_shortform_list(context);
509         else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
510                 return xfs_attr_leaf_list(context);
511         return xfs_attr_node_list(context);
512 }
513
514 int
515 xfs_attr_list_int(
516         xfs_attr_list_context_t *context)
517 {
518         int error;
519         xfs_inode_t *dp = context->dp;
520         uint            lock_mode;
521
522         XFS_STATS_INC(dp->i_mount, xs_attr_list);
523
524         if (XFS_FORCED_SHUTDOWN(dp->i_mount))
525                 return -EIO;
526
527         lock_mode = xfs_ilock_attr_map_shared(dp);
528         error = xfs_attr_list_int_ilocked(context);
529         xfs_iunlock(dp, lock_mode);
530         return error;
531 }
532
533 #define ATTR_ENTBASESIZE                /* minimum bytes used by an attr */ \
534         (((struct attrlist_ent *) 0)->a_name - (char *) 0)
535 #define ATTR_ENTSIZE(namelen)           /* actual bytes used by an attr */ \
536         ((ATTR_ENTBASESIZE + (namelen) + 1 + sizeof(uint32_t)-1) \
537          & ~(sizeof(uint32_t)-1))
538
539 /*
540  * Format an attribute and copy it out to the user's buffer.
541  * Take care to check values and protect against them changing later,
542  * we may be reading them directly out of a user buffer.
543  */
544 STATIC void
545 xfs_attr_put_listent(
546         xfs_attr_list_context_t *context,
547         int             flags,
548         unsigned char   *name,
549         int             namelen,
550         int             valuelen)
551 {
552         struct attrlist *alist = (struct attrlist *)context->alist;
553         attrlist_ent_t *aep;
554         int arraytop;
555
556         ASSERT(!context->seen_enough);
557         ASSERT(!(context->flags & ATTR_KERNOVAL));
558         ASSERT(context->count >= 0);
559         ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
560         ASSERT(context->firstu >= sizeof(*alist));
561         ASSERT(context->firstu <= context->bufsize);
562
563         /*
564          * Only list entries in the right namespace.
565          */
566         if (((context->flags & ATTR_SECURE) == 0) !=
567             ((flags & XFS_ATTR_SECURE) == 0))
568                 return;
569         if (((context->flags & ATTR_ROOT) == 0) !=
570             ((flags & XFS_ATTR_ROOT) == 0))
571                 return;
572
573         arraytop = sizeof(*alist) +
574                         context->count * sizeof(alist->al_offset[0]);
575         context->firstu -= ATTR_ENTSIZE(namelen);
576         if (context->firstu < arraytop) {
577                 trace_xfs_attr_list_full(context);
578                 alist->al_more = 1;
579                 context->seen_enough = 1;
580                 return;
581         }
582
583         aep = (attrlist_ent_t *)&context->alist[context->firstu];
584         aep->a_valuelen = valuelen;
585         memcpy(aep->a_name, name, namelen);
586         aep->a_name[namelen] = 0;
587         alist->al_offset[context->count++] = context->firstu;
588         alist->al_count = context->count;
589         trace_xfs_attr_list_add(context);
590         return;
591 }
592
593 /*
594  * Generate a list of extended attribute names and optionally
595  * also value lengths.  Positive return value follows the XFS
596  * convention of being an error, zero or negative return code
597  * is the length of the buffer returned (negated), indicating
598  * success.
599  */
600 int
601 xfs_attr_list(
602         xfs_inode_t     *dp,
603         char            *buffer,
604         int             bufsize,
605         int             flags,
606         attrlist_cursor_kern_t *cursor)
607 {
608         xfs_attr_list_context_t context;
609         struct attrlist *alist;
610         int error;
611
612         /*
613          * Validate the cursor.
614          */
615         if (cursor->pad1 || cursor->pad2)
616                 return -EINVAL;
617         if ((cursor->initted == 0) &&
618             (cursor->hashval || cursor->blkno || cursor->offset))
619                 return -EINVAL;
620
621         /* Only internal consumers can retrieve incomplete attrs. */
622         if (flags & ATTR_INCOMPLETE)
623                 return -EINVAL;
624
625         /*
626          * Check for a properly aligned buffer.
627          */
628         if (((long)buffer) & (sizeof(int)-1))
629                 return -EFAULT;
630         if (flags & ATTR_KERNOVAL)
631                 bufsize = 0;
632
633         /*
634          * Initialize the output buffer.
635          */
636         memset(&context, 0, sizeof(context));
637         context.dp = dp;
638         context.cursor = cursor;
639         context.resynch = 1;
640         context.flags = flags;
641         context.alist = buffer;
642         context.bufsize = (bufsize & ~(sizeof(int)-1));  /* align */
643         context.firstu = context.bufsize;
644         context.put_listent = xfs_attr_put_listent;
645
646         alist = (struct attrlist *)context.alist;
647         alist->al_count = 0;
648         alist->al_more = 0;
649         alist->al_offset[0] = context.bufsize;
650
651         error = xfs_attr_list_int(&context);
652         ASSERT(error <= 0);
653         return error;
654 }