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