Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * VirtualBox Guest Shared Folders support: Utility functions.
0004  * Mainly conversion from/to VirtualBox/Linux data structures.
0005  *
0006  * Copyright (C) 2006-2018 Oracle Corporation
0007  */
0008 
0009 #include <linux/namei.h>
0010 #include <linux/nls.h>
0011 #include <linux/sizes.h>
0012 #include <linux/pagemap.h>
0013 #include <linux/vfs.h>
0014 #include "vfsmod.h"
0015 
0016 struct inode *vboxsf_new_inode(struct super_block *sb)
0017 {
0018     struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
0019     struct inode *inode;
0020     unsigned long flags;
0021     int cursor, ret;
0022     u32 gen;
0023 
0024     inode = new_inode(sb);
0025     if (!inode)
0026         return ERR_PTR(-ENOMEM);
0027 
0028     idr_preload(GFP_KERNEL);
0029     spin_lock_irqsave(&sbi->ino_idr_lock, flags);
0030     cursor = idr_get_cursor(&sbi->ino_idr);
0031     ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC);
0032     if (ret >= 0 && ret < cursor)
0033         sbi->next_generation++;
0034     gen = sbi->next_generation;
0035     spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
0036     idr_preload_end();
0037 
0038     if (ret < 0) {
0039         iput(inode);
0040         return ERR_PTR(ret);
0041     }
0042 
0043     inode->i_ino = ret;
0044     inode->i_generation = gen;
0045     return inode;
0046 }
0047 
0048 /* set [inode] attributes based on [info], uid/gid based on [sbi] */
0049 int vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode,
0050                const struct shfl_fsobjinfo *info, bool reinit)
0051 {
0052     const struct shfl_fsobjattr *attr;
0053     s64 allocated;
0054     umode_t mode;
0055 
0056     attr = &info->attr;
0057 
0058 #define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0)
0059 
0060     mode = mode_set(IRUSR);
0061     mode |= mode_set(IWUSR);
0062     mode |= mode_set(IXUSR);
0063 
0064     mode |= mode_set(IRGRP);
0065     mode |= mode_set(IWGRP);
0066     mode |= mode_set(IXGRP);
0067 
0068     mode |= mode_set(IROTH);
0069     mode |= mode_set(IWOTH);
0070     mode |= mode_set(IXOTH);
0071 
0072 #undef mode_set
0073 
0074     /* We use the host-side values for these */
0075     inode->i_flags |= S_NOATIME | S_NOCMTIME;
0076     inode->i_mapping->a_ops = &vboxsf_reg_aops;
0077 
0078     if (SHFL_IS_DIRECTORY(attr->mode)) {
0079         if (sbi->o.dmode_set)
0080             mode = sbi->o.dmode;
0081         mode &= ~sbi->o.dmask;
0082         mode |= S_IFDIR;
0083         if (!reinit) {
0084             inode->i_op = &vboxsf_dir_iops;
0085             inode->i_fop = &vboxsf_dir_fops;
0086             /*
0087              * XXX: this probably should be set to the number of entries
0088              * in the directory plus two (. ..)
0089              */
0090             set_nlink(inode, 1);
0091         } else if (!S_ISDIR(inode->i_mode))
0092             return -ESTALE;
0093         inode->i_mode = mode;
0094     } else if (SHFL_IS_SYMLINK(attr->mode)) {
0095         if (sbi->o.fmode_set)
0096             mode = sbi->o.fmode;
0097         mode &= ~sbi->o.fmask;
0098         mode |= S_IFLNK;
0099         if (!reinit) {
0100             inode->i_op = &vboxsf_lnk_iops;
0101             set_nlink(inode, 1);
0102         } else if (!S_ISLNK(inode->i_mode))
0103             return -ESTALE;
0104         inode->i_mode = mode;
0105     } else {
0106         if (sbi->o.fmode_set)
0107             mode = sbi->o.fmode;
0108         mode &= ~sbi->o.fmask;
0109         mode |= S_IFREG;
0110         if (!reinit) {
0111             inode->i_op = &vboxsf_reg_iops;
0112             inode->i_fop = &vboxsf_reg_fops;
0113             set_nlink(inode, 1);
0114         } else if (!S_ISREG(inode->i_mode))
0115             return -ESTALE;
0116         inode->i_mode = mode;
0117     }
0118 
0119     inode->i_uid = sbi->o.uid;
0120     inode->i_gid = sbi->o.gid;
0121 
0122     inode->i_size = info->size;
0123     inode->i_blkbits = 12;
0124     /* i_blocks always in units of 512 bytes! */
0125     allocated = info->allocated + 511;
0126     do_div(allocated, 512);
0127     inode->i_blocks = allocated;
0128 
0129     inode->i_atime = ns_to_timespec64(
0130                  info->access_time.ns_relative_to_unix_epoch);
0131     inode->i_ctime = ns_to_timespec64(
0132                  info->change_time.ns_relative_to_unix_epoch);
0133     inode->i_mtime = ns_to_timespec64(
0134                info->modification_time.ns_relative_to_unix_epoch);
0135     return 0;
0136 }
0137 
0138 int vboxsf_create_at_dentry(struct dentry *dentry,
0139                 struct shfl_createparms *params)
0140 {
0141     struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
0142     struct shfl_string *path;
0143     int err;
0144 
0145     path = vboxsf_path_from_dentry(sbi, dentry);
0146     if (IS_ERR(path))
0147         return PTR_ERR(path);
0148 
0149     err = vboxsf_create(sbi->root, path, params);
0150     __putname(path);
0151 
0152     return err;
0153 }
0154 
0155 int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path,
0156         struct shfl_fsobjinfo *info)
0157 {
0158     struct shfl_createparms params = {};
0159     int err;
0160 
0161     params.handle = SHFL_HANDLE_NIL;
0162     params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW;
0163 
0164     err = vboxsf_create(sbi->root, path, &params);
0165     if (err)
0166         return err;
0167 
0168     if (params.result != SHFL_FILE_EXISTS)
0169         return -ENOENT;
0170 
0171     if (info)
0172         *info = params.info;
0173 
0174     return 0;
0175 }
0176 
0177 int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info)
0178 {
0179     struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
0180     struct shfl_string *path;
0181     int err;
0182 
0183     path = vboxsf_path_from_dentry(sbi, dentry);
0184     if (IS_ERR(path))
0185         return PTR_ERR(path);
0186 
0187     err = vboxsf_stat(sbi, path, info);
0188     __putname(path);
0189     return err;
0190 }
0191 
0192 int vboxsf_inode_revalidate(struct dentry *dentry)
0193 {
0194     struct vboxsf_sbi *sbi;
0195     struct vboxsf_inode *sf_i;
0196     struct shfl_fsobjinfo info;
0197     struct timespec64 prev_mtime;
0198     struct inode *inode;
0199     int err;
0200 
0201     if (!dentry || !d_really_is_positive(dentry))
0202         return -EINVAL;
0203 
0204     inode = d_inode(dentry);
0205     prev_mtime = inode->i_mtime;
0206     sf_i = VBOXSF_I(inode);
0207     sbi = VBOXSF_SBI(dentry->d_sb);
0208     if (!sf_i->force_restat) {
0209         if (time_before(jiffies, dentry->d_time + sbi->o.ttl))
0210             return 0;
0211     }
0212 
0213     err = vboxsf_stat_dentry(dentry, &info);
0214     if (err)
0215         return err;
0216 
0217     dentry->d_time = jiffies;
0218     sf_i->force_restat = 0;
0219     err = vboxsf_init_inode(sbi, inode, &info, true);
0220     if (err)
0221         return err;
0222 
0223     /*
0224      * If the file was changed on the host side we need to invalidate the
0225      * page-cache for it.  Note this also gets triggered by our own writes,
0226      * this is unavoidable.
0227      */
0228     if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0)
0229         invalidate_inode_pages2(inode->i_mapping);
0230 
0231     return 0;
0232 }
0233 
0234 int vboxsf_getattr(struct user_namespace *mnt_userns, const struct path *path,
0235            struct kstat *kstat, u32 request_mask, unsigned int flags)
0236 {
0237     int err;
0238     struct dentry *dentry = path->dentry;
0239     struct inode *inode = d_inode(dentry);
0240     struct vboxsf_inode *sf_i = VBOXSF_I(inode);
0241 
0242     switch (flags & AT_STATX_SYNC_TYPE) {
0243     case AT_STATX_DONT_SYNC:
0244         err = 0;
0245         break;
0246     case AT_STATX_FORCE_SYNC:
0247         sf_i->force_restat = 1;
0248         fallthrough;
0249     default:
0250         err = vboxsf_inode_revalidate(dentry);
0251     }
0252     if (err)
0253         return err;
0254 
0255     generic_fillattr(&init_user_ns, d_inode(dentry), kstat);
0256     return 0;
0257 }
0258 
0259 int vboxsf_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
0260            struct iattr *iattr)
0261 {
0262     struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry));
0263     struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb);
0264     struct shfl_createparms params = {};
0265     struct shfl_fsobjinfo info = {};
0266     u32 buf_len;
0267     int err;
0268 
0269     params.handle = SHFL_HANDLE_NIL;
0270     params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS |
0271                   SHFL_CF_ACT_FAIL_IF_NEW |
0272                   SHFL_CF_ACCESS_ATTR_WRITE;
0273 
0274     /* this is at least required for Posix hosts */
0275     if (iattr->ia_valid & ATTR_SIZE)
0276         params.create_flags |= SHFL_CF_ACCESS_WRITE;
0277 
0278     err = vboxsf_create_at_dentry(dentry, &params);
0279     if (err || params.result != SHFL_FILE_EXISTS)
0280         return err ? err : -ENOENT;
0281 
0282 #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0)
0283 
0284     /*
0285      * Setting the file size and setting the other attributes has to
0286      * be handled separately.
0287      */
0288     if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) {
0289         if (iattr->ia_valid & ATTR_MODE) {
0290             info.attr.mode = mode_set(IRUSR);
0291             info.attr.mode |= mode_set(IWUSR);
0292             info.attr.mode |= mode_set(IXUSR);
0293             info.attr.mode |= mode_set(IRGRP);
0294             info.attr.mode |= mode_set(IWGRP);
0295             info.attr.mode |= mode_set(IXGRP);
0296             info.attr.mode |= mode_set(IROTH);
0297             info.attr.mode |= mode_set(IWOTH);
0298             info.attr.mode |= mode_set(IXOTH);
0299 
0300             if (iattr->ia_mode & S_IFDIR)
0301                 info.attr.mode |= SHFL_TYPE_DIRECTORY;
0302             else
0303                 info.attr.mode |= SHFL_TYPE_FILE;
0304         }
0305 
0306         if (iattr->ia_valid & ATTR_ATIME)
0307             info.access_time.ns_relative_to_unix_epoch =
0308                         timespec64_to_ns(&iattr->ia_atime);
0309 
0310         if (iattr->ia_valid & ATTR_MTIME)
0311             info.modification_time.ns_relative_to_unix_epoch =
0312                         timespec64_to_ns(&iattr->ia_mtime);
0313 
0314         /*
0315          * Ignore ctime (inode change time) as it can't be set
0316          * from userland anyway.
0317          */
0318 
0319         buf_len = sizeof(info);
0320         err = vboxsf_fsinfo(sbi->root, params.handle,
0321                     SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len,
0322                     &info);
0323         if (err) {
0324             vboxsf_close(sbi->root, params.handle);
0325             return err;
0326         }
0327 
0328         /* the host may have given us different attr then requested */
0329         sf_i->force_restat = 1;
0330     }
0331 
0332 #undef mode_set
0333 
0334     if (iattr->ia_valid & ATTR_SIZE) {
0335         memset(&info, 0, sizeof(info));
0336         info.size = iattr->ia_size;
0337         buf_len = sizeof(info);
0338         err = vboxsf_fsinfo(sbi->root, params.handle,
0339                     SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len,
0340                     &info);
0341         if (err) {
0342             vboxsf_close(sbi->root, params.handle);
0343             return err;
0344         }
0345 
0346         /* the host may have given us different attr then requested */
0347         sf_i->force_restat = 1;
0348     }
0349 
0350     vboxsf_close(sbi->root, params.handle);
0351 
0352     /* Update the inode with what the host has actually given us. */
0353     if (sf_i->force_restat)
0354         vboxsf_inode_revalidate(dentry);
0355 
0356     return 0;
0357 }
0358 
0359 /*
0360  * [dentry] contains string encoded in coding system that corresponds
0361  * to [sbi]->nls, we must convert it to UTF8 here.
0362  * Returns a shfl_string allocated through __getname (must be freed using
0363  * __putname), or an ERR_PTR on error.
0364  */
0365 struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi,
0366                         struct dentry *dentry)
0367 {
0368     struct shfl_string *shfl_path;
0369     int path_len, out_len, nb;
0370     char *buf, *path;
0371     wchar_t uni;
0372     u8 *out;
0373 
0374     buf = __getname();
0375     if (!buf)
0376         return ERR_PTR(-ENOMEM);
0377 
0378     path = dentry_path_raw(dentry, buf, PATH_MAX);
0379     if (IS_ERR(path)) {
0380         __putname(buf);
0381         return ERR_CAST(path);
0382     }
0383     path_len = strlen(path);
0384 
0385     if (sbi->nls) {
0386         shfl_path = __getname();
0387         if (!shfl_path) {
0388             __putname(buf);
0389             return ERR_PTR(-ENOMEM);
0390         }
0391 
0392         out = shfl_path->string.utf8;
0393         out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1;
0394 
0395         while (path_len) {
0396             nb = sbi->nls->char2uni(path, path_len, &uni);
0397             if (nb < 0) {
0398                 __putname(shfl_path);
0399                 __putname(buf);
0400                 return ERR_PTR(-EINVAL);
0401             }
0402             path += nb;
0403             path_len -= nb;
0404 
0405             nb = utf32_to_utf8(uni, out, out_len);
0406             if (nb < 0) {
0407                 __putname(shfl_path);
0408                 __putname(buf);
0409                 return ERR_PTR(-ENAMETOOLONG);
0410             }
0411             out += nb;
0412             out_len -= nb;
0413         }
0414         *out = 0;
0415         shfl_path->length = out - shfl_path->string.utf8;
0416         shfl_path->size = shfl_path->length + 1;
0417         __putname(buf);
0418     } else {
0419         if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) {
0420             __putname(buf);
0421             return ERR_PTR(-ENAMETOOLONG);
0422         }
0423         /*
0424          * dentry_path stores the name at the end of buf, but the
0425          * shfl_string string we return must be properly aligned.
0426          */
0427         shfl_path = (struct shfl_string *)buf;
0428         memmove(shfl_path->string.utf8, path, path_len);
0429         shfl_path->string.utf8[path_len] = 0;
0430         shfl_path->length = path_len;
0431         shfl_path->size = path_len + 1;
0432     }
0433 
0434     return shfl_path;
0435 }
0436 
0437 int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len,
0438           const unsigned char *utf8_name, size_t utf8_len)
0439 {
0440     const char *in;
0441     char *out;
0442     size_t out_len;
0443     size_t out_bound_len;
0444     size_t in_bound_len;
0445 
0446     in = utf8_name;
0447     in_bound_len = utf8_len;
0448 
0449     out = name;
0450     out_len = 0;
0451     /* Reserve space for terminating 0 */
0452     out_bound_len = name_bound_len - 1;
0453 
0454     while (in_bound_len) {
0455         int nb;
0456         unicode_t uni;
0457 
0458         nb = utf8_to_utf32(in, in_bound_len, &uni);
0459         if (nb < 0)
0460             return -EINVAL;
0461 
0462         in += nb;
0463         in_bound_len -= nb;
0464 
0465         nb = sbi->nls->uni2char(uni, out, out_bound_len);
0466         if (nb < 0)
0467             return nb;
0468 
0469         out += nb;
0470         out_bound_len -= nb;
0471         out_len += nb;
0472     }
0473 
0474     *out = 0;
0475 
0476     return 0;
0477 }
0478 
0479 static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list)
0480 {
0481     struct vboxsf_dir_buf *b;
0482 
0483     b = kmalloc(sizeof(*b), GFP_KERNEL);
0484     if (!b)
0485         return NULL;
0486 
0487     b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL);
0488     if (!b->buf) {
0489         kfree(b);
0490         return NULL;
0491     }
0492 
0493     b->entries = 0;
0494     b->used = 0;
0495     b->free = DIR_BUFFER_SIZE;
0496     list_add(&b->head, list);
0497 
0498     return b;
0499 }
0500 
0501 static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b)
0502 {
0503     list_del(&b->head);
0504     kfree(b->buf);
0505     kfree(b);
0506 }
0507 
0508 struct vboxsf_dir_info *vboxsf_dir_info_alloc(void)
0509 {
0510     struct vboxsf_dir_info *p;
0511 
0512     p = kmalloc(sizeof(*p), GFP_KERNEL);
0513     if (!p)
0514         return NULL;
0515 
0516     INIT_LIST_HEAD(&p->info_list);
0517     return p;
0518 }
0519 
0520 void vboxsf_dir_info_free(struct vboxsf_dir_info *p)
0521 {
0522     struct list_head *list, *pos, *tmp;
0523 
0524     list = &p->info_list;
0525     list_for_each_safe(pos, tmp, list) {
0526         struct vboxsf_dir_buf *b;
0527 
0528         b = list_entry(pos, struct vboxsf_dir_buf, head);
0529         vboxsf_dir_buf_free(b);
0530     }
0531     kfree(p);
0532 }
0533 
0534 int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d,
0535             u64 handle)
0536 {
0537     struct vboxsf_dir_buf *b;
0538     u32 entries, size;
0539     int err = 0;
0540     void *buf;
0541 
0542     /* vboxsf_dirinfo returns 1 on end of dir */
0543     while (err == 0) {
0544         b = vboxsf_dir_buf_alloc(&sf_d->info_list);
0545         if (!b) {
0546             err = -ENOMEM;
0547             break;
0548         }
0549 
0550         buf = b->buf;
0551         size = b->free;
0552 
0553         err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0,
0554                      &size, buf, &entries);
0555         if (err < 0)
0556             break;
0557 
0558         b->entries += entries;
0559         b->free -= size;
0560         b->used += size;
0561     }
0562 
0563     if (b && b->used == 0)
0564         vboxsf_dir_buf_free(b);
0565 
0566     /* -EILSEQ means the host could not translate a filename, ignore */
0567     if (err > 0 || err == -EILSEQ)
0568         err = 0;
0569 
0570     return err;
0571 }