xref: /openbmc/linux/fs/vboxsf/utils.c (revision 0ad53fe3)
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 }
571