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