xref: /linux/fs/vboxsf/utils.c (revision 9b61b2069681b60d0d0bedbd0fe3c70123dddb19)
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 
vboxsf_new_inode(struct super_block * sb)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] */
vboxsf_init_inode(struct vboxsf_sbi * sbi,struct inode * inode,const struct shfl_fsobjinfo * info,bool reinit)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_set_atime_to_ts(inode,
130 			      ns_to_timespec64(info->access_time.ns_relative_to_unix_epoch));
131 	inode_set_ctime_to_ts(inode,
132 			      ns_to_timespec64(info->change_time.ns_relative_to_unix_epoch));
133 	inode_set_mtime_to_ts(inode,
134 			      ns_to_timespec64(info->modification_time.ns_relative_to_unix_epoch));
135 	return 0;
136 }
137 
vboxsf_create_at_dentry(struct dentry * dentry,struct shfl_createparms * params)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 
vboxsf_stat(struct vboxsf_sbi * sbi,struct shfl_string * path,struct shfl_fsobjinfo * info)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 
vboxsf_stat_dentry(struct dentry * dentry,struct shfl_fsobjinfo * info)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 
vboxsf_inode_revalidate(struct dentry * dentry)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 mtime, 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_get_mtime(inode);
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 	mtime = inode_get_mtime(inode);
229 	if (timespec64_compare(&mtime, &prev_mtime) > 0)
230 		invalidate_inode_pages2(inode->i_mapping);
231 
232 	return 0;
233 }
234 
vboxsf_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * kstat,u32 request_mask,unsigned int flags)235 int vboxsf_getattr(struct mnt_idmap *idmap, const struct path *path,
236 		   struct kstat *kstat, u32 request_mask, unsigned int flags)
237 {
238 	int err;
239 	struct dentry *dentry = path->dentry;
240 	struct inode *inode = d_inode(dentry);
241 	struct vboxsf_inode *sf_i = VBOXSF_I(inode);
242 
243 	switch (flags & AT_STATX_SYNC_TYPE) {
244 	case AT_STATX_DONT_SYNC:
245 		err = 0;
246 		break;
247 	case AT_STATX_FORCE_SYNC:
248 		sf_i->force_restat = 1;
249 		fallthrough;
250 	default:
251 		err = vboxsf_inode_revalidate(dentry);
252 	}
253 	if (err)
254 		return err;
255 
256 	generic_fillattr(&nop_mnt_idmap, request_mask, d_inode(dentry), kstat);
257 	return 0;
258 }
259 
vboxsf_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)260 int vboxsf_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
261 		   struct iattr *iattr)
262 {
263 	struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
264 	struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
265 	struct shfl_createparms params = {};
266 	struct shfl_fsobjinfo info = {};
267 	u32 buf_len;
268 	int err;
269 
270 	params.handle = SHFL_HANDLE_NIL;
271 	params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
272 			      SHFL_CF_ACT_FAIL_IF_NEW |
273 			      SHFL_CF_ACCESS_ATTR_WRITE;
274 
275 	/* this is at least required for Posix hosts */
276 	if (iattr->ia_valid & ATTR_SIZE)
277 		params.create_flags |= SHFL_CF_ACCESS_WRITE;
278 
279 	err = vboxsf_create_at_dentry(dentry, &params);
280 	if (err || params.result != SHFL_FILE_EXISTS)
281 		return err ? err : -ENOENT;
282 
283 #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
284 
285 	/*
286 	 * Setting the file size and setting the other attributes has to
287 	 * be handled separately.
288 	 */
289 	if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
290 		if (iattr->ia_valid & ATTR_MODE) {
291 			info.attr.mode = mode_set(IRUSR);
292 			info.attr.mode |= mode_set(IWUSR);
293 			info.attr.mode |= mode_set(IXUSR);
294 			info.attr.mode |= mode_set(IRGRP);
295 			info.attr.mode |= mode_set(IWGRP);
296 			info.attr.mode |= mode_set(IXGRP);
297 			info.attr.mode |= mode_set(IROTH);
298 			info.attr.mode |= mode_set(IWOTH);
299 			info.attr.mode |= mode_set(IXOTH);
300 
301 			if (iattr->ia_mode & S_IFDIR)
302 				info.attr.mode |= SHFL_TYPE_DIRECTORY;
303 			else
304 				info.attr.mode |= SHFL_TYPE_FILE;
305 		}
306 
307 		if (iattr->ia_valid & ATTR_ATIME)
308 			info.access_time.ns_relative_to_unix_epoch =
309 					    timespec64_to_ns(&iattr->ia_atime);
310 
311 		if (iattr->ia_valid & ATTR_MTIME)
312 			info.modification_time.ns_relative_to_unix_epoch =
313 					    timespec64_to_ns(&iattr->ia_mtime);
314 
315 		/*
316 		 * Ignore ctime (inode change time) as it can't be set
317 		 * from userland anyway.
318 		 */
319 
320 		buf_len = sizeof(info);
321 		err = vboxsf_fsinfo(sbi->root, params.handle,
322 				    SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
323 				    &info);
324 		if (err) {
325 			vboxsf_close(sbi->root, params.handle);
326 			return err;
327 		}
328 
329 		/* the host may have given us different attr then requested */
330 		sf_i->force_restat = 1;
331 	}
332 
333 #undef mode_set
334 
335 	if (iattr->ia_valid & ATTR_SIZE) {
336 		memset(&info, 0, sizeof(info));
337 		info.size = iattr->ia_size;
338 		buf_len = sizeof(info);
339 		err = vboxsf_fsinfo(sbi->root, params.handle,
340 				    SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
341 				    &info);
342 		if (err) {
343 			vboxsf_close(sbi->root, params.handle);
344 			return err;
345 		}
346 
347 		/* the host may have given us different attr then requested */
348 		sf_i->force_restat = 1;
349 	}
350 
351 	vboxsf_close(sbi->root, params.handle);
352 
353 	/* Update the inode with what the host has actually given us. */
354 	if (sf_i->force_restat)
355 		vboxsf_inode_revalidate(dentry);
356 
357 	return 0;
358 }
359 
360 /*
361  * [dentry] contains string encoded in coding system that corresponds
362  * to [sbi]->nls, we must convert it to UTF8 here.
363  * Returns a shfl_string allocated through __getname (must be freed using
364  * __putname), or an ERR_PTR on error.
365  */
vboxsf_path_from_dentry(struct vboxsf_sbi * sbi,struct dentry * dentry)366 struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
367 					    struct dentry *dentry)
368 {
369 	struct shfl_string *shfl_path;
370 	int path_len, out_len, nb;
371 	char *buf, *path;
372 	wchar_t uni;
373 	u8 *out;
374 
375 	buf = __getname();
376 	if (!buf)
377 		return ERR_PTR(-ENOMEM);
378 
379 	path = dentry_path_raw(dentry, buf, PATH_MAX);
380 	if (IS_ERR(path)) {
381 		__putname(buf);
382 		return ERR_CAST(path);
383 	}
384 	path_len = strlen(path);
385 
386 	if (sbi->nls) {
387 		shfl_path = __getname();
388 		if (!shfl_path) {
389 			__putname(buf);
390 			return ERR_PTR(-ENOMEM);
391 		}
392 
393 		out = shfl_path->string.utf8;
394 		out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
395 
396 		while (path_len) {
397 			nb = sbi->nls->char2uni(path, path_len, &uni);
398 			if (nb < 0) {
399 				__putname(shfl_path);
400 				__putname(buf);
401 				return ERR_PTR(-EINVAL);
402 			}
403 			path += nb;
404 			path_len -= nb;
405 
406 			nb = utf32_to_utf8(uni, out, out_len);
407 			if (nb < 0) {
408 				__putname(shfl_path);
409 				__putname(buf);
410 				return ERR_PTR(-ENAMETOOLONG);
411 			}
412 			out += nb;
413 			out_len -= nb;
414 		}
415 		*out = 0;
416 		shfl_path->length = out - shfl_path->string.utf8;
417 		shfl_path->size = shfl_path->length + 1;
418 		__putname(buf);
419 	} else {
420 		if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
421 			__putname(buf);
422 			return ERR_PTR(-ENAMETOOLONG);
423 		}
424 		/*
425 		 * dentry_path stores the name at the end of buf, but the
426 		 * shfl_string string we return must be properly aligned.
427 		 */
428 		shfl_path = (struct shfl_string *)buf;
429 		memmove(shfl_path->string.utf8, path, path_len);
430 		shfl_path->string.utf8[path_len] = 0;
431 		shfl_path->length = path_len;
432 		shfl_path->size = path_len + 1;
433 	}
434 
435 	return shfl_path;
436 }
437 
vboxsf_nlscpy(struct vboxsf_sbi * sbi,char * name,size_t name_bound_len,const unsigned char * utf8_name,size_t utf8_len)438 int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
439 		  const unsigned char *utf8_name, size_t utf8_len)
440 {
441 	const char *in;
442 	char *out;
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 	/* 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 	}
471 
472 	*out = 0;
473 
474 	return 0;
475 }
476 
vboxsf_dir_buf_alloc(struct list_head * list)477 static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
478 {
479 	struct vboxsf_dir_buf *b;
480 
481 	b = kmalloc(sizeof(*b), GFP_KERNEL);
482 	if (!b)
483 		return NULL;
484 
485 	b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
486 	if (!b->buf) {
487 		kfree(b);
488 		return NULL;
489 	}
490 
491 	b->entries = 0;
492 	b->used = 0;
493 	b->free = DIR_BUFFER_SIZE;
494 	list_add(&b->head, list);
495 
496 	return b;
497 }
498 
vboxsf_dir_buf_free(struct vboxsf_dir_buf * b)499 static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
500 {
501 	list_del(&b->head);
502 	kfree(b->buf);
503 	kfree(b);
504 }
505 
vboxsf_dir_info_alloc(void)506 struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
507 {
508 	struct vboxsf_dir_info *p;
509 
510 	p = kmalloc(sizeof(*p), GFP_KERNEL);
511 	if (!p)
512 		return NULL;
513 
514 	INIT_LIST_HEAD(&p->info_list);
515 	return p;
516 }
517 
vboxsf_dir_info_free(struct vboxsf_dir_info * p)518 void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
519 {
520 	struct list_head *list, *pos, *tmp;
521 
522 	list = &p->info_list;
523 	list_for_each_safe(pos, tmp, list) {
524 		struct vboxsf_dir_buf *b;
525 
526 		b = list_entry(pos, struct vboxsf_dir_buf, head);
527 		vboxsf_dir_buf_free(b);
528 	}
529 	kfree(p);
530 }
531 
vboxsf_dir_read_all(struct vboxsf_sbi * sbi,struct vboxsf_dir_info * sf_d,u64 handle)532 int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
533 			u64 handle)
534 {
535 	struct vboxsf_dir_buf *b;
536 	u32 entries, size;
537 	int err = 0;
538 	void *buf;
539 
540 	/* vboxsf_dirinfo returns 1 on end of dir */
541 	while (err == 0) {
542 		b = vboxsf_dir_buf_alloc(&sf_d->info_list);
543 		if (!b) {
544 			err = -ENOMEM;
545 			break;
546 		}
547 
548 		buf = b->buf;
549 		size = b->free;
550 
551 		err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
552 				     &size, buf, &entries);
553 		if (err < 0)
554 			break;
555 
556 		b->entries += entries;
557 		b->free -= size;
558 		b->used += size;
559 	}
560 
561 	if (b && b->used == 0)
562 		vboxsf_dir_buf_free(b);
563 
564 	/* -EILSEQ means the host could not translate a filename, ignore */
565 	if (err > 0 || err == -EILSEQ)
566 		err = 0;
567 
568 	return err;
569 }
570