1 // SPDX-License-Identifier: MIT 2 /* 3 * VirtualBox Guest Shared Folders support: Directory inode and file operations 4 * 5 * Copyright (C) 2006-2018 Oracle Corporation 6 */ 7 8 #include <linux/namei.h> 9 #include <linux/vbox_utils.h> 10 #include "vfsmod.h" 11 12 static int vboxsf_dir_open(struct inode *inode, struct file *file) 13 { 14 struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 15 struct shfl_createparms params = {}; 16 struct vboxsf_dir_info *sf_d; 17 int err; 18 19 sf_d = vboxsf_dir_info_alloc(); 20 if (!sf_d) 21 return -ENOMEM; 22 23 params.handle = SHFL_HANDLE_NIL; 24 params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | 25 SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; 26 27 err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); 28 if (err) 29 goto err_free_dir_info; 30 31 if (params.result != SHFL_FILE_EXISTS) { 32 err = -ENOENT; 33 goto err_close; 34 } 35 36 err = vboxsf_dir_read_all(sbi, sf_d, params.handle); 37 if (err) 38 goto err_close; 39 40 vboxsf_close(sbi->root, params.handle); 41 file->private_data = sf_d; 42 return 0; 43 44 err_close: 45 vboxsf_close(sbi->root, params.handle); 46 err_free_dir_info: 47 vboxsf_dir_info_free(sf_d); 48 return err; 49 } 50 51 static int vboxsf_dir_release(struct inode *inode, struct file *file) 52 { 53 if (file->private_data) 54 vboxsf_dir_info_free(file->private_data); 55 56 return 0; 57 } 58 59 static unsigned int vboxsf_get_d_type(u32 mode) 60 { 61 unsigned int d_type; 62 63 switch (mode & SHFL_TYPE_MASK) { 64 case SHFL_TYPE_FIFO: 65 d_type = DT_FIFO; 66 break; 67 case SHFL_TYPE_DEV_CHAR: 68 d_type = DT_CHR; 69 break; 70 case SHFL_TYPE_DIRECTORY: 71 d_type = DT_DIR; 72 break; 73 case SHFL_TYPE_DEV_BLOCK: 74 d_type = DT_BLK; 75 break; 76 case SHFL_TYPE_FILE: 77 d_type = DT_REG; 78 break; 79 case SHFL_TYPE_SYMLINK: 80 d_type = DT_LNK; 81 break; 82 case SHFL_TYPE_SOCKET: 83 d_type = DT_SOCK; 84 break; 85 case SHFL_TYPE_WHITEOUT: 86 d_type = DT_WHT; 87 break; 88 default: 89 d_type = DT_UNKNOWN; 90 break; 91 } 92 return d_type; 93 } 94 95 static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) 96 { 97 struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); 98 struct vboxsf_dir_info *sf_d = dir->private_data; 99 struct shfl_dirinfo *info; 100 struct vboxsf_dir_buf *b; 101 unsigned int d_type; 102 loff_t i, cur = 0; 103 ino_t fake_ino; 104 void *end; 105 int err; 106 107 list_for_each_entry(b, &sf_d->info_list, head) { 108 try_next_entry: 109 if (ctx->pos >= cur + b->entries) { 110 cur += b->entries; 111 continue; 112 } 113 114 /* 115 * Note the vboxsf_dir_info objects we are iterating over here 116 * are variable sized, so the info pointer may end up being 117 * unaligned. This is how we get the data from the host. 118 * Since vboxsf is only supported on x86 machines this is not 119 * a problem. 120 */ 121 for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { 122 end = &info->name.string.utf8[info->name.size]; 123 /* Only happens if the host gives us corrupt data */ 124 if (WARN_ON(end > (b->buf + b->used))) 125 return false; 126 info = end; 127 } 128 129 end = &info->name.string.utf8[info->name.size]; 130 if (WARN_ON(end > (b->buf + b->used))) 131 return false; 132 133 /* Info now points to the right entry, emit it. */ 134 d_type = vboxsf_get_d_type(info->info.attr.mode); 135 136 /* 137 * On 32-bit systems pos is 64-bit signed, while ino is 32-bit 138 * unsigned so fake_ino may overflow, check for this. 139 */ 140 if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { 141 vbg_err("vboxsf: fake ino overflow, truncating dir\n"); 142 return false; 143 } 144 fake_ino = ctx->pos + 1; 145 146 if (sbi->nls) { 147 char d_name[NAME_MAX]; 148 149 err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, 150 info->name.string.utf8, 151 info->name.length); 152 if (err) { 153 /* skip erroneous entry and proceed */ 154 ctx->pos += 1; 155 goto try_next_entry; 156 } 157 158 return dir_emit(ctx, d_name, strlen(d_name), 159 fake_ino, d_type); 160 } 161 162 return dir_emit(ctx, info->name.string.utf8, info->name.length, 163 fake_ino, d_type); 164 } 165 166 return false; 167 } 168 169 static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) 170 { 171 bool emitted; 172 173 do { 174 emitted = vboxsf_dir_emit(dir, ctx); 175 if (emitted) 176 ctx->pos += 1; 177 } while (emitted); 178 179 return 0; 180 } 181 182 WRAP_DIR_ITER(vboxsf_dir_iterate) // FIXME! 183 const struct file_operations vboxsf_dir_fops = { 184 .open = vboxsf_dir_open, 185 .iterate_shared = shared_vboxsf_dir_iterate, 186 .release = vboxsf_dir_release, 187 .read = generic_read_dir, 188 .llseek = generic_file_llseek, 189 }; 190 191 /* 192 * This is called during name resolution/lookup to check if the @dentry in 193 * the cache is still valid. the job is handled by vboxsf_inode_revalidate. 194 */ 195 static int vboxsf_dentry_revalidate(struct inode *dir, const struct qstr *name, 196 struct dentry *dentry, unsigned int flags) 197 { 198 if (flags & LOOKUP_RCU) 199 return -ECHILD; 200 201 if (d_really_is_positive(dentry)) 202 return vboxsf_inode_revalidate(dentry) == 0; 203 else 204 return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; 205 } 206 207 const struct dentry_operations vboxsf_dentry_ops = { 208 .d_revalidate = vboxsf_dentry_revalidate 209 }; 210 211 /* iops */ 212 213 static struct dentry *vboxsf_dir_lookup(struct inode *parent, 214 struct dentry *dentry, 215 unsigned int flags) 216 { 217 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 218 struct shfl_fsobjinfo fsinfo; 219 struct inode *inode; 220 int err; 221 222 dentry->d_time = jiffies; 223 224 err = vboxsf_stat_dentry(dentry, &fsinfo); 225 if (err) { 226 inode = (err == -ENOENT) ? NULL : ERR_PTR(err); 227 } else { 228 inode = vboxsf_new_inode(parent->i_sb); 229 if (!IS_ERR(inode)) 230 vboxsf_init_inode(sbi, inode, &fsinfo, false); 231 } 232 233 return d_splice_alias(inode, dentry); 234 } 235 236 static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, 237 struct shfl_fsobjinfo *info) 238 { 239 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 240 struct vboxsf_inode *sf_i; 241 struct inode *inode; 242 243 inode = vboxsf_new_inode(parent->i_sb); 244 if (IS_ERR(inode)) 245 return PTR_ERR(inode); 246 247 sf_i = VBOXSF_I(inode); 248 /* The host may have given us different attr then requested */ 249 sf_i->force_restat = 1; 250 vboxsf_init_inode(sbi, inode, info, false); 251 252 d_instantiate(dentry, inode); 253 254 return 0; 255 } 256 257 static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, 258 umode_t mode, bool is_dir, bool excl, u64 *handle_ret) 259 { 260 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 261 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 262 struct shfl_createparms params = {}; 263 int err; 264 265 params.handle = SHFL_HANDLE_NIL; 266 params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | SHFL_CF_ACCESS_READWRITE; 267 if (is_dir) 268 params.create_flags |= SHFL_CF_DIRECTORY; 269 if (excl) 270 params.create_flags |= SHFL_CF_ACT_FAIL_IF_EXISTS; 271 272 params.info.attr.mode = (mode & 0777) | 273 (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); 274 params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; 275 276 err = vboxsf_create_at_dentry(dentry, ¶ms); 277 if (err) 278 return err; 279 280 if (params.result != SHFL_FILE_CREATED) 281 return -EPERM; 282 283 err = vboxsf_dir_instantiate(parent, dentry, ¶ms.info); 284 if (err) 285 goto out; 286 287 /* parent directory access/change time changed */ 288 sf_parent_i->force_restat = 1; 289 290 out: 291 if (err == 0 && handle_ret) 292 *handle_ret = params.handle; 293 else 294 vboxsf_close(sbi->root, params.handle); 295 296 return err; 297 } 298 299 static int vboxsf_dir_mkfile(struct mnt_idmap *idmap, 300 struct inode *parent, struct dentry *dentry, 301 umode_t mode, bool excl) 302 { 303 return vboxsf_dir_create(parent, dentry, mode, false, excl, NULL); 304 } 305 306 static struct dentry *vboxsf_dir_mkdir(struct mnt_idmap *idmap, 307 struct inode *parent, struct dentry *dentry, 308 umode_t mode) 309 { 310 return ERR_PTR(vboxsf_dir_create(parent, dentry, mode, true, true, NULL)); 311 } 312 313 static int vboxsf_dir_atomic_open(struct inode *parent, struct dentry *dentry, 314 struct file *file, unsigned int flags, umode_t mode) 315 { 316 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 317 struct vboxsf_handle *sf_handle; 318 struct dentry *res = NULL; 319 u64 handle; 320 int err; 321 322 if (d_in_lookup(dentry)) { 323 res = vboxsf_dir_lookup(parent, dentry, 0); 324 if (IS_ERR(res)) 325 return PTR_ERR(res); 326 327 if (res) 328 dentry = res; 329 } 330 331 /* Only creates */ 332 if (!(flags & O_CREAT) || d_really_is_positive(dentry)) 333 return finish_no_open(file, res); 334 335 err = vboxsf_dir_create(parent, dentry, mode, false, flags & O_EXCL, &handle); 336 if (err) 337 goto out; 338 339 sf_handle = vboxsf_create_sf_handle(d_inode(dentry), handle, SHFL_CF_ACCESS_READWRITE); 340 if (IS_ERR(sf_handle)) { 341 vboxsf_close(sbi->root, handle); 342 err = PTR_ERR(sf_handle); 343 goto out; 344 } 345 346 err = finish_open(file, dentry, generic_file_open); 347 if (err) { 348 /* This also closes the handle passed to vboxsf_create_sf_handle() */ 349 vboxsf_release_sf_handle(d_inode(dentry), sf_handle); 350 goto out; 351 } 352 353 file->private_data = sf_handle; 354 file->f_mode |= FMODE_CREATED; 355 out: 356 dput(res); 357 return err; 358 } 359 360 static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) 361 { 362 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 363 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 364 struct inode *inode = d_inode(dentry); 365 struct shfl_string *path; 366 u32 flags; 367 int err; 368 369 if (S_ISDIR(inode->i_mode)) 370 flags = SHFL_REMOVE_DIR; 371 else 372 flags = SHFL_REMOVE_FILE; 373 374 if (S_ISLNK(inode->i_mode)) 375 flags |= SHFL_REMOVE_SYMLINK; 376 377 path = vboxsf_path_from_dentry(sbi, dentry); 378 if (IS_ERR(path)) 379 return PTR_ERR(path); 380 381 err = vboxsf_remove(sbi->root, path, flags); 382 __putname(path); 383 if (err) 384 return err; 385 386 /* parent directory access/change time changed */ 387 sf_parent_i->force_restat = 1; 388 389 return 0; 390 } 391 392 static int vboxsf_dir_rename(struct mnt_idmap *idmap, 393 struct inode *old_parent, 394 struct dentry *old_dentry, 395 struct inode *new_parent, 396 struct dentry *new_dentry, 397 unsigned int flags) 398 { 399 struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); 400 struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); 401 struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); 402 u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; 403 struct shfl_string *old_path, *new_path; 404 int err; 405 406 if (flags) 407 return -EINVAL; 408 409 old_path = vboxsf_path_from_dentry(sbi, old_dentry); 410 if (IS_ERR(old_path)) 411 return PTR_ERR(old_path); 412 413 new_path = vboxsf_path_from_dentry(sbi, new_dentry); 414 if (IS_ERR(new_path)) { 415 err = PTR_ERR(new_path); 416 goto err_put_old_path; 417 } 418 419 if (d_inode(old_dentry)->i_mode & S_IFDIR) 420 shfl_flags = 0; 421 422 err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); 423 if (err == 0) { 424 /* parent directories access/change time changed */ 425 sf_new_parent_i->force_restat = 1; 426 sf_old_parent_i->force_restat = 1; 427 } 428 429 __putname(new_path); 430 err_put_old_path: 431 __putname(old_path); 432 return err; 433 } 434 435 static int vboxsf_dir_symlink(struct mnt_idmap *idmap, 436 struct inode *parent, struct dentry *dentry, 437 const char *symname) 438 { 439 struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 440 struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 441 int symname_size = strlen(symname) + 1; 442 struct shfl_string *path, *ssymname; 443 struct shfl_fsobjinfo info; 444 int err; 445 446 path = vboxsf_path_from_dentry(sbi, dentry); 447 if (IS_ERR(path)) 448 return PTR_ERR(path); 449 450 ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); 451 if (!ssymname) { 452 __putname(path); 453 return -ENOMEM; 454 } 455 ssymname->length = symname_size - 1; 456 ssymname->size = symname_size; 457 memcpy(ssymname->string.utf8, symname, symname_size); 458 459 err = vboxsf_symlink(sbi->root, path, ssymname, &info); 460 kfree(ssymname); 461 __putname(path); 462 if (err) { 463 /* -EROFS means symlinks are note support -> -EPERM */ 464 return (err == -EROFS) ? -EPERM : err; 465 } 466 467 err = vboxsf_dir_instantiate(parent, dentry, &info); 468 if (err) 469 return err; 470 471 /* parent directory access/change time changed */ 472 sf_parent_i->force_restat = 1; 473 return 0; 474 } 475 476 const struct inode_operations vboxsf_dir_iops = { 477 .lookup = vboxsf_dir_lookup, 478 .create = vboxsf_dir_mkfile, 479 .mkdir = vboxsf_dir_mkdir, 480 .atomic_open = vboxsf_dir_atomic_open, 481 .rmdir = vboxsf_dir_unlink, 482 .unlink = vboxsf_dir_unlink, 483 .rename = vboxsf_dir_rename, 484 .symlink = vboxsf_dir_symlink, 485 .getattr = vboxsf_getattr, 486 .setattr = vboxsf_setattr, 487 }; 488