utils.c (12987B)
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 16struct 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] */ 49int 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 138int 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 155int 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, ¶ms); 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 177int 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 192int 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 234int 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 259int 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, ¶ms); 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 */ 365struct 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 437int 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 479static 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 501static 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 508struct 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 520void 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 534int 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}