fs/ntfs3: Fix a memory leak on object opts
[platform/kernel/linux-starfive.git] / fs / ntfs3 / dir.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *
4  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
5  *
6  *  Directory handling functions for NTFS-based filesystems.
7  *
8  */
9
10 #include <linux/fs.h>
11 #include <linux/nls.h>
12
13 #include "debug.h"
14 #include "ntfs.h"
15 #include "ntfs_fs.h"
16
17 /* Convert little endian UTF-16 to NLS string. */
18 int ntfs_utf16_to_nls(struct ntfs_sb_info *sbi, const struct le_str *uni,
19                       u8 *buf, int buf_len)
20 {
21         int ret, uni_len, warn;
22         const __le16 *ip;
23         u8 *op;
24         struct nls_table *nls = sbi->options->nls;
25
26         static_assert(sizeof(wchar_t) == sizeof(__le16));
27
28         if (!nls) {
29                 /* UTF-16 -> UTF-8 */
30                 ret = utf16s_to_utf8s((wchar_t *)uni->name, uni->len,
31                                       UTF16_LITTLE_ENDIAN, buf, buf_len);
32                 buf[ret] = '\0';
33                 return ret;
34         }
35
36         ip = uni->name;
37         op = buf;
38         uni_len = uni->len;
39         warn = 0;
40
41         while (uni_len--) {
42                 u16 ec;
43                 int charlen;
44                 char dump[5];
45
46                 if (buf_len < NLS_MAX_CHARSET_SIZE) {
47                         ntfs_warn(sbi->sb,
48                                   "filename was truncated while converting.");
49                         break;
50                 }
51
52                 ec = le16_to_cpu(*ip++);
53                 charlen = nls->uni2char(ec, op, buf_len);
54
55                 if (charlen > 0) {
56                         op += charlen;
57                         buf_len -= charlen;
58                         continue;
59                 }
60
61                 *op++ = '_';
62                 buf_len -= 1;
63                 if (warn)
64                         continue;
65
66                 warn = 1;
67                 hex_byte_pack(&dump[0], ec >> 8);
68                 hex_byte_pack(&dump[2], ec);
69                 dump[4] = 0;
70
71                 ntfs_err(sbi->sb, "failed to convert \"%s\" to %s", dump,
72                          nls->charset);
73         }
74
75         *op = '\0';
76         return op - buf;
77 }
78
79 // clang-format off
80 #define PLANE_SIZE      0x00010000
81
82 #define SURROGATE_PAIR  0x0000d800
83 #define SURROGATE_LOW   0x00000400
84 #define SURROGATE_BITS  0x000003ff
85 // clang-format on
86
87 /*
88  * put_utf16 - Modified version of put_utf16 from fs/nls/nls_base.c
89  *
90  * Function is sparse warnings free.
91  */
92 static inline void put_utf16(wchar_t *s, unsigned int c,
93                              enum utf16_endian endian)
94 {
95         static_assert(sizeof(wchar_t) == sizeof(__le16));
96         static_assert(sizeof(wchar_t) == sizeof(__be16));
97
98         switch (endian) {
99         default:
100                 *s = (wchar_t)c;
101                 break;
102         case UTF16_LITTLE_ENDIAN:
103                 *(__le16 *)s = __cpu_to_le16(c);
104                 break;
105         case UTF16_BIG_ENDIAN:
106                 *(__be16 *)s = __cpu_to_be16(c);
107                 break;
108         }
109 }
110
111 /*
112  * _utf8s_to_utf16s
113  *
114  * Modified version of 'utf8s_to_utf16s' allows to
115  * detect -ENAMETOOLONG without writing out of expected maximum.
116  */
117 static int _utf8s_to_utf16s(const u8 *s, int inlen, enum utf16_endian endian,
118                             wchar_t *pwcs, int maxout)
119 {
120         u16 *op;
121         int size;
122         unicode_t u;
123
124         op = pwcs;
125         while (inlen > 0 && *s) {
126                 if (*s & 0x80) {
127                         size = utf8_to_utf32(s, inlen, &u);
128                         if (size < 0)
129                                 return -EINVAL;
130                         s += size;
131                         inlen -= size;
132
133                         if (u >= PLANE_SIZE) {
134                                 if (maxout < 2)
135                                         return -ENAMETOOLONG;
136
137                                 u -= PLANE_SIZE;
138                                 put_utf16(op++,
139                                           SURROGATE_PAIR |
140                                                   ((u >> 10) & SURROGATE_BITS),
141                                           endian);
142                                 put_utf16(op++,
143                                           SURROGATE_PAIR | SURROGATE_LOW |
144                                                   (u & SURROGATE_BITS),
145                                           endian);
146                                 maxout -= 2;
147                         } else {
148                                 if (maxout < 1)
149                                         return -ENAMETOOLONG;
150
151                                 put_utf16(op++, u, endian);
152                                 maxout--;
153                         }
154                 } else {
155                         if (maxout < 1)
156                                 return -ENAMETOOLONG;
157
158                         put_utf16(op++, *s++, endian);
159                         inlen--;
160                         maxout--;
161                 }
162         }
163         return op - pwcs;
164 }
165
166 /*
167  * ntfs_nls_to_utf16 - Convert input string to UTF-16.
168  * @name:       Input name.
169  * @name_len:   Input name length.
170  * @uni:        Destination memory.
171  * @max_ulen:   Destination memory.
172  * @endian:     Endian of target UTF-16 string.
173  *
174  * This function is called:
175  * - to create NTFS name
176  * - to create symlink
177  *
178  * Return: UTF-16 string length or error (if negative).
179  */
180 int ntfs_nls_to_utf16(struct ntfs_sb_info *sbi, const u8 *name, u32 name_len,
181                       struct cpu_str *uni, u32 max_ulen,
182                       enum utf16_endian endian)
183 {
184         int ret, slen;
185         const u8 *end;
186         struct nls_table *nls = sbi->options->nls;
187         u16 *uname = uni->name;
188
189         static_assert(sizeof(wchar_t) == sizeof(u16));
190
191         if (!nls) {
192                 /* utf8 -> utf16 */
193                 ret = _utf8s_to_utf16s(name, name_len, endian, uname, max_ulen);
194                 uni->len = ret;
195                 return ret;
196         }
197
198         for (ret = 0, end = name + name_len; name < end; ret++, name += slen) {
199                 if (ret >= max_ulen)
200                         return -ENAMETOOLONG;
201
202                 slen = nls->char2uni(name, end - name, uname + ret);
203                 if (!slen)
204                         return -EINVAL;
205                 if (slen < 0)
206                         return slen;
207         }
208
209 #ifdef __BIG_ENDIAN
210         if (endian == UTF16_LITTLE_ENDIAN) {
211                 int i = ret;
212
213                 while (i--) {
214                         __cpu_to_le16s(uname);
215                         uname++;
216                 }
217         }
218 #else
219         if (endian == UTF16_BIG_ENDIAN) {
220                 int i = ret;
221
222                 while (i--) {
223                         __cpu_to_be16s(uname);
224                         uname++;
225                 }
226         }
227 #endif
228
229         uni->len = ret;
230         return ret;
231 }
232
233 /*
234  * dir_search_u - Helper function.
235  */
236 struct inode *dir_search_u(struct inode *dir, const struct cpu_str *uni,
237                            struct ntfs_fnd *fnd)
238 {
239         int err = 0;
240         struct super_block *sb = dir->i_sb;
241         struct ntfs_sb_info *sbi = sb->s_fs_info;
242         struct ntfs_inode *ni = ntfs_i(dir);
243         struct NTFS_DE *e;
244         int diff;
245         struct inode *inode = NULL;
246         struct ntfs_fnd *fnd_a = NULL;
247
248         if (!fnd) {
249                 fnd_a = fnd_get();
250                 if (!fnd_a) {
251                         err = -ENOMEM;
252                         goto out;
253                 }
254                 fnd = fnd_a;
255         }
256
257         err = indx_find(&ni->dir, ni, NULL, uni, 0, sbi, &diff, &e, fnd);
258
259         if (err)
260                 goto out;
261
262         if (diff) {
263                 err = -ENOENT;
264                 goto out;
265         }
266
267         inode = ntfs_iget5(sb, &e->ref, uni);
268         if (!IS_ERR(inode) && is_bad_inode(inode)) {
269                 iput(inode);
270                 err = -EINVAL;
271         }
272 out:
273         fnd_put(fnd_a);
274
275         return err == -ENOENT ? NULL : err ? ERR_PTR(err) : inode;
276 }
277
278 static inline int ntfs_filldir(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
279                                const struct NTFS_DE *e, u8 *name,
280                                struct dir_context *ctx)
281 {
282         const struct ATTR_FILE_NAME *fname;
283         unsigned long ino;
284         int name_len;
285         u32 dt_type;
286
287         fname = Add2Ptr(e, sizeof(struct NTFS_DE));
288
289         if (fname->type == FILE_NAME_DOS)
290                 return 0;
291
292         if (!mi_is_ref(&ni->mi, &fname->home))
293                 return 0;
294
295         ino = ino_get(&e->ref);
296
297         if (ino == MFT_REC_ROOT)
298                 return 0;
299
300         /* Skip meta files. Unless option to show metafiles is set. */
301         if (!sbi->options->showmeta && ntfs_is_meta_file(sbi, ino))
302                 return 0;
303
304         if (sbi->options->nohidden && (fname->dup.fa & FILE_ATTRIBUTE_HIDDEN))
305                 return 0;
306
307         name_len = ntfs_utf16_to_nls(sbi, (struct le_str *)&fname->name_len,
308                                      name, PATH_MAX);
309         if (name_len <= 0) {
310                 ntfs_warn(sbi->sb, "failed to convert name for inode %lx.",
311                           ino);
312                 return 0;
313         }
314
315         dt_type = (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY) ? DT_DIR : DT_REG;
316
317         return !dir_emit(ctx, (s8 *)name, name_len, ino, dt_type);
318 }
319
320 /*
321  * ntfs_read_hdr - Helper function for ntfs_readdir().
322  */
323 static int ntfs_read_hdr(struct ntfs_sb_info *sbi, struct ntfs_inode *ni,
324                          const struct INDEX_HDR *hdr, u64 vbo, u64 pos,
325                          u8 *name, struct dir_context *ctx)
326 {
327         int err;
328         const struct NTFS_DE *e;
329         u32 e_size;
330         u32 end = le32_to_cpu(hdr->used);
331         u32 off = le32_to_cpu(hdr->de_off);
332
333         for (;; off += e_size) {
334                 if (off + sizeof(struct NTFS_DE) > end)
335                         return -1;
336
337                 e = Add2Ptr(hdr, off);
338                 e_size = le16_to_cpu(e->size);
339                 if (e_size < sizeof(struct NTFS_DE) || off + e_size > end)
340                         return -1;
341
342                 if (de_is_last(e))
343                         return 0;
344
345                 /* Skip already enumerated. */
346                 if (vbo + off < pos)
347                         continue;
348
349                 if (le16_to_cpu(e->key_size) < SIZEOF_ATTRIBUTE_FILENAME)
350                         return -1;
351
352                 ctx->pos = vbo + off;
353
354                 /* Submit the name to the filldir callback. */
355                 err = ntfs_filldir(sbi, ni, e, name, ctx);
356                 if (err)
357                         return err;
358         }
359 }
360
361 /*
362  * ntfs_readdir - file_operations::iterate_shared
363  *
364  * Use non sorted enumeration.
365  * We have an example of broken volume where sorted enumeration
366  * counts each name twice.
367  */
368 static int ntfs_readdir(struct file *file, struct dir_context *ctx)
369 {
370         const struct INDEX_ROOT *root;
371         u64 vbo;
372         size_t bit;
373         loff_t eod;
374         int err = 0;
375         struct inode *dir = file_inode(file);
376         struct ntfs_inode *ni = ntfs_i(dir);
377         struct super_block *sb = dir->i_sb;
378         struct ntfs_sb_info *sbi = sb->s_fs_info;
379         loff_t i_size = i_size_read(dir);
380         u32 pos = ctx->pos;
381         u8 *name = NULL;
382         struct indx_node *node = NULL;
383         u8 index_bits = ni->dir.index_bits;
384
385         /* Name is a buffer of PATH_MAX length. */
386         static_assert(NTFS_NAME_LEN * 4 < PATH_MAX);
387
388         eod = i_size + sbi->record_size;
389
390         if (pos >= eod)
391                 return 0;
392
393         if (!dir_emit_dots(file, ctx))
394                 return 0;
395
396         /* Allocate PATH_MAX bytes. */
397         name = __getname();
398         if (!name)
399                 return -ENOMEM;
400
401         if (!ni->mi_loaded && ni->attr_list.size) {
402                 /*
403                  * Directory inode is locked for read.
404                  * Load all subrecords to avoid 'write' access to 'ni' during
405                  * directory reading.
406                  */
407                 ni_lock(ni);
408                 if (!ni->mi_loaded && ni->attr_list.size) {
409                         err = ni_load_all_mi(ni);
410                         if (!err)
411                                 ni->mi_loaded = true;
412                 }
413                 ni_unlock(ni);
414                 if (err)
415                         goto out;
416         }
417
418         root = indx_get_root(&ni->dir, ni, NULL, NULL);
419         if (!root) {
420                 err = -EINVAL;
421                 goto out;
422         }
423
424         if (pos >= sbi->record_size) {
425                 bit = (pos - sbi->record_size) >> index_bits;
426         } else {
427                 err = ntfs_read_hdr(sbi, ni, &root->ihdr, 0, pos, name, ctx);
428                 if (err)
429                         goto out;
430                 bit = 0;
431         }
432
433         if (!i_size) {
434                 ctx->pos = eod;
435                 goto out;
436         }
437
438         for (;;) {
439                 vbo = (u64)bit << index_bits;
440                 if (vbo >= i_size) {
441                         ctx->pos = eod;
442                         goto out;
443                 }
444
445                 err = indx_used_bit(&ni->dir, ni, &bit);
446                 if (err)
447                         goto out;
448
449                 if (bit == MINUS_ONE_T) {
450                         ctx->pos = eod;
451                         goto out;
452                 }
453
454                 vbo = (u64)bit << index_bits;
455                 if (vbo >= i_size) {
456                         ntfs_inode_err(dir, "Looks like your dir is corrupt");
457                         err = -EINVAL;
458                         goto out;
459                 }
460
461                 err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
462                                 &node);
463                 if (err)
464                         goto out;
465
466                 err = ntfs_read_hdr(sbi, ni, &node->index->ihdr,
467                                     vbo + sbi->record_size, pos, name, ctx);
468                 if (err)
469                         goto out;
470
471                 bit += 1;
472         }
473
474 out:
475
476         __putname(name);
477         put_indx_node(node);
478
479         if (err == -ENOENT) {
480                 err = 0;
481                 ctx->pos = pos;
482         }
483
484         return err;
485 }
486
487 static int ntfs_dir_count(struct inode *dir, bool *is_empty, size_t *dirs,
488                           size_t *files)
489 {
490         int err = 0;
491         struct ntfs_inode *ni = ntfs_i(dir);
492         struct NTFS_DE *e = NULL;
493         struct INDEX_ROOT *root;
494         struct INDEX_HDR *hdr;
495         const struct ATTR_FILE_NAME *fname;
496         u32 e_size, off, end;
497         u64 vbo = 0;
498         size_t drs = 0, fles = 0, bit = 0;
499         loff_t i_size = ni->vfs_inode.i_size;
500         struct indx_node *node = NULL;
501         u8 index_bits = ni->dir.index_bits;
502
503         if (is_empty)
504                 *is_empty = true;
505
506         root = indx_get_root(&ni->dir, ni, NULL, NULL);
507         if (!root)
508                 return -EINVAL;
509
510         hdr = &root->ihdr;
511
512         for (;;) {
513                 end = le32_to_cpu(hdr->used);
514                 off = le32_to_cpu(hdr->de_off);
515
516                 for (; off + sizeof(struct NTFS_DE) <= end; off += e_size) {
517                         e = Add2Ptr(hdr, off);
518                         e_size = le16_to_cpu(e->size);
519                         if (e_size < sizeof(struct NTFS_DE) ||
520                             off + e_size > end)
521                                 break;
522
523                         if (de_is_last(e))
524                                 break;
525
526                         fname = de_get_fname(e);
527                         if (!fname)
528                                 continue;
529
530                         if (fname->type == FILE_NAME_DOS)
531                                 continue;
532
533                         if (is_empty) {
534                                 *is_empty = false;
535                                 if (!dirs && !files)
536                                         goto out;
537                         }
538
539                         if (fname->dup.fa & FILE_ATTRIBUTE_DIRECTORY)
540                                 drs += 1;
541                         else
542                                 fles += 1;
543                 }
544
545                 if (vbo >= i_size)
546                         goto out;
547
548                 err = indx_used_bit(&ni->dir, ni, &bit);
549                 if (err)
550                         goto out;
551
552                 if (bit == MINUS_ONE_T)
553                         goto out;
554
555                 vbo = (u64)bit << index_bits;
556                 if (vbo >= i_size)
557                         goto out;
558
559                 err = indx_read(&ni->dir, ni, bit << ni->dir.idx2vbn_bits,
560                                 &node);
561                 if (err)
562                         goto out;
563
564                 hdr = &node->index->ihdr;
565                 bit += 1;
566                 vbo = (u64)bit << ni->dir.idx2vbn_bits;
567         }
568
569 out:
570         put_indx_node(node);
571         if (dirs)
572                 *dirs = drs;
573         if (files)
574                 *files = fles;
575
576         return err;
577 }
578
579 bool dir_is_empty(struct inode *dir)
580 {
581         bool is_empty = false;
582
583         ntfs_dir_count(dir, &is_empty, NULL, NULL);
584
585         return is_empty;
586 }
587
588 // clang-format off
589 const struct file_operations ntfs_dir_operations = {
590         .llseek         = generic_file_llseek,
591         .read           = generic_read_dir,
592         .iterate_shared = ntfs_readdir,
593         .fsync          = generic_file_fsync,
594         .open           = ntfs_file_open,
595 };
596 // clang-format on