Merge tag 'input-for-v5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / fs / vboxsf / utils.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * VirtualBox Guest Shared Folders support: Utility functions.
4  * Mainly conversion from/to VirtualBox/Linux data structures.
5  *
6  * Copyright (C) 2006-2018 Oracle Corporation
7  */
8
9 #include <linux/namei.h>
10 #include <linux/nls.h>
11 #include <linux/sizes.h>
12 #include <linux/pagemap.h>
13 #include <linux/vfs.h>
14 #include "vfsmod.h"
15
16 struct inode *vboxsf_new_inode(struct super_block *sb)
17 {
18         struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
19         struct inode *inode;
20         unsigned long flags;
21         int cursor, ret;
22         u32 gen;
23
24         inode = new_inode(sb);
25         if (!inode)
26                 return ERR_PTR(-ENOMEM);
27
28         idr_preload(GFP_KERNEL);
29         spin_lock_irqsave(&sbi->ino_idr_lock, flags);
30         cursor = idr_get_cursor(&sbi->ino_idr);
31         ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
32         if (ret >= 0 && ret < cursor)
33                 sbi->next_generation++;
34         gen = sbi->next_generation;
35         spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
36         idr_preload_end();
37
38         if (ret < 0) {
39                 iput(inode);
40                 return ERR_PTR(ret);
41         }
42
43         inode->i_ino = ret;
44         inode->i_generation = gen;
45         return inode;
46 }
47
48 /* set [inode] attributes based on [info], uid/gid based on [sbi] */
49 int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
50                        const struct shfl_fsobjinfo *info, bool reinit)
51 {
52         const struct shfl_fsobjattr *attr;
53         s64 allocated;
54         umode_t mode;
55
56         attr = &info->attr;
57
58 #define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
59
60         mode = mode_set(IRUSR);
61         mode |= mode_set(IWUSR);
62         mode |= mode_set(IXUSR);
63
64         mode |= mode_set(IRGRP);
65         mode |= mode_set(IWGRP);
66         mode |= mode_set(IXGRP);
67
68         mode |= mode_set(IROTH);
69         mode |= mode_set(IWOTH);
70         mode |= mode_set(IXOTH);
71
72 #undef mode_set
73
74         /* We use the host-side values for these */
75         inode->i_flags |= S_NOATIME | S_NOCMTIME;
76         inode->i_mapping->a_ops = &vboxsf_reg_aops;
77
78         if (SHFL_IS_DIRECTORY(attr->mode)) {
79                 if (sbi->o.dmode_set)
80                         mode = sbi->o.dmode;
81                 mode &= ~sbi->o.dmask;
82                 mode |= S_IFDIR;
83                 if (!reinit) {
84                         inode->i_op = &vboxsf_dir_iops;
85                         inode->i_fop = &vboxsf_dir_fops;
86                         /*
87                          * XXX: this probably should be set to the number of entries
88                          * in the directory plus two (. ..)
89                          */
90                         set_nlink(inode, 1);
91                 } else if (!S_ISDIR(inode->i_mode))
92                         return -ESTALE;
93                 inode->i_mode = mode;
94         } else if (SHFL_IS_SYMLINK(attr->mode)) {
95                 if (sbi->o.fmode_set)
96                         mode = sbi->o.fmode;
97                 mode &= ~sbi->o.fmask;
98                 mode |= S_IFLNK;
99                 if (!reinit) {
100                         inode->i_op = &vboxsf_lnk_iops;
101                         set_nlink(inode, 1);
102                 } else if (!S_ISLNK(inode->i_mode))
103                         return -ESTALE;
104                 inode->i_mode = mode;
105         } else {
106                 if (sbi->o.fmode_set)
107                         mode = sbi->o.fmode;
108                 mode &= ~sbi->o.fmask;
109                 mode |= S_IFREG;
110                 if (!reinit) {
111                         inode->i_op = &vboxsf_reg_iops;
112                         inode->i_fop = &vboxsf_reg_fops;
113                         set_nlink(inode, 1);
114                 } else if (!S_ISREG(inode->i_mode))
115                         return -ESTALE;
116                 inode->i_mode = mode;
117         }
118
119         inode->i_uid = sbi->o.uid;
120         inode->i_gid = sbi->o.gid;
121
122         inode->i_size = info->size;
123         inode->i_blkbits = 12;
124         /* i_blocks always in units of 512 bytes! */
125         allocated = info->allocated + 511;
126         do_div(allocated, 512);
127         inode->i_blocks = allocated;
128
129         inode->i_atime = ns_to_timespec64(
130                                  info->access_time.ns_relative_to_unix_epoch);
131         inode->i_ctime = ns_to_timespec64(
132                                  info->change_time.ns_relative_to_unix_epoch);
133         inode->i_mtime = ns_to_timespec64(
134                            info->modification_time.ns_relative_to_unix_epoch);
135         return 0;
136 }
137
138 int vboxsf_create_at_dentry(struct dentry *dentry,
139                             struct shfl_createparms *params)
140 {
141         struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
142         struct shfl_string *path;
143         int err;
144
145         path = vboxsf_path_from_dentry(sbi, dentry);
146         if (IS_ERR(path))
147                 return PTR_ERR(path);
148
149         err = vboxsf_create(sbi->root, path, params);
150         __putname(path);
151
152         return err;
153 }
154
155 int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
156                 struct shfl_fsobjinfo *info)
157 {
158         struct shfl_createparms params = {};
159         int err;
160
161         params.handle = SHFL_HANDLE_NIL;
162         params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
163
164         err = vboxsf_create(sbi->root, path, &params);
165         if (err)
166                 return err;
167
168         if (params.result != SHFL_FILE_EXISTS)
169                 return -ENOENT;
170
171         if (info)
172                 *info = params.info;
173
174         return 0;
175 }
176
177 int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
178 {
179         struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
180         struct shfl_string *path;
181         int err;
182
183         path = vboxsf_path_from_dentry(sbi, dentry);
184         if (IS_ERR(path))
185                 return PTR_ERR(path);
186
187         err = vboxsf_stat(sbi, path, info);
188         __putname(path);
189         return err;
190 }
191
192 int vboxsf_inode_revalidate(struct dentry *dentry)
193 {
194         struct vboxsf_sbi *sbi;
195         struct vboxsf_inode *sf_i;
196         struct shfl_fsobjinfo info;
197         struct timespec64 prev_mtime;
198         struct inode *inode;
199         int err;
200
201         if (!dentry || !d_really_is_positive(dentry))
202                 return -EINVAL;
203
204         inode = d_inode(dentry);
205         prev_mtime = inode->i_mtime;
206         sf_i = VBOXSF_I(inode);
207         sbi = VBOXSF_SBI(dentry->d_sb);
208         if (!sf_i->force_restat) {
209                 if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
210                         return 0;
211         }
212
213         err = vboxsf_stat_dentry(dentry, &info);
214         if (err)
215                 return err;
216
217         dentry->d_time = jiffies;
218         sf_i->force_restat = 0;
219         err = vboxsf_init_inode(sbi, inode, &info, true);
220         if (err)
221                 return err;
222
223         /*
224          * If the file was changed on the host side we need to invalidate the
225          * page-cache for it.  Note this also gets triggered by our own writes,
226          * this is unavoidable.
227          */
228         if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0)
229                 invalidate_inode_pages2(inode->i_mapping);
230
231         return 0;
232 }
233
234 int vboxsf_getattr(struct user_namespace *mnt_userns, const struct path *path,
235                    struct kstat *kstat, u32 request_mask, unsigned int flags)
236 {
237         int err;
238         struct dentry *dentry = path->dentry;
239         struct inode *inode = d_inode(dentry);
240         struct vboxsf_inode *sf_i = VBOXSF_I(inode);
241
242         switch (flags & AT_STATX_SYNC_TYPE) {
243         case AT_STATX_DONT_SYNC:
244                 err = 0;
245                 break;
246         case AT_STATX_FORCE_SYNC:
247                 sf_i->force_restat = 1;
248                 fallthrough;
249         default:
250                 err = vboxsf_inode_revalidate(dentry);
251         }
252         if (err)
253                 return err;
254
255         generic_fillattr(&init_user_ns, d_inode(dentry), kstat);
256         return 0;
257 }
258
259 int vboxsf_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
260                    struct iattr *iattr)
261 {
262         struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
263         struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
264         struct shfl_createparms params = {};
265         struct shfl_fsobjinfo info = {};
266         u32 buf_len;
267         int err;
268
269         params.handle = SHFL_HANDLE_NIL;
270         params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
271                               SHFL_CF_ACT_FAIL_IF_NEW |
272                               SHFL_CF_ACCESS_ATTR_WRITE;
273
274         /* this is at least required for Posix hosts */
275         if (iattr->ia_valid & ATTR_SIZE)
276                 params.create_flags |= SHFL_CF_ACCESS_WRITE;
277
278         err = vboxsf_create_at_dentry(dentry, &params);
279         if (err || params.result != SHFL_FILE_EXISTS)
280                 return err ? err : -ENOENT;
281
282 #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
283
284         /*
285          * Setting the file size and setting the other attributes has to
286          * be handled separately.
287          */
288         if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
289                 if (iattr->ia_valid & ATTR_MODE) {
290                         info.attr.mode = mode_set(IRUSR);
291                         info.attr.mode |= mode_set(IWUSR);
292                         info.attr.mode |= mode_set(IXUSR);
293                         info.attr.mode |= mode_set(IRGRP);
294                         info.attr.mode |= mode_set(IWGRP);
295                         info.attr.mode |= mode_set(IXGRP);
296                         info.attr.mode |= mode_set(IROTH);
297                         info.attr.mode |= mode_set(IWOTH);
298                         info.attr.mode |= mode_set(IXOTH);
299
300                         if (iattr->ia_mode & S_IFDIR)
301                                 info.attr.mode |= SHFL_TYPE_DIRECTORY;
302                         else
303                                 info.attr.mode |= SHFL_TYPE_FILE;
304                 }
305
306                 if (iattr->ia_valid & ATTR_ATIME)
307                         info.access_time.ns_relative_to_unix_epoch =
308                                             timespec64_to_ns(&iattr->ia_atime);
309
310                 if (iattr->ia_valid & ATTR_MTIME)
311                         info.modification_time.ns_relative_to_unix_epoch =
312                                             timespec64_to_ns(&iattr->ia_mtime);
313
314                 /*
315                  * Ignore ctime (inode change time) as it can't be set
316                  * from userland anyway.
317                  */
318
319                 buf_len = sizeof(info);
320                 err = vboxsf_fsinfo(sbi->root, params.handle,
321                                     SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
322                                     &info);
323                 if (err) {
324                         vboxsf_close(sbi->root, params.handle);
325                         return err;
326                 }
327
328                 /* the host may have given us different attr then requested */
329                 sf_i->force_restat = 1;
330         }
331
332 #undef mode_set
333
334         if (iattr->ia_valid & ATTR_SIZE) {
335                 memset(&info, 0, sizeof(info));
336                 info.size = iattr->ia_size;
337                 buf_len = sizeof(info);
338                 err = vboxsf_fsinfo(sbi->root, params.handle,
339                                     SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
340                                     &info);
341                 if (err) {
342                         vboxsf_close(sbi->root, params.handle);
343                         return err;
344                 }
345
346                 /* the host may have given us different attr then requested */
347                 sf_i->force_restat = 1;
348         }
349
350         vboxsf_close(sbi->root, params.handle);
351
352         /* Update the inode with what the host has actually given us. */
353         if (sf_i->force_restat)
354                 vboxsf_inode_revalidate(dentry);
355
356         return 0;
357 }
358
359 /*
360  * [dentry] contains string encoded in coding system that corresponds
361  * to [sbi]->nls, we must convert it to UTF8 here.
362  * Returns a shfl_string allocated through __getname (must be freed using
363  * __putname), or an ERR_PTR on error.
364  */
365 struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
366                                             struct dentry *dentry)
367 {
368         struct shfl_string *shfl_path;
369         int path_len, out_len, nb;
370         char *buf, *path;
371         wchar_t uni;
372         u8 *out;
373
374         buf = __getname();
375         if (!buf)
376                 return ERR_PTR(-ENOMEM);
377
378         path = dentry_path_raw(dentry, buf, PATH_MAX);
379         if (IS_ERR(path)) {
380                 __putname(buf);
381                 return ERR_CAST(path);
382         }
383         path_len = strlen(path);
384
385         if (sbi->nls) {
386                 shfl_path = __getname();
387                 if (!shfl_path) {
388                         __putname(buf);
389                         return ERR_PTR(-ENOMEM);
390                 }
391
392                 out = shfl_path->string.utf8;
393                 out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
394
395                 while (path_len) {
396                         nb = sbi->nls->char2uni(path, path_len, &uni);
397                         if (nb < 0) {
398                                 __putname(shfl_path);
399                                 __putname(buf);
400                                 return ERR_PTR(-EINVAL);
401                         }
402                         path += nb;
403                         path_len -= nb;
404
405                         nb = utf32_to_utf8(uni, out, out_len);
406                         if (nb < 0) {
407                                 __putname(shfl_path);
408                                 __putname(buf);
409                                 return ERR_PTR(-ENAMETOOLONG);
410                         }
411                         out += nb;
412                         out_len -= nb;
413                 }
414                 *out = 0;
415                 shfl_path->length = out - shfl_path->string.utf8;
416                 shfl_path->size = shfl_path->length + 1;
417                 __putname(buf);
418         } else {
419                 if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
420                         __putname(buf);
421                         return ERR_PTR(-ENAMETOOLONG);
422                 }
423                 /*
424                  * dentry_path stores the name at the end of buf, but the
425                  * shfl_string string we return must be properly aligned.
426                  */
427                 shfl_path = (struct shfl_string *)buf;
428                 memmove(shfl_path->string.utf8, path, path_len);
429                 shfl_path->string.utf8[path_len] = 0;
430                 shfl_path->length = path_len;
431                 shfl_path->size = path_len + 1;
432         }
433
434         return shfl_path;
435 }
436
437 int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
438                   const unsigned char *utf8_name, size_t utf8_len)
439 {
440         const char *in;
441         char *out;
442         size_t out_len;
443         size_t out_bound_len;
444         size_t in_bound_len;
445
446         in = utf8_name;
447         in_bound_len = utf8_len;
448
449         out = name;
450         out_len = 0;
451         /* Reserve space for terminating 0 */
452         out_bound_len = name_bound_len - 1;
453
454         while (in_bound_len) {
455                 int nb;
456                 unicode_t uni;
457
458                 nb = utf8_to_utf32(in, in_bound_len, &uni);
459                 if (nb < 0)
460                         return -EINVAL;
461
462                 in += nb;
463                 in_bound_len -= nb;
464
465                 nb = sbi->nls->uni2char(uni, out, out_bound_len);
466                 if (nb < 0)
467                         return nb;
468
469                 out += nb;
470                 out_bound_len -= nb;
471                 out_len += nb;
472         }
473
474         *out = 0;
475
476         return 0;
477 }
478
479 static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
480 {
481         struct vboxsf_dir_buf *b;
482
483         b = kmalloc(sizeof(*b), GFP_KERNEL);
484         if (!b)
485                 return NULL;
486
487         b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
488         if (!b->buf) {
489                 kfree(b);
490                 return NULL;
491         }
492
493         b->entries = 0;
494         b->used = 0;
495         b->free = DIR_BUFFER_SIZE;
496         list_add(&b->head, list);
497
498         return b;
499 }
500
501 static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
502 {
503         list_del(&b->head);
504         kfree(b->buf);
505         kfree(b);
506 }
507
508 struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
509 {
510         struct vboxsf_dir_info *p;
511
512         p = kmalloc(sizeof(*p), GFP_KERNEL);
513         if (!p)
514                 return NULL;
515
516         INIT_LIST_HEAD(&p->info_list);
517         return p;
518 }
519
520 void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
521 {
522         struct list_head *list, *pos, *tmp;
523
524         list = &p->info_list;
525         list_for_each_safe(pos, tmp, list) {
526                 struct vboxsf_dir_buf *b;
527
528                 b = list_entry(pos, struct vboxsf_dir_buf, head);
529                 vboxsf_dir_buf_free(b);
530         }
531         kfree(p);
532 }
533
534 int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
535                         u64 handle)
536 {
537         struct vboxsf_dir_buf *b;
538         u32 entries, size;
539         int err = 0;
540         void *buf;
541
542         /* vboxsf_dirinfo returns 1 on end of dir */
543         while (err == 0) {
544                 b = vboxsf_dir_buf_alloc(&sf_d->info_list);
545                 if (!b) {
546                         err = -ENOMEM;
547                         break;
548                 }
549
550                 buf = b->buf;
551                 size = b->free;
552
553                 err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
554                                      &size, buf, &entries);
555                 if (err < 0)
556                         break;
557
558                 b->entries += entries;
559                 b->free -= size;
560                 b->used += size;
561         }
562
563         if (b && b->used == 0)
564                 vboxsf_dir_buf_free(b);
565
566         /* -EILSEQ means the host could not translate a filename, ignore */
567         if (err > 0 || err == -EILSEQ)
568                 err = 0;
569
570         return err;
571 }