1e5e5558eSMiklos Szeredi /* 2e5e5558eSMiklos Szeredi FUSE: Filesystem in Userspace 31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu> 4e5e5558eSMiklos Szeredi 5e5e5558eSMiklos Szeredi This program can be distributed under the terms of the GNU GPL. 6e5e5558eSMiklos Szeredi See the file COPYING. 7e5e5558eSMiklos Szeredi */ 8e5e5558eSMiklos Szeredi 9e5e5558eSMiklos Szeredi #include "fuse_i.h" 10e5e5558eSMiklos Szeredi 11e5e5558eSMiklos Szeredi #include <linux/pagemap.h> 12e5e5558eSMiklos Szeredi #include <linux/file.h> 13bf109c64SMax Reitz #include <linux/fs_context.h> 149ccf47b2SDave Marchevsky #include <linux/moduleparam.h> 15e5e5558eSMiklos Szeredi #include <linux/sched.h> 16e5e5558eSMiklos Szeredi #include <linux/namei.h> 1707e77dcaSMiklos Szeredi #include <linux/slab.h> 18703c7362SSeth Forshee #include <linux/xattr.h> 19261aaba7SMiklos Szeredi #include <linux/iversion.h> 2060bcc88aSSeth Forshee #include <linux/posix_acl.h> 213e2b6fdbSVivek Goyal #include <linux/security.h> 223e2b6fdbSVivek Goyal #include <linux/types.h> 233e2b6fdbSVivek Goyal #include <linux/kernel.h> 24e5e5558eSMiklos Szeredi 259ccf47b2SDave Marchevsky static bool __read_mostly allow_sys_admin_access; 269ccf47b2SDave Marchevsky module_param(allow_sys_admin_access, bool, 0644); 279ccf47b2SDave Marchevsky MODULE_PARM_DESC(allow_sys_admin_access, 289ccf47b2SDave Marchevsky "Allow users with CAP_SYS_ADMIN in initial userns to bypass allow_other access check"); 299ccf47b2SDave Marchevsky 304582a4abSFeng Shuo static void fuse_advise_use_readdirplus(struct inode *dir) 314582a4abSFeng Shuo { 324582a4abSFeng Shuo struct fuse_inode *fi = get_fuse_inode(dir); 334582a4abSFeng Shuo 344582a4abSFeng Shuo set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state); 354582a4abSFeng Shuo } 364582a4abSFeng Shuo 3730c6a23dSKhazhismel Kumykov #if BITS_PER_LONG >= 64 3830c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *entry, u64 time) 3930c6a23dSKhazhismel Kumykov { 4030c6a23dSKhazhismel Kumykov entry->d_fsdata = (void *) time; 4130c6a23dSKhazhismel Kumykov } 4230c6a23dSKhazhismel Kumykov 4330c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 4430c6a23dSKhazhismel Kumykov { 4530c6a23dSKhazhismel Kumykov return (u64)entry->d_fsdata; 4630c6a23dSKhazhismel Kumykov } 4730c6a23dSKhazhismel Kumykov 4830c6a23dSKhazhismel Kumykov #else 49f75fdf22SMiklos Szeredi union fuse_dentry { 50f75fdf22SMiklos Szeredi u64 time; 51f75fdf22SMiklos Szeredi struct rcu_head rcu; 52f75fdf22SMiklos Szeredi }; 53f75fdf22SMiklos Szeredi 5430c6a23dSKhazhismel Kumykov static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time) 5530c6a23dSKhazhismel Kumykov { 5630c6a23dSKhazhismel Kumykov ((union fuse_dentry *) dentry->d_fsdata)->time = time; 5730c6a23dSKhazhismel Kumykov } 5830c6a23dSKhazhismel Kumykov 5930c6a23dSKhazhismel Kumykov static inline u64 fuse_dentry_time(const struct dentry *entry) 6030c6a23dSKhazhismel Kumykov { 6130c6a23dSKhazhismel Kumykov return ((union fuse_dentry *) entry->d_fsdata)->time; 6230c6a23dSKhazhismel Kumykov } 6330c6a23dSKhazhismel Kumykov #endif 6430c6a23dSKhazhismel Kumykov 658fab0106SMiklos Szeredi static void fuse_dentry_settime(struct dentry *dentry, u64 time) 660a0898cfSMiklos Szeredi { 678fab0106SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb); 688fab0106SMiklos Szeredi bool delete = !time && fc->delete_stale; 698fab0106SMiklos Szeredi /* 708fab0106SMiklos Szeredi * Mess with DCACHE_OP_DELETE because dput() will be faster without it. 718fab0106SMiklos Szeredi * Don't care about races, either way it's just an optimization 728fab0106SMiklos Szeredi */ 738fab0106SMiklos Szeredi if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) || 748fab0106SMiklos Szeredi (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) { 758fab0106SMiklos Szeredi spin_lock(&dentry->d_lock); 768fab0106SMiklos Szeredi if (!delete) 778fab0106SMiklos Szeredi dentry->d_flags &= ~DCACHE_OP_DELETE; 788fab0106SMiklos Szeredi else 798fab0106SMiklos Szeredi dentry->d_flags |= DCACHE_OP_DELETE; 808fab0106SMiklos Szeredi spin_unlock(&dentry->d_lock); 810a0898cfSMiklos Szeredi } 820a0898cfSMiklos Szeredi 8330c6a23dSKhazhismel Kumykov __fuse_dentry_settime(dentry, time); 840a0898cfSMiklos Szeredi } 850a0898cfSMiklos Szeredi 866f9f1180SMiklos Szeredi /* 876f9f1180SMiklos Szeredi * FUSE caches dentries and attributes with separate timeout. The 886f9f1180SMiklos Szeredi * time in jiffies until the dentry/attributes are valid is stored in 89f75fdf22SMiklos Szeredi * dentry->d_fsdata and fuse_inode->i_time respectively. 906f9f1180SMiklos Szeredi */ 916f9f1180SMiklos Szeredi 926f9f1180SMiklos Szeredi /* 936f9f1180SMiklos Szeredi * Calculate the time in jiffies until a dentry/attributes are valid 946f9f1180SMiklos Szeredi */ 95bcb6f6d2SMiklos Szeredi static u64 time_to_jiffies(u64 sec, u32 nsec) 96e5e5558eSMiklos Szeredi { 97685d16ddSMiklos Szeredi if (sec || nsec) { 98bcb6f6d2SMiklos Szeredi struct timespec64 ts = { 99bcb6f6d2SMiklos Szeredi sec, 10021067527SDavid Sheets min_t(u32, nsec, NSEC_PER_SEC - 1) 101bcb6f6d2SMiklos Szeredi }; 102bcb6f6d2SMiklos Szeredi 103bcb6f6d2SMiklos Szeredi return get_jiffies_64() + timespec64_to_jiffies(&ts); 104685d16ddSMiklos Szeredi } else 1050a0898cfSMiklos Szeredi return 0; 106e5e5558eSMiklos Szeredi } 107e5e5558eSMiklos Szeredi 1086f9f1180SMiklos Szeredi /* 1096f9f1180SMiklos Szeredi * Set dentry and possibly attribute timeouts from the lookup/mk* 1106f9f1180SMiklos Szeredi * replies 1116f9f1180SMiklos Szeredi */ 112d123d8e1SMiklos Szeredi void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o) 1130aa7c699SMiklos Szeredi { 1140a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 1150a0898cfSMiklos Szeredi time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 1161fb69e78SMiklos Szeredi } 1171fb69e78SMiklos Szeredi 1181fb69e78SMiklos Szeredi static u64 attr_timeout(struct fuse_attr_out *o) 1191fb69e78SMiklos Szeredi { 1201fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1211fb69e78SMiklos Szeredi } 1221fb69e78SMiklos Szeredi 123d123d8e1SMiklos Szeredi u64 entry_attr_timeout(struct fuse_entry_out *o) 1241fb69e78SMiklos Szeredi { 1251fb69e78SMiklos Szeredi return time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 1268cbdf1e6SMiklos Szeredi } 1278cbdf1e6SMiklos Szeredi 128fa5eee57SMiklos Szeredi void fuse_invalidate_attr_mask(struct inode *inode, u32 mask) 1292f1e8196SMiklos Szeredi { 1302f1e8196SMiklos Szeredi set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask); 1312f1e8196SMiklos Szeredi } 1322f1e8196SMiklos Szeredi 1336f9f1180SMiklos Szeredi /* 1346f9f1180SMiklos Szeredi * Mark the attributes as stale, so that at the next call to 1356f9f1180SMiklos Szeredi * ->getattr() they will be fetched from userspace 1366f9f1180SMiklos Szeredi */ 1378cbdf1e6SMiklos Szeredi void fuse_invalidate_attr(struct inode *inode) 1388cbdf1e6SMiklos Szeredi { 1392f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS); 1408cbdf1e6SMiklos Szeredi } 1418cbdf1e6SMiklos Szeredi 142261aaba7SMiklos Szeredi static void fuse_dir_changed(struct inode *dir) 143261aaba7SMiklos Szeredi { 144261aaba7SMiklos Szeredi fuse_invalidate_attr(dir); 145261aaba7SMiklos Szeredi inode_maybe_inc_iversion(dir, false); 146261aaba7SMiklos Szeredi } 147261aaba7SMiklos Szeredi 14806bbb761SRandy Dunlap /* 149451418fcSAndrew Gallagher * Mark the attributes as stale due to an atime change. Avoid the invalidate if 150451418fcSAndrew Gallagher * atime is not used. 151451418fcSAndrew Gallagher */ 152451418fcSAndrew Gallagher void fuse_invalidate_atime(struct inode *inode) 153451418fcSAndrew Gallagher { 154451418fcSAndrew Gallagher if (!IS_RDONLY(inode)) 1552f1e8196SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_ATIME); 156451418fcSAndrew Gallagher } 157451418fcSAndrew Gallagher 1586f9f1180SMiklos Szeredi /* 1596f9f1180SMiklos Szeredi * Just mark the entry as stale, so that a next attempt to look it up 1606f9f1180SMiklos Szeredi * will result in a new lookup call to userspace 1616f9f1180SMiklos Szeredi * 1626f9f1180SMiklos Szeredi * This is called when a dentry is about to become negative and the 1636f9f1180SMiklos Szeredi * timeout is unknown (unlink, rmdir, rename and in some cases 1646f9f1180SMiklos Szeredi * lookup) 1656f9f1180SMiklos Szeredi */ 166dbd561d2SMiklos Szeredi void fuse_invalidate_entry_cache(struct dentry *entry) 1678cbdf1e6SMiklos Szeredi { 1680a0898cfSMiklos Szeredi fuse_dentry_settime(entry, 0); 1698cbdf1e6SMiklos Szeredi } 1708cbdf1e6SMiklos Szeredi 1716f9f1180SMiklos Szeredi /* 1726f9f1180SMiklos Szeredi * Same as fuse_invalidate_entry_cache(), but also try to remove the 1736f9f1180SMiklos Szeredi * dentry from the hash 1746f9f1180SMiklos Szeredi */ 1758cbdf1e6SMiklos Szeredi static void fuse_invalidate_entry(struct dentry *entry) 1768cbdf1e6SMiklos Szeredi { 1778cbdf1e6SMiklos Szeredi d_invalidate(entry); 1788cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1790aa7c699SMiklos Szeredi } 1800aa7c699SMiklos Szeredi 1817078187aSMiklos Szeredi static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, 18213983d06SAl Viro u64 nodeid, const struct qstr *name, 183e5e5558eSMiklos Szeredi struct fuse_entry_out *outarg) 184e5e5558eSMiklos Szeredi { 1850e9663eeSMiklos Szeredi memset(outarg, 0, sizeof(struct fuse_entry_out)); 186d5b48543SMiklos Szeredi args->opcode = FUSE_LOOKUP; 187d5b48543SMiklos Szeredi args->nodeid = nodeid; 188d5b48543SMiklos Szeredi args->in_numargs = 1; 189d5b48543SMiklos Szeredi args->in_args[0].size = name->len + 1; 190d5b48543SMiklos Szeredi args->in_args[0].value = name->name; 191d5b48543SMiklos Szeredi args->out_numargs = 1; 192d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(struct fuse_entry_out); 193d5b48543SMiklos Szeredi args->out_args[0].value = outarg; 194e5e5558eSMiklos Szeredi } 195e5e5558eSMiklos Szeredi 1966f9f1180SMiklos Szeredi /* 1976f9f1180SMiklos Szeredi * Check whether the dentry is still valid 1986f9f1180SMiklos Szeredi * 1996f9f1180SMiklos Szeredi * If the entry validity timeout has expired and the dentry is 2006f9f1180SMiklos Szeredi * positive, try to redo the lookup. If the lookup results in a 2016f9f1180SMiklos Szeredi * different inode, then let the VFS invalidate the dentry and redo 2026f9f1180SMiklos Szeredi * the lookup once more. If the lookup results in the same inode, 2036f9f1180SMiklos Szeredi * then refresh the attributes, timeouts and mark the dentry valid. 2046f9f1180SMiklos Szeredi */ 2050b728e19SAl Viro static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) 206e5e5558eSMiklos Szeredi { 20734286d66SNick Piggin struct inode *inode; 20828420dadSMiklos Szeredi struct dentry *parent; 209fcee216bSMax Reitz struct fuse_mount *fm; 2106314efeeSMiklos Szeredi struct fuse_inode *fi; 211e2a6b952SMiklos Szeredi int ret; 2128cbdf1e6SMiklos Szeredi 2132b0143b5SDavid Howells inode = d_inode_rcu(entry); 2145d069dbeSMiklos Szeredi if (inode && fuse_is_bad(inode)) 215e2a6b952SMiklos Szeredi goto invalid; 216154210ccSAnand Avati else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || 217ccc031e2SJiachen Zhang (flags & (LOOKUP_EXCL | LOOKUP_REVAL | LOOKUP_RENAME_TARGET))) { 218e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 2197078187aSMiklos Szeredi FUSE_ARGS(args); 22007e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 2211fb69e78SMiklos Szeredi u64 attr_version; 2228cbdf1e6SMiklos Szeredi 22350322fe7SMiklos Szeredi /* For negative dentries, always do a fresh lookup */ 2248cbdf1e6SMiklos Szeredi if (!inode) 225e2a6b952SMiklos Szeredi goto invalid; 2268cbdf1e6SMiklos Szeredi 227e2a6b952SMiklos Szeredi ret = -ECHILD; 2280b728e19SAl Viro if (flags & LOOKUP_RCU) 229e2a6b952SMiklos Szeredi goto out; 230e7c0a167SMiklos Szeredi 231fcee216bSMax Reitz fm = get_fuse_mount(inode); 232e5e5558eSMiklos Szeredi 23307e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 234e2a6b952SMiklos Szeredi ret = -ENOMEM; 2357078187aSMiklos Szeredi if (!forget) 236e2a6b952SMiklos Szeredi goto out; 2372d51013eSMiklos Szeredi 238fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 2391fb69e78SMiklos Szeredi 240e956edd0SMiklos Szeredi parent = dget_parent(entry); 241fcee216bSMax Reitz fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)), 242c180eebeSMiklos Szeredi &entry->d_name, &outarg); 243fcee216bSMax Reitz ret = fuse_simple_request(fm, &args); 244e956edd0SMiklos Szeredi dput(parent); 24550322fe7SMiklos Szeredi /* Zero nodeid is same as -ENOENT */ 2467078187aSMiklos Szeredi if (!ret && !outarg.nodeid) 2477078187aSMiklos Szeredi ret = -ENOENT; 2487078187aSMiklos Szeredi if (!ret) { 2496314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 250bf109c64SMax Reitz if (outarg.nodeid != get_node_id(inode) || 251bf109c64SMax Reitz (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) { 252fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, 253fcee216bSMax Reitz outarg.nodeid, 1); 254e2a6b952SMiklos Szeredi goto invalid; 2559e6268dbSMiklos Szeredi } 256c9d8f5f0SKirill Tkhai spin_lock(&fi->lock); 2579e6268dbSMiklos Szeredi fi->nlookup++; 258c9d8f5f0SKirill Tkhai spin_unlock(&fi->lock); 2599e6268dbSMiklos Szeredi } 26007e77dcaSMiklos Szeredi kfree(forget); 2617078187aSMiklos Szeredi if (ret == -ENOMEM) 2627078187aSMiklos Szeredi goto out; 263eb59bd17SMiklos Szeredi if (ret || fuse_invalid_attr(&outarg.attr) || 26415db1683SAmir Goldstein fuse_stale_inode(inode, outarg.generation, &outarg.attr)) 265e2a6b952SMiklos Szeredi goto invalid; 266e5e5558eSMiklos Szeredi 26760bcc88aSSeth Forshee forget_all_cached_acls(inode); 2681fb69e78SMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 2691fb69e78SMiklos Szeredi entry_attr_timeout(&outarg), 2701fb69e78SMiklos Szeredi attr_version); 2711fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 27228420dadSMiklos Szeredi } else if (inode) { 2736314efeeSMiklos Szeredi fi = get_fuse_inode(inode); 2746314efeeSMiklos Szeredi if (flags & LOOKUP_RCU) { 2756314efeeSMiklos Szeredi if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state)) 2766314efeeSMiklos Szeredi return -ECHILD; 2776314efeeSMiklos Szeredi } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) { 27828420dadSMiklos Szeredi parent = dget_parent(entry); 2792b0143b5SDavid Howells fuse_advise_use_readdirplus(d_inode(parent)); 28028420dadSMiklos Szeredi dput(parent); 281e5e5558eSMiklos Szeredi } 28228420dadSMiklos Szeredi } 283e2a6b952SMiklos Szeredi ret = 1; 284e2a6b952SMiklos Szeredi out: 285e2a6b952SMiklos Szeredi return ret; 286e2a6b952SMiklos Szeredi 287e2a6b952SMiklos Szeredi invalid: 288e2a6b952SMiklos Szeredi ret = 0; 289e2a6b952SMiklos Szeredi goto out; 290e5e5558eSMiklos Szeredi } 291e5e5558eSMiklos Szeredi 29230c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 293f75fdf22SMiklos Szeredi static int fuse_dentry_init(struct dentry *dentry) 294f75fdf22SMiklos Szeredi { 295dc69e98cSKhazhismel Kumykov dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry), 296dc69e98cSKhazhismel Kumykov GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE); 297f75fdf22SMiklos Szeredi 298f75fdf22SMiklos Szeredi return dentry->d_fsdata ? 0 : -ENOMEM; 299f75fdf22SMiklos Szeredi } 300f75fdf22SMiklos Szeredi static void fuse_dentry_release(struct dentry *dentry) 301f75fdf22SMiklos Szeredi { 302f75fdf22SMiklos Szeredi union fuse_dentry *fd = dentry->d_fsdata; 303f75fdf22SMiklos Szeredi 304f75fdf22SMiklos Szeredi kfree_rcu(fd, rcu); 305f75fdf22SMiklos Szeredi } 30630c6a23dSKhazhismel Kumykov #endif 307f75fdf22SMiklos Szeredi 3088fab0106SMiklos Szeredi static int fuse_dentry_delete(const struct dentry *dentry) 3098fab0106SMiklos Szeredi { 3108fab0106SMiklos Szeredi return time_before64(fuse_dentry_time(dentry), get_jiffies_64()); 3118fab0106SMiklos Szeredi } 3128fab0106SMiklos Szeredi 313bf109c64SMax Reitz /* 314bf109c64SMax Reitz * Create a fuse_mount object with a new superblock (with path->dentry 315bf109c64SMax Reitz * as the root), and return that mount so it can be auto-mounted on 316bf109c64SMax Reitz * @path. 317bf109c64SMax Reitz */ 318bf109c64SMax Reitz static struct vfsmount *fuse_dentry_automount(struct path *path) 319bf109c64SMax Reitz { 320bf109c64SMax Reitz struct fs_context *fsc; 321bf109c64SMax Reitz struct vfsmount *mnt; 322bf109c64SMax Reitz struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry)); 323bf109c64SMax Reitz 324bf109c64SMax Reitz fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry); 32529e0e4dfSGreg Kurz if (IS_ERR(fsc)) 32629e0e4dfSGreg Kurz return ERR_CAST(fsc); 327bf109c64SMax Reitz 328266eb3f2SGreg Kurz /* Pass the FUSE inode of the mount for fuse_get_tree_submount() */ 329266eb3f2SGreg Kurz fsc->fs_private = mp_fi; 330266eb3f2SGreg Kurz 331bf109c64SMax Reitz /* Create the submount */ 33229e0e4dfSGreg Kurz mnt = fc_mount(fsc); 33329e0e4dfSGreg Kurz if (!IS_ERR(mnt)) 334bf109c64SMax Reitz mntget(mnt); 33529e0e4dfSGreg Kurz 336bf109c64SMax Reitz put_fs_context(fsc); 337bf109c64SMax Reitz return mnt; 338bf109c64SMax Reitz } 339bf109c64SMax Reitz 3404269590aSAl Viro const struct dentry_operations fuse_dentry_operations = { 341e5e5558eSMiklos Szeredi .d_revalidate = fuse_dentry_revalidate, 3428fab0106SMiklos Szeredi .d_delete = fuse_dentry_delete, 34330c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 344f75fdf22SMiklos Szeredi .d_init = fuse_dentry_init, 345f75fdf22SMiklos Szeredi .d_release = fuse_dentry_release, 34630c6a23dSKhazhismel Kumykov #endif 347bf109c64SMax Reitz .d_automount = fuse_dentry_automount, 348e5e5558eSMiklos Szeredi }; 349e5e5558eSMiklos Szeredi 3500ce267ffSMiklos Szeredi const struct dentry_operations fuse_root_dentry_operations = { 35130c6a23dSKhazhismel Kumykov #if BITS_PER_LONG < 64 3520ce267ffSMiklos Szeredi .d_init = fuse_dentry_init, 3530ce267ffSMiklos Szeredi .d_release = fuse_dentry_release, 35430c6a23dSKhazhismel Kumykov #endif 3550ce267ffSMiklos Szeredi }; 3560ce267ffSMiklos Szeredi 357a5bfffacSTimo Savola int fuse_valid_type(int m) 35839ee059aSMiklos Szeredi { 35939ee059aSMiklos Szeredi return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) || 36039ee059aSMiklos Szeredi S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); 36139ee059aSMiklos Szeredi } 36239ee059aSMiklos Szeredi 363eb59bd17SMiklos Szeredi bool fuse_invalid_attr(struct fuse_attr *attr) 364eb59bd17SMiklos Szeredi { 365eb59bd17SMiklos Szeredi return !fuse_valid_type(attr->mode) || 366eb59bd17SMiklos Szeredi attr->size > LLONG_MAX; 367eb59bd17SMiklos Szeredi } 368eb59bd17SMiklos Szeredi 36913983d06SAl Viro int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, 370c180eebeSMiklos Szeredi struct fuse_entry_out *outarg, struct inode **inode) 371c180eebeSMiklos Szeredi { 372fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount_super(sb); 3737078187aSMiklos Szeredi FUSE_ARGS(args); 37407e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 375c180eebeSMiklos Szeredi u64 attr_version; 376c180eebeSMiklos Szeredi int err; 377c180eebeSMiklos Szeredi 378c180eebeSMiklos Szeredi *inode = NULL; 379c180eebeSMiklos Szeredi err = -ENAMETOOLONG; 380c180eebeSMiklos Szeredi if (name->len > FUSE_NAME_MAX) 381c180eebeSMiklos Szeredi goto out; 382c180eebeSMiklos Szeredi 383c180eebeSMiklos Szeredi 38407e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 38507e77dcaSMiklos Szeredi err = -ENOMEM; 3867078187aSMiklos Szeredi if (!forget) 387c180eebeSMiklos Szeredi goto out; 388c180eebeSMiklos Szeredi 389fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 390c180eebeSMiklos Szeredi 391fcee216bSMax Reitz fuse_lookup_init(fm->fc, &args, nodeid, name, outarg); 392fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 393c180eebeSMiklos Szeredi /* Zero nodeid is same as -ENOENT, but with valid timeout */ 394c180eebeSMiklos Szeredi if (err || !outarg->nodeid) 395c180eebeSMiklos Szeredi goto out_put_forget; 396c180eebeSMiklos Szeredi 397c180eebeSMiklos Szeredi err = -EIO; 398c180eebeSMiklos Szeredi if (!outarg->nodeid) 399c180eebeSMiklos Szeredi goto out_put_forget; 400eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg->attr)) 401c180eebeSMiklos Szeredi goto out_put_forget; 402c180eebeSMiklos Szeredi 403c180eebeSMiklos Szeredi *inode = fuse_iget(sb, outarg->nodeid, outarg->generation, 404c180eebeSMiklos Szeredi &outarg->attr, entry_attr_timeout(outarg), 405c180eebeSMiklos Szeredi attr_version); 406c180eebeSMiklos Szeredi err = -ENOMEM; 407c180eebeSMiklos Szeredi if (!*inode) { 408fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1); 409c180eebeSMiklos Szeredi goto out; 410c180eebeSMiklos Szeredi } 411c180eebeSMiklos Szeredi err = 0; 412c180eebeSMiklos Szeredi 413c180eebeSMiklos Szeredi out_put_forget: 41407e77dcaSMiklos Szeredi kfree(forget); 415c180eebeSMiklos Szeredi out: 416c180eebeSMiklos Szeredi return err; 417c180eebeSMiklos Szeredi } 418c180eebeSMiklos Szeredi 4190aa7c699SMiklos Szeredi static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, 42000cd8dd3SAl Viro unsigned int flags) 421e5e5558eSMiklos Szeredi { 422e5e5558eSMiklos Szeredi int err; 423e5e5558eSMiklos Szeredi struct fuse_entry_out outarg; 424c180eebeSMiklos Szeredi struct inode *inode; 4250de6256dSMiklos Szeredi struct dentry *newent; 426c180eebeSMiklos Szeredi bool outarg_valid = true; 42763576c13SMiklos Szeredi bool locked; 428e5e5558eSMiklos Szeredi 4295d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 4305d069dbeSMiklos Szeredi return ERR_PTR(-EIO); 4315d069dbeSMiklos Szeredi 43263576c13SMiklos Szeredi locked = fuse_lock_inode(dir); 433c180eebeSMiklos Szeredi err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, 434c180eebeSMiklos Szeredi &outarg, &inode); 43563576c13SMiklos Szeredi fuse_unlock_inode(dir, locked); 436c180eebeSMiklos Szeredi if (err == -ENOENT) { 437c180eebeSMiklos Szeredi outarg_valid = false; 438c180eebeSMiklos Szeredi err = 0; 4392d51013eSMiklos Szeredi } 440c180eebeSMiklos Szeredi if (err) 441c180eebeSMiklos Szeredi goto out_err; 4422d51013eSMiklos Szeredi 443ee4e5271SMiklos Szeredi err = -EIO; 444c180eebeSMiklos Szeredi if (inode && get_node_id(inode) == FUSE_ROOT_ID) 445c180eebeSMiklos Szeredi goto out_iput; 446e5e5558eSMiklos Szeredi 44741d28bcaSAl Viro newent = d_splice_alias(inode, entry); 448c180eebeSMiklos Szeredi err = PTR_ERR(newent); 449c180eebeSMiklos Szeredi if (IS_ERR(newent)) 4505835f339SMiklos Szeredi goto out_err; 451d2a85164SMiklos Szeredi 4520de6256dSMiklos Szeredi entry = newent ? newent : entry; 453c180eebeSMiklos Szeredi if (outarg_valid) 4541fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 4558cbdf1e6SMiklos Szeredi else 4568cbdf1e6SMiklos Szeredi fuse_invalidate_entry_cache(entry); 457c180eebeSMiklos Szeredi 4586c26f717SMiklos Szeredi if (inode) 4594582a4abSFeng Shuo fuse_advise_use_readdirplus(dir); 4600de6256dSMiklos Szeredi return newent; 461c180eebeSMiklos Szeredi 462c180eebeSMiklos Szeredi out_iput: 463c180eebeSMiklos Szeredi iput(inode); 464c180eebeSMiklos Szeredi out_err: 465c180eebeSMiklos Szeredi return ERR_PTR(err); 466e5e5558eSMiklos Szeredi } 467e5e5558eSMiklos Szeredi 4683e2b6fdbSVivek Goyal static int get_security_context(struct dentry *entry, umode_t mode, 46915d937d7SMiklos Szeredi struct fuse_in_arg *ext) 4703e2b6fdbSVivek Goyal { 4713e2b6fdbSVivek Goyal struct fuse_secctx *fctx; 4723e2b6fdbSVivek Goyal struct fuse_secctx_header *header; 4733e2b6fdbSVivek Goyal void *ctx = NULL, *ptr; 4743e2b6fdbSVivek Goyal u32 ctxlen, total_len = sizeof(*header); 4753e2b6fdbSVivek Goyal int err, nr_ctx = 0; 4763e2b6fdbSVivek Goyal const char *name; 4773e2b6fdbSVivek Goyal size_t namelen; 4783e2b6fdbSVivek Goyal 4793e2b6fdbSVivek Goyal err = security_dentry_init_security(entry, mode, &entry->d_name, 4803e2b6fdbSVivek Goyal &name, &ctx, &ctxlen); 4813e2b6fdbSVivek Goyal if (err) { 4823e2b6fdbSVivek Goyal if (err != -EOPNOTSUPP) 4833e2b6fdbSVivek Goyal goto out_err; 4843e2b6fdbSVivek Goyal /* No LSM is supporting this security hook. Ignore error */ 4853e2b6fdbSVivek Goyal ctxlen = 0; 4863e2b6fdbSVivek Goyal ctx = NULL; 4873e2b6fdbSVivek Goyal } 4883e2b6fdbSVivek Goyal 4893e2b6fdbSVivek Goyal if (ctxlen) { 4903e2b6fdbSVivek Goyal nr_ctx = 1; 4913e2b6fdbSVivek Goyal namelen = strlen(name) + 1; 4923e2b6fdbSVivek Goyal err = -EIO; 4933e2b6fdbSVivek Goyal if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX)) 4943e2b6fdbSVivek Goyal goto out_err; 4953e2b6fdbSVivek Goyal total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen); 4963e2b6fdbSVivek Goyal } 4973e2b6fdbSVivek Goyal 4983e2b6fdbSVivek Goyal err = -ENOMEM; 4993e2b6fdbSVivek Goyal header = ptr = kzalloc(total_len, GFP_KERNEL); 5003e2b6fdbSVivek Goyal if (!ptr) 5013e2b6fdbSVivek Goyal goto out_err; 5023e2b6fdbSVivek Goyal 5033e2b6fdbSVivek Goyal header->nr_secctx = nr_ctx; 5043e2b6fdbSVivek Goyal header->size = total_len; 5053e2b6fdbSVivek Goyal ptr += sizeof(*header); 5063e2b6fdbSVivek Goyal if (nr_ctx) { 5073e2b6fdbSVivek Goyal fctx = ptr; 5083e2b6fdbSVivek Goyal fctx->size = ctxlen; 5093e2b6fdbSVivek Goyal ptr += sizeof(*fctx); 5103e2b6fdbSVivek Goyal 5113e2b6fdbSVivek Goyal strcpy(ptr, name); 5123e2b6fdbSVivek Goyal ptr += namelen; 5133e2b6fdbSVivek Goyal 5143e2b6fdbSVivek Goyal memcpy(ptr, ctx, ctxlen); 5153e2b6fdbSVivek Goyal } 51615d937d7SMiklos Szeredi ext->size = total_len; 51715d937d7SMiklos Szeredi ext->value = header; 5183e2b6fdbSVivek Goyal err = 0; 5193e2b6fdbSVivek Goyal out_err: 5203e2b6fdbSVivek Goyal kfree(ctx); 5213e2b6fdbSVivek Goyal return err; 5223e2b6fdbSVivek Goyal } 5233e2b6fdbSVivek Goyal 5248ed7cb3fSMiklos Szeredi static void *extend_arg(struct fuse_in_arg *buf, u32 bytes) 5258ed7cb3fSMiklos Szeredi { 5268ed7cb3fSMiklos Szeredi void *p; 5278ed7cb3fSMiklos Szeredi u32 newlen = buf->size + bytes; 5288ed7cb3fSMiklos Szeredi 5298ed7cb3fSMiklos Szeredi p = krealloc(buf->value, newlen, GFP_KERNEL); 5308ed7cb3fSMiklos Szeredi if (!p) { 5318ed7cb3fSMiklos Szeredi kfree(buf->value); 5328ed7cb3fSMiklos Szeredi buf->size = 0; 5338ed7cb3fSMiklos Szeredi buf->value = NULL; 5348ed7cb3fSMiklos Szeredi return NULL; 5358ed7cb3fSMiklos Szeredi } 5368ed7cb3fSMiklos Szeredi 5378ed7cb3fSMiklos Szeredi memset(p + buf->size, 0, bytes); 5388ed7cb3fSMiklos Szeredi buf->value = p; 5398ed7cb3fSMiklos Szeredi buf->size = newlen; 5408ed7cb3fSMiklos Szeredi 5418ed7cb3fSMiklos Szeredi return p + newlen - bytes; 5428ed7cb3fSMiklos Szeredi } 5438ed7cb3fSMiklos Szeredi 5448ed7cb3fSMiklos Szeredi static u32 fuse_ext_size(size_t size) 5458ed7cb3fSMiklos Szeredi { 5468ed7cb3fSMiklos Szeredi return FUSE_REC_ALIGN(sizeof(struct fuse_ext_header) + size); 5478ed7cb3fSMiklos Szeredi } 5488ed7cb3fSMiklos Szeredi 5498ed7cb3fSMiklos Szeredi /* 5508ed7cb3fSMiklos Szeredi * This adds just a single supplementary group that matches the parent's group. 5518ed7cb3fSMiklos Szeredi */ 5528ed7cb3fSMiklos Szeredi static int get_create_supp_group(struct inode *dir, struct fuse_in_arg *ext) 5538ed7cb3fSMiklos Szeredi { 5548ed7cb3fSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 5558ed7cb3fSMiklos Szeredi struct fuse_ext_header *xh; 5568ed7cb3fSMiklos Szeredi struct fuse_supp_groups *sg; 5578ed7cb3fSMiklos Szeredi kgid_t kgid = dir->i_gid; 5588ed7cb3fSMiklos Szeredi gid_t parent_gid = from_kgid(fc->user_ns, kgid); 5598ed7cb3fSMiklos Szeredi u32 sg_len = fuse_ext_size(sizeof(*sg) + sizeof(sg->groups[0])); 5608ed7cb3fSMiklos Szeredi 5618ed7cb3fSMiklos Szeredi if (parent_gid == (gid_t) -1 || gid_eq(kgid, current_fsgid()) || 5628ed7cb3fSMiklos Szeredi !in_group_p(kgid)) 5638ed7cb3fSMiklos Szeredi return 0; 5648ed7cb3fSMiklos Szeredi 5658ed7cb3fSMiklos Szeredi xh = extend_arg(ext, sg_len); 5668ed7cb3fSMiklos Szeredi if (!xh) 5678ed7cb3fSMiklos Szeredi return -ENOMEM; 5688ed7cb3fSMiklos Szeredi 5698ed7cb3fSMiklos Szeredi xh->size = sg_len; 5708ed7cb3fSMiklos Szeredi xh->type = FUSE_EXT_GROUPS; 5718ed7cb3fSMiklos Szeredi 5728ed7cb3fSMiklos Szeredi sg = (struct fuse_supp_groups *) &xh[1]; 5738ed7cb3fSMiklos Szeredi sg->nr_groups = 1; 5748ed7cb3fSMiklos Szeredi sg->groups[0] = parent_gid; 5758ed7cb3fSMiklos Szeredi 5768ed7cb3fSMiklos Szeredi return 0; 5778ed7cb3fSMiklos Szeredi } 5788ed7cb3fSMiklos Szeredi 5798ed7cb3fSMiklos Szeredi static int get_create_ext(struct fuse_args *args, 5808ed7cb3fSMiklos Szeredi struct inode *dir, struct dentry *dentry, 58115d937d7SMiklos Szeredi umode_t mode) 58215d937d7SMiklos Szeredi { 58315d937d7SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb); 58415d937d7SMiklos Szeredi struct fuse_in_arg ext = { .size = 0, .value = NULL }; 58515d937d7SMiklos Szeredi int err = 0; 58615d937d7SMiklos Szeredi 58715d937d7SMiklos Szeredi if (fc->init_security) 58815d937d7SMiklos Szeredi err = get_security_context(dentry, mode, &ext); 5898ed7cb3fSMiklos Szeredi if (!err && fc->create_supp_group) 5908ed7cb3fSMiklos Szeredi err = get_create_supp_group(dir, &ext); 59115d937d7SMiklos Szeredi 59215d937d7SMiklos Szeredi if (!err && ext.size) { 59315d937d7SMiklos Szeredi WARN_ON(args->in_numargs >= ARRAY_SIZE(args->in_args)); 59415d937d7SMiklos Szeredi args->is_ext = true; 59515d937d7SMiklos Szeredi args->ext_idx = args->in_numargs++; 59615d937d7SMiklos Szeredi args->in_args[args->ext_idx] = ext; 59715d937d7SMiklos Szeredi } else { 59815d937d7SMiklos Szeredi kfree(ext.value); 59915d937d7SMiklos Szeredi } 60015d937d7SMiklos Szeredi 60115d937d7SMiklos Szeredi return err; 60215d937d7SMiklos Szeredi } 60315d937d7SMiklos Szeredi 60415d937d7SMiklos Szeredi static void free_ext_value(struct fuse_args *args) 60515d937d7SMiklos Szeredi { 60615d937d7SMiklos Szeredi if (args->is_ext) 60715d937d7SMiklos Szeredi kfree(args->in_args[args->ext_idx].value); 60815d937d7SMiklos Szeredi } 60915d937d7SMiklos Szeredi 6106f9f1180SMiklos Szeredi /* 6116f9f1180SMiklos Szeredi * Atomic create+open operation 6126f9f1180SMiklos Szeredi * 6136f9f1180SMiklos Szeredi * If the filesystem doesn't support this, then fall back to separate 6146f9f1180SMiklos Szeredi * 'mknod' + 'open' requests. 6156f9f1180SMiklos Szeredi */ 616d9585277SAl Viro static int fuse_create_open(struct inode *dir, struct dentry *entry, 61754d601cbSMiklos Szeredi struct file *file, unsigned int flags, 6187d375390SMiklos Szeredi umode_t mode, u32 opcode) 619fd72faacSMiklos Szeredi { 620fd72faacSMiklos Szeredi int err; 621fd72faacSMiklos Szeredi struct inode *inode; 622fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 6237078187aSMiklos Szeredi FUSE_ARGS(args); 62407e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 625e0a43ddcSMiklos Szeredi struct fuse_create_in inarg; 626fd72faacSMiklos Szeredi struct fuse_open_out outopen; 627fd72faacSMiklos Szeredi struct fuse_entry_out outentry; 628ebf84d0cSKirill Tkhai struct fuse_inode *fi; 629fd72faacSMiklos Szeredi struct fuse_file *ff; 6302fdbb8ddSMiklos Szeredi bool trunc = flags & O_TRUNC; 631fd72faacSMiklos Szeredi 632af109bcaSMiklos Szeredi /* Userspace expects S_IFREG in create mode */ 633af109bcaSMiklos Szeredi BUG_ON((mode & S_IFMT) != S_IFREG); 634af109bcaSMiklos Szeredi 63507e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 636c8ccbe03SMiklos Szeredi err = -ENOMEM; 63707e77dcaSMiklos Szeredi if (!forget) 638c8ccbe03SMiklos Szeredi goto out_err; 63951eb01e7SMiklos Szeredi 640ce1d5a49SMiklos Szeredi err = -ENOMEM; 641fcee216bSMax Reitz ff = fuse_file_alloc(fm); 642fd72faacSMiklos Szeredi if (!ff) 6437078187aSMiklos Szeredi goto out_put_forget_req; 644fd72faacSMiklos Szeredi 645fcee216bSMax Reitz if (!fm->fc->dont_mask) 646e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 647e0a43ddcSMiklos Szeredi 648fd72faacSMiklos Szeredi flags &= ~O_NOCTTY; 649fd72faacSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 6500e9663eeSMiklos Szeredi memset(&outentry, 0, sizeof(outentry)); 651fd72faacSMiklos Szeredi inarg.flags = flags; 652fd72faacSMiklos Szeredi inarg.mode = mode; 653e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 654643a666aSVivek Goyal 6552fdbb8ddSMiklos Szeredi if (fm->fc->handle_killpriv_v2 && trunc && 656643a666aSVivek Goyal !(flags & O_EXCL) && !capable(CAP_FSETID)) { 657643a666aSVivek Goyal inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID; 658643a666aSVivek Goyal } 659643a666aSVivek Goyal 6607d375390SMiklos Szeredi args.opcode = opcode; 661d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 662d5b48543SMiklos Szeredi args.in_numargs = 2; 663d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 664d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 665d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 666d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 667d5b48543SMiklos Szeredi args.out_numargs = 2; 668d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outentry); 669d5b48543SMiklos Szeredi args.out_args[0].value = &outentry; 670d5b48543SMiklos Szeredi args.out_args[1].size = sizeof(outopen); 671d5b48543SMiklos Szeredi args.out_args[1].value = &outopen; 6723e2b6fdbSVivek Goyal 6738ed7cb3fSMiklos Szeredi err = get_create_ext(&args, dir, entry, mode); 6743e2b6fdbSVivek Goyal if (err) 6753e2b6fdbSVivek Goyal goto out_put_forget_req; 6763e2b6fdbSVivek Goyal 677fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 67815d937d7SMiklos Szeredi free_ext_value(&args); 679c8ccbe03SMiklos Szeredi if (err) 680fd72faacSMiklos Szeredi goto out_free_ff; 681fd72faacSMiklos Szeredi 682fd72faacSMiklos Szeredi err = -EIO; 683eb59bd17SMiklos Szeredi if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) || 684eb59bd17SMiklos Szeredi fuse_invalid_attr(&outentry.attr)) 685fd72faacSMiklos Szeredi goto out_free_ff; 686fd72faacSMiklos Szeredi 687c7b7143cSMiklos Szeredi ff->fh = outopen.fh; 688c7b7143cSMiklos Szeredi ff->nodeid = outentry.nodeid; 689c7b7143cSMiklos Szeredi ff->open_flags = outopen.open_flags; 690fd72faacSMiklos Szeredi inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 6911fb69e78SMiklos Szeredi &outentry.attr, entry_attr_timeout(&outentry), 0); 692fd72faacSMiklos Szeredi if (!inode) { 693fd72faacSMiklos Szeredi flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 694ebf84d0cSKirill Tkhai fuse_sync_release(NULL, ff, flags); 695fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1); 696c8ccbe03SMiklos Szeredi err = -ENOMEM; 697c8ccbe03SMiklos Szeredi goto out_err; 698fd72faacSMiklos Szeredi } 69907e77dcaSMiklos Szeredi kfree(forget); 700fd72faacSMiklos Szeredi d_instantiate(entry, inode); 7011fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outentry); 702261aaba7SMiklos Szeredi fuse_dir_changed(dir); 703be12af3eSAl Viro err = finish_open(file, entry, generic_file_open); 70430d90494SAl Viro if (err) { 705ebf84d0cSKirill Tkhai fi = get_fuse_inode(inode); 706ebf84d0cSKirill Tkhai fuse_sync_release(fi, ff, flags); 707c8ccbe03SMiklos Szeredi } else { 708267d8444SMiklos Szeredi file->private_data = ff; 709c7b7143cSMiklos Szeredi fuse_finish_open(inode, file); 7102fdbb8ddSMiklos Szeredi if (fm->fc->atomic_o_trunc && trunc) 7112fdbb8ddSMiklos Szeredi truncate_pagecache(inode, 0); 7122fdbb8ddSMiklos Szeredi else if (!(ff->open_flags & FOPEN_KEEP_CACHE)) 7132fdbb8ddSMiklos Szeredi invalidate_inode_pages2(inode->i_mapping); 714c8ccbe03SMiklos Szeredi } 715d9585277SAl Viro return err; 716fd72faacSMiklos Szeredi 717fd72faacSMiklos Szeredi out_free_ff: 718fd72faacSMiklos Szeredi fuse_file_free(ff); 71951eb01e7SMiklos Szeredi out_put_forget_req: 72007e77dcaSMiklos Szeredi kfree(forget); 721c8ccbe03SMiklos Szeredi out_err: 722d9585277SAl Viro return err; 723c8ccbe03SMiklos Szeredi } 724c8ccbe03SMiklos Szeredi 7255ebb29beSChristian Brauner static int fuse_mknod(struct mnt_idmap *, struct inode *, struct dentry *, 726549c7297SChristian Brauner umode_t, dev_t); 727d9585277SAl Viro static int fuse_atomic_open(struct inode *dir, struct dentry *entry, 72830d90494SAl Viro struct file *file, unsigned flags, 72944907d79SAl Viro umode_t mode) 730c8ccbe03SMiklos Szeredi { 731c8ccbe03SMiklos Szeredi int err; 732c8ccbe03SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 733c8ccbe03SMiklos Szeredi struct dentry *res = NULL; 734c8ccbe03SMiklos Szeredi 7355d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 7365d069dbeSMiklos Szeredi return -EIO; 7375d069dbeSMiklos Szeredi 73800699ad8SAl Viro if (d_in_lookup(entry)) { 73900cd8dd3SAl Viro res = fuse_lookup(dir, entry, 0); 740c8ccbe03SMiklos Szeredi if (IS_ERR(res)) 741d9585277SAl Viro return PTR_ERR(res); 742c8ccbe03SMiklos Szeredi 743c8ccbe03SMiklos Szeredi if (res) 744c8ccbe03SMiklos Szeredi entry = res; 745c8ccbe03SMiklos Szeredi } 746c8ccbe03SMiklos Szeredi 7472b0143b5SDavid Howells if (!(flags & O_CREAT) || d_really_is_positive(entry)) 748c8ccbe03SMiklos Szeredi goto no_open; 749c8ccbe03SMiklos Szeredi 750c8ccbe03SMiklos Szeredi /* Only creates */ 75173a09dd9SAl Viro file->f_mode |= FMODE_CREATED; 752c8ccbe03SMiklos Szeredi 753c8ccbe03SMiklos Szeredi if (fc->no_create) 754c8ccbe03SMiklos Szeredi goto mknod; 755c8ccbe03SMiklos Szeredi 7567d375390SMiklos Szeredi err = fuse_create_open(dir, entry, file, flags, mode, FUSE_CREATE); 757d9585277SAl Viro if (err == -ENOSYS) { 758c8ccbe03SMiklos Szeredi fc->no_create = 1; 759c8ccbe03SMiklos Szeredi goto mknod; 760c8ccbe03SMiklos Szeredi } 761c8ccbe03SMiklos Szeredi out_dput: 762c8ccbe03SMiklos Szeredi dput(res); 763d9585277SAl Viro return err; 764c8ccbe03SMiklos Szeredi 765c8ccbe03SMiklos Szeredi mknod: 7665ebb29beSChristian Brauner err = fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0); 767d9585277SAl Viro if (err) 768c8ccbe03SMiklos Szeredi goto out_dput; 769c8ccbe03SMiklos Szeredi no_open: 770e45198a6SAl Viro return finish_no_open(file, res); 771fd72faacSMiklos Szeredi } 772fd72faacSMiklos Szeredi 7736f9f1180SMiklos Szeredi /* 7746f9f1180SMiklos Szeredi * Code shared between mknod, mkdir, symlink and link 7756f9f1180SMiklos Szeredi */ 776fcee216bSMax Reitz static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args, 7779e6268dbSMiklos Szeredi struct inode *dir, struct dentry *entry, 778541af6a0SAl Viro umode_t mode) 7799e6268dbSMiklos Szeredi { 7809e6268dbSMiklos Szeredi struct fuse_entry_out outarg; 7819e6268dbSMiklos Szeredi struct inode *inode; 782c971e6a0SAl Viro struct dentry *d; 7839e6268dbSMiklos Szeredi int err; 78407e77dcaSMiklos Szeredi struct fuse_forget_link *forget; 7852d51013eSMiklos Szeredi 7865d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 7875d069dbeSMiklos Szeredi return -EIO; 7885d069dbeSMiklos Szeredi 78907e77dcaSMiklos Szeredi forget = fuse_alloc_forget(); 7907078187aSMiklos Szeredi if (!forget) 79107e77dcaSMiklos Szeredi return -ENOMEM; 7929e6268dbSMiklos Szeredi 7930e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 794d5b48543SMiklos Szeredi args->nodeid = get_node_id(dir); 795d5b48543SMiklos Szeredi args->out_numargs = 1; 796d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(outarg); 797d5b48543SMiklos Szeredi args->out_args[0].value = &outarg; 7983e2b6fdbSVivek Goyal 79915d937d7SMiklos Szeredi if (args->opcode != FUSE_LINK) { 8008ed7cb3fSMiklos Szeredi err = get_create_ext(args, dir, entry, mode); 8013e2b6fdbSVivek Goyal if (err) 8023e2b6fdbSVivek Goyal goto out_put_forget_req; 8033e2b6fdbSVivek Goyal } 8043e2b6fdbSVivek Goyal 805fcee216bSMax Reitz err = fuse_simple_request(fm, args); 80615d937d7SMiklos Szeredi free_ext_value(args); 8072d51013eSMiklos Szeredi if (err) 8082d51013eSMiklos Szeredi goto out_put_forget_req; 8092d51013eSMiklos Szeredi 81039ee059aSMiklos Szeredi err = -EIO; 811eb59bd17SMiklos Szeredi if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr)) 8122d51013eSMiklos Szeredi goto out_put_forget_req; 81339ee059aSMiklos Szeredi 81439ee059aSMiklos Szeredi if ((outarg.attr.mode ^ mode) & S_IFMT) 8152d51013eSMiklos Szeredi goto out_put_forget_req; 81639ee059aSMiklos Szeredi 8179e6268dbSMiklos Szeredi inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 8181fb69e78SMiklos Szeredi &outarg.attr, entry_attr_timeout(&outarg), 0); 8199e6268dbSMiklos Szeredi if (!inode) { 820fcee216bSMax Reitz fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1); 8219e6268dbSMiklos Szeredi return -ENOMEM; 8229e6268dbSMiklos Szeredi } 82307e77dcaSMiklos Szeredi kfree(forget); 8249e6268dbSMiklos Szeredi 825c971e6a0SAl Viro d_drop(entry); 826c971e6a0SAl Viro d = d_splice_alias(inode, entry); 827c971e6a0SAl Viro if (IS_ERR(d)) 828c971e6a0SAl Viro return PTR_ERR(d); 829d2a85164SMiklos Szeredi 830c971e6a0SAl Viro if (d) { 831c971e6a0SAl Viro fuse_change_entry_timeout(d, &outarg); 832c971e6a0SAl Viro dput(d); 833c971e6a0SAl Viro } else { 8341fb69e78SMiklos Szeredi fuse_change_entry_timeout(entry, &outarg); 835c971e6a0SAl Viro } 836261aaba7SMiklos Szeredi fuse_dir_changed(dir); 8379e6268dbSMiklos Szeredi return 0; 83839ee059aSMiklos Szeredi 8392d51013eSMiklos Szeredi out_put_forget_req: 84007e77dcaSMiklos Szeredi kfree(forget); 84139ee059aSMiklos Szeredi return err; 8429e6268dbSMiklos Szeredi } 8439e6268dbSMiklos Szeredi 8445ebb29beSChristian Brauner static int fuse_mknod(struct mnt_idmap *idmap, struct inode *dir, 845549c7297SChristian Brauner struct dentry *entry, umode_t mode, dev_t rdev) 8469e6268dbSMiklos Szeredi { 8479e6268dbSMiklos Szeredi struct fuse_mknod_in inarg; 848fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 8497078187aSMiklos Szeredi FUSE_ARGS(args); 8509e6268dbSMiklos Szeredi 851fcee216bSMax Reitz if (!fm->fc->dont_mask) 852e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 853e0a43ddcSMiklos Szeredi 8549e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 8559e6268dbSMiklos Szeredi inarg.mode = mode; 8569e6268dbSMiklos Szeredi inarg.rdev = new_encode_dev(rdev); 857e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 858d5b48543SMiklos Szeredi args.opcode = FUSE_MKNOD; 859d5b48543SMiklos Szeredi args.in_numargs = 2; 860d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 861d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 862d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 863d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 864fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, mode); 8659e6268dbSMiklos Szeredi } 8669e6268dbSMiklos Szeredi 8676c960e68SChristian Brauner static int fuse_create(struct mnt_idmap *idmap, struct inode *dir, 868549c7297SChristian Brauner struct dentry *entry, umode_t mode, bool excl) 8699e6268dbSMiklos Szeredi { 8705ebb29beSChristian Brauner return fuse_mknod(&nop_mnt_idmap, dir, entry, mode, 0); 8719e6268dbSMiklos Szeredi } 8729e6268dbSMiklos Szeredi 873011e2b71SChristian Brauner static int fuse_tmpfile(struct mnt_idmap *idmap, struct inode *dir, 8747d375390SMiklos Szeredi struct file *file, umode_t mode) 8757d375390SMiklos Szeredi { 8767d375390SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(dir); 8777d375390SMiklos Szeredi int err; 8787d375390SMiklos Szeredi 8797d375390SMiklos Szeredi if (fc->no_tmpfile) 8807d375390SMiklos Szeredi return -EOPNOTSUPP; 8817d375390SMiklos Szeredi 8827d375390SMiklos Szeredi err = fuse_create_open(dir, file->f_path.dentry, file, file->f_flags, mode, FUSE_TMPFILE); 8837d375390SMiklos Szeredi if (err == -ENOSYS) { 8847d375390SMiklos Szeredi fc->no_tmpfile = 1; 8857d375390SMiklos Szeredi err = -EOPNOTSUPP; 8867d375390SMiklos Szeredi } 8877d375390SMiklos Szeredi return err; 8887d375390SMiklos Szeredi } 8897d375390SMiklos Szeredi 890c54bd91eSChristian Brauner static int fuse_mkdir(struct mnt_idmap *idmap, struct inode *dir, 891549c7297SChristian Brauner struct dentry *entry, umode_t mode) 8929e6268dbSMiklos Szeredi { 8939e6268dbSMiklos Szeredi struct fuse_mkdir_in inarg; 894fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 8957078187aSMiklos Szeredi FUSE_ARGS(args); 8969e6268dbSMiklos Szeredi 897fcee216bSMax Reitz if (!fm->fc->dont_mask) 898e0a43ddcSMiklos Szeredi mode &= ~current_umask(); 899e0a43ddcSMiklos Szeredi 9009e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 9019e6268dbSMiklos Szeredi inarg.mode = mode; 902e0a43ddcSMiklos Szeredi inarg.umask = current_umask(); 903d5b48543SMiklos Szeredi args.opcode = FUSE_MKDIR; 904d5b48543SMiklos Szeredi args.in_numargs = 2; 905d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 906d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 907d5b48543SMiklos Szeredi args.in_args[1].size = entry->d_name.len + 1; 908d5b48543SMiklos Szeredi args.in_args[1].value = entry->d_name.name; 909fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFDIR); 9109e6268dbSMiklos Szeredi } 9119e6268dbSMiklos Szeredi 9127a77db95SChristian Brauner static int fuse_symlink(struct mnt_idmap *idmap, struct inode *dir, 913549c7297SChristian Brauner struct dentry *entry, const char *link) 9149e6268dbSMiklos Szeredi { 915fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 9169e6268dbSMiklos Szeredi unsigned len = strlen(link) + 1; 9177078187aSMiklos Szeredi FUSE_ARGS(args); 9189e6268dbSMiklos Szeredi 919d5b48543SMiklos Szeredi args.opcode = FUSE_SYMLINK; 920d5b48543SMiklos Szeredi args.in_numargs = 2; 921d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 922d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 923d5b48543SMiklos Szeredi args.in_args[1].size = len; 924d5b48543SMiklos Szeredi args.in_args[1].value = link; 925fcee216bSMax Reitz return create_new_entry(fm, &args, dir, entry, S_IFLNK); 9269e6268dbSMiklos Szeredi } 9279e6268dbSMiklos Szeredi 9285c791fe1SMiklos Szeredi void fuse_flush_time_update(struct inode *inode) 9295c791fe1SMiklos Szeredi { 9305c791fe1SMiklos Szeredi int err = sync_inode_metadata(inode, 1); 9315c791fe1SMiklos Szeredi 9325c791fe1SMiklos Szeredi mapping_set_error(inode->i_mapping, err); 9335c791fe1SMiklos Szeredi } 9345c791fe1SMiklos Szeredi 93597f044f6SMiklos Szeredi static void fuse_update_ctime_in_cache(struct inode *inode) 93631f3267bSMaxim Patlasov { 93731f3267bSMaxim Patlasov if (!IS_NOCMTIME(inode)) { 938*ceb2d5e9SJeff Layton inode_set_ctime_current(inode); 93931f3267bSMaxim Patlasov mark_inode_dirty_sync(inode); 9405c791fe1SMiklos Szeredi fuse_flush_time_update(inode); 94131f3267bSMaxim Patlasov } 94231f3267bSMaxim Patlasov } 94331f3267bSMaxim Patlasov 94497f044f6SMiklos Szeredi void fuse_update_ctime(struct inode *inode) 94597f044f6SMiklos Szeredi { 946fa5eee57SMiklos Szeredi fuse_invalidate_attr_mask(inode, STATX_CTIME); 94797f044f6SMiklos Szeredi fuse_update_ctime_in_cache(inode); 94897f044f6SMiklos Szeredi } 94997f044f6SMiklos Szeredi 950cefd1b83SMiklos Szeredi static void fuse_entry_unlinked(struct dentry *entry) 951cefd1b83SMiklos Szeredi { 952cefd1b83SMiklos Szeredi struct inode *inode = d_inode(entry); 953cefd1b83SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 954cefd1b83SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 955cefd1b83SMiklos Szeredi 956cefd1b83SMiklos Szeredi spin_lock(&fi->lock); 957cefd1b83SMiklos Szeredi fi->attr_version = atomic64_inc_return(&fc->attr_version); 958cefd1b83SMiklos Szeredi /* 959cefd1b83SMiklos Szeredi * If i_nlink == 0 then unlink doesn't make sense, yet this can 960cefd1b83SMiklos Szeredi * happen if userspace filesystem is careless. It would be 961cefd1b83SMiklos Szeredi * difficult to enforce correct nlink usage so just ignore this 962cefd1b83SMiklos Szeredi * condition here 963cefd1b83SMiklos Szeredi */ 964cefd1b83SMiklos Szeredi if (S_ISDIR(inode->i_mode)) 965cefd1b83SMiklos Szeredi clear_nlink(inode); 966cefd1b83SMiklos Szeredi else if (inode->i_nlink > 0) 967cefd1b83SMiklos Szeredi drop_nlink(inode); 968cefd1b83SMiklos Szeredi spin_unlock(&fi->lock); 969cefd1b83SMiklos Szeredi fuse_invalidate_entry_cache(entry); 970cefd1b83SMiklos Szeredi fuse_update_ctime(inode); 971cefd1b83SMiklos Szeredi } 972cefd1b83SMiklos Szeredi 9739e6268dbSMiklos Szeredi static int fuse_unlink(struct inode *dir, struct dentry *entry) 9749e6268dbSMiklos Szeredi { 9759e6268dbSMiklos Szeredi int err; 976fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 9777078187aSMiklos Szeredi FUSE_ARGS(args); 9789e6268dbSMiklos Szeredi 9795d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 9805d069dbeSMiklos Szeredi return -EIO; 9815d069dbeSMiklos Szeredi 982d5b48543SMiklos Szeredi args.opcode = FUSE_UNLINK; 983d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 984d5b48543SMiklos Szeredi args.in_numargs = 1; 985d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 986d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 987fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 9889e6268dbSMiklos Szeredi if (!err) { 989261aaba7SMiklos Szeredi fuse_dir_changed(dir); 990cefd1b83SMiklos Szeredi fuse_entry_unlinked(entry); 9919e6268dbSMiklos Szeredi } else if (err == -EINTR) 9929e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 9939e6268dbSMiklos Szeredi return err; 9949e6268dbSMiklos Szeredi } 9959e6268dbSMiklos Szeredi 9969e6268dbSMiklos Szeredi static int fuse_rmdir(struct inode *dir, struct dentry *entry) 9979e6268dbSMiklos Szeredi { 9989e6268dbSMiklos Szeredi int err; 999fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(dir); 10007078187aSMiklos Szeredi FUSE_ARGS(args); 10019e6268dbSMiklos Szeredi 10025d069dbeSMiklos Szeredi if (fuse_is_bad(dir)) 10035d069dbeSMiklos Szeredi return -EIO; 10045d069dbeSMiklos Szeredi 1005d5b48543SMiklos Szeredi args.opcode = FUSE_RMDIR; 1006d5b48543SMiklos Szeredi args.nodeid = get_node_id(dir); 1007d5b48543SMiklos Szeredi args.in_numargs = 1; 1008d5b48543SMiklos Szeredi args.in_args[0].size = entry->d_name.len + 1; 1009d5b48543SMiklos Szeredi args.in_args[0].value = entry->d_name.name; 1010fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 10119e6268dbSMiklos Szeredi if (!err) { 1012261aaba7SMiklos Szeredi fuse_dir_changed(dir); 1013cefd1b83SMiklos Szeredi fuse_entry_unlinked(entry); 10149e6268dbSMiklos Szeredi } else if (err == -EINTR) 10159e6268dbSMiklos Szeredi fuse_invalidate_entry(entry); 10169e6268dbSMiklos Szeredi return err; 10179e6268dbSMiklos Szeredi } 10189e6268dbSMiklos Szeredi 10191560c974SMiklos Szeredi static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, 10201560c974SMiklos Szeredi struct inode *newdir, struct dentry *newent, 10211560c974SMiklos Szeredi unsigned int flags, int opcode, size_t argsize) 10229e6268dbSMiklos Szeredi { 10239e6268dbSMiklos Szeredi int err; 10241560c974SMiklos Szeredi struct fuse_rename2_in inarg; 1025fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(olddir); 10267078187aSMiklos Szeredi FUSE_ARGS(args); 10279e6268dbSMiklos Szeredi 10281560c974SMiklos Szeredi memset(&inarg, 0, argsize); 10299e6268dbSMiklos Szeredi inarg.newdir = get_node_id(newdir); 10301560c974SMiklos Szeredi inarg.flags = flags; 1031d5b48543SMiklos Szeredi args.opcode = opcode; 1032d5b48543SMiklos Szeredi args.nodeid = get_node_id(olddir); 1033d5b48543SMiklos Szeredi args.in_numargs = 3; 1034d5b48543SMiklos Szeredi args.in_args[0].size = argsize; 1035d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1036d5b48543SMiklos Szeredi args.in_args[1].size = oldent->d_name.len + 1; 1037d5b48543SMiklos Szeredi args.in_args[1].value = oldent->d_name.name; 1038d5b48543SMiklos Szeredi args.in_args[2].size = newent->d_name.len + 1; 1039d5b48543SMiklos Szeredi args.in_args[2].value = newent->d_name.name; 1040fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 10419e6268dbSMiklos Szeredi if (!err) { 104208b63307SMiklos Szeredi /* ctime changes */ 10432b0143b5SDavid Howells fuse_update_ctime(d_inode(oldent)); 104408b63307SMiklos Szeredi 1045371e8fd0SMiklos Szeredi if (flags & RENAME_EXCHANGE) 10462b0143b5SDavid Howells fuse_update_ctime(d_inode(newent)); 10471560c974SMiklos Szeredi 1048261aaba7SMiklos Szeredi fuse_dir_changed(olddir); 10499e6268dbSMiklos Szeredi if (olddir != newdir) 1050261aaba7SMiklos Szeredi fuse_dir_changed(newdir); 10518cbdf1e6SMiklos Szeredi 10528cbdf1e6SMiklos Szeredi /* newent will end up negative */ 1053cefd1b83SMiklos Szeredi if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) 1054cefd1b83SMiklos Szeredi fuse_entry_unlinked(newent); 10559e6268dbSMiklos Szeredi } else if (err == -EINTR) { 10569e6268dbSMiklos Szeredi /* If request was interrupted, DEITY only knows if the 10579e6268dbSMiklos Szeredi rename actually took place. If the invalidation 10589e6268dbSMiklos Szeredi fails (e.g. some process has CWD under the renamed 10599e6268dbSMiklos Szeredi directory), then there can be inconsistency between 10609e6268dbSMiklos Szeredi the dcache and the real filesystem. Tough luck. */ 10619e6268dbSMiklos Szeredi fuse_invalidate_entry(oldent); 10622b0143b5SDavid Howells if (d_really_is_positive(newent)) 10639e6268dbSMiklos Szeredi fuse_invalidate_entry(newent); 10649e6268dbSMiklos Szeredi } 10659e6268dbSMiklos Szeredi 10669e6268dbSMiklos Szeredi return err; 10679e6268dbSMiklos Szeredi } 10689e6268dbSMiklos Szeredi 1069e18275aeSChristian Brauner static int fuse_rename2(struct mnt_idmap *idmap, struct inode *olddir, 1070549c7297SChristian Brauner struct dentry *oldent, struct inode *newdir, 1071549c7297SChristian Brauner struct dentry *newent, unsigned int flags) 10721560c974SMiklos Szeredi { 10731560c974SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(olddir); 10741560c974SMiklos Szeredi int err; 10751560c974SMiklos Szeredi 10765d069dbeSMiklos Szeredi if (fuse_is_bad(olddir)) 10775d069dbeSMiklos Szeredi return -EIO; 10785d069dbeSMiklos Szeredi 1079519525faSVivek Goyal if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) 10801560c974SMiklos Szeredi return -EINVAL; 10811560c974SMiklos Szeredi 10824237ba43SMiklos Szeredi if (flags) { 10831560c974SMiklos Szeredi if (fc->no_rename2 || fc->minor < 23) 10841560c974SMiklos Szeredi return -EINVAL; 10851560c974SMiklos Szeredi 10861560c974SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, flags, 10874237ba43SMiklos Szeredi FUSE_RENAME2, 10884237ba43SMiklos Szeredi sizeof(struct fuse_rename2_in)); 10891560c974SMiklos Szeredi if (err == -ENOSYS) { 10901560c974SMiklos Szeredi fc->no_rename2 = 1; 10911560c974SMiklos Szeredi err = -EINVAL; 10921560c974SMiklos Szeredi } 10934237ba43SMiklos Szeredi } else { 10944237ba43SMiklos Szeredi err = fuse_rename_common(olddir, oldent, newdir, newent, 0, 10954237ba43SMiklos Szeredi FUSE_RENAME, 10964237ba43SMiklos Szeredi sizeof(struct fuse_rename_in)); 10974237ba43SMiklos Szeredi } 10981560c974SMiklos Szeredi 10994237ba43SMiklos Szeredi return err; 11004237ba43SMiklos Szeredi } 11014237ba43SMiklos Szeredi 11029e6268dbSMiklos Szeredi static int fuse_link(struct dentry *entry, struct inode *newdir, 11039e6268dbSMiklos Szeredi struct dentry *newent) 11049e6268dbSMiklos Szeredi { 11059e6268dbSMiklos Szeredi int err; 11069e6268dbSMiklos Szeredi struct fuse_link_in inarg; 11072b0143b5SDavid Howells struct inode *inode = d_inode(entry); 1108fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 11097078187aSMiklos Szeredi FUSE_ARGS(args); 11109e6268dbSMiklos Szeredi 11119e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 11129e6268dbSMiklos Szeredi inarg.oldnodeid = get_node_id(inode); 1113d5b48543SMiklos Szeredi args.opcode = FUSE_LINK; 1114d5b48543SMiklos Szeredi args.in_numargs = 2; 1115d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1116d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1117d5b48543SMiklos Szeredi args.in_args[1].size = newent->d_name.len + 1; 1118d5b48543SMiklos Szeredi args.in_args[1].value = newent->d_name.name; 1119fcee216bSMax Reitz err = create_new_entry(fm, &args, newdir, newent, inode->i_mode); 112097f044f6SMiklos Szeredi if (!err) 112197f044f6SMiklos Szeredi fuse_update_ctime_in_cache(inode); 112297f044f6SMiklos Szeredi else if (err == -EINTR) 1123ac45d613SMiklos Szeredi fuse_invalidate_attr(inode); 112497f044f6SMiklos Szeredi 11259e6268dbSMiklos Szeredi return err; 11269e6268dbSMiklos Szeredi } 11279e6268dbSMiklos Szeredi 11281fb69e78SMiklos Szeredi static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, 11291fb69e78SMiklos Szeredi struct kstat *stat) 11301fb69e78SMiklos Szeredi { 1131203627bbSMiklos Szeredi unsigned int blkbits; 11328373200bSPavel Emelyanov struct fuse_conn *fc = get_fuse_conn(inode); 11338373200bSPavel Emelyanov 11341fb69e78SMiklos Szeredi stat->dev = inode->i_sb->s_dev; 11351fb69e78SMiklos Szeredi stat->ino = attr->ino; 11361fb69e78SMiklos Szeredi stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 11371fb69e78SMiklos Szeredi stat->nlink = attr->nlink; 11388cb08329SEric W. Biederman stat->uid = make_kuid(fc->user_ns, attr->uid); 11398cb08329SEric W. Biederman stat->gid = make_kgid(fc->user_ns, attr->gid); 11401fb69e78SMiklos Szeredi stat->rdev = inode->i_rdev; 11411fb69e78SMiklos Szeredi stat->atime.tv_sec = attr->atime; 11421fb69e78SMiklos Szeredi stat->atime.tv_nsec = attr->atimensec; 11431fb69e78SMiklos Szeredi stat->mtime.tv_sec = attr->mtime; 11441fb69e78SMiklos Szeredi stat->mtime.tv_nsec = attr->mtimensec; 11451fb69e78SMiklos Szeredi stat->ctime.tv_sec = attr->ctime; 11461fb69e78SMiklos Szeredi stat->ctime.tv_nsec = attr->ctimensec; 11471fb69e78SMiklos Szeredi stat->size = attr->size; 11481fb69e78SMiklos Szeredi stat->blocks = attr->blocks; 1149203627bbSMiklos Szeredi 1150203627bbSMiklos Szeredi if (attr->blksize != 0) 1151203627bbSMiklos Szeredi blkbits = ilog2(attr->blksize); 1152203627bbSMiklos Szeredi else 1153203627bbSMiklos Szeredi blkbits = inode->i_sb->s_blocksize_bits; 1154203627bbSMiklos Szeredi 1155203627bbSMiklos Szeredi stat->blksize = 1 << blkbits; 11561fb69e78SMiklos Szeredi } 11571fb69e78SMiklos Szeredi 1158c79e322fSMiklos Szeredi static int fuse_do_getattr(struct inode *inode, struct kstat *stat, 1159c79e322fSMiklos Szeredi struct file *file) 1160e5e5558eSMiklos Szeredi { 1161e5e5558eSMiklos Szeredi int err; 1162c79e322fSMiklos Szeredi struct fuse_getattr_in inarg; 1163c79e322fSMiklos Szeredi struct fuse_attr_out outarg; 1164fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 11657078187aSMiklos Szeredi FUSE_ARGS(args); 11661fb69e78SMiklos Szeredi u64 attr_version; 11671fb69e78SMiklos Szeredi 1168fcee216bSMax Reitz attr_version = fuse_get_attr_version(fm->fc); 11691fb69e78SMiklos Szeredi 1170c79e322fSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 11710e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 1172c79e322fSMiklos Szeredi /* Directories have separate file-handle space */ 1173c79e322fSMiklos Szeredi if (file && S_ISREG(inode->i_mode)) { 1174c79e322fSMiklos Szeredi struct fuse_file *ff = file->private_data; 1175c79e322fSMiklos Szeredi 1176c79e322fSMiklos Szeredi inarg.getattr_flags |= FUSE_GETATTR_FH; 1177c79e322fSMiklos Szeredi inarg.fh = ff->fh; 1178c79e322fSMiklos Szeredi } 1179d5b48543SMiklos Szeredi args.opcode = FUSE_GETATTR; 1180d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1181d5b48543SMiklos Szeredi args.in_numargs = 1; 1182d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1183d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1184d5b48543SMiklos Szeredi args.out_numargs = 1; 1185d5b48543SMiklos Szeredi args.out_args[0].size = sizeof(outarg); 1186d5b48543SMiklos Szeredi args.out_args[0].value = &outarg; 1187fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1188e5e5558eSMiklos Szeredi if (!err) { 1189eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 11906e3e2c43SAl Viro inode_wrong_type(inode, outarg.attr.mode)) { 11915d069dbeSMiklos Szeredi fuse_make_bad(inode); 1192e5e5558eSMiklos Szeredi err = -EIO; 1193e5e5558eSMiklos Szeredi } else { 1194c79e322fSMiklos Szeredi fuse_change_attributes(inode, &outarg.attr, 1195c79e322fSMiklos Szeredi attr_timeout(&outarg), 11961fb69e78SMiklos Szeredi attr_version); 11971fb69e78SMiklos Szeredi if (stat) 1198c79e322fSMiklos Szeredi fuse_fillattr(inode, &outarg.attr, stat); 1199e5e5558eSMiklos Szeredi } 1200e5e5558eSMiklos Szeredi } 1201e5e5558eSMiklos Szeredi return err; 1202e5e5558eSMiklos Szeredi } 1203e5e5558eSMiklos Szeredi 12045b97eeacSMiklos Szeredi static int fuse_update_get_attr(struct inode *inode, struct file *file, 12052f1e8196SMiklos Szeredi struct kstat *stat, u32 request_mask, 12062f1e8196SMiklos Szeredi unsigned int flags) 1207bcb4be80SMiklos Szeredi { 1208bcb4be80SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 12095b97eeacSMiklos Szeredi int err = 0; 1210bf5c1898SMiklos Szeredi bool sync; 1211ec855375SMiklos Szeredi u32 inval_mask = READ_ONCE(fi->inval_mask); 1212ec855375SMiklos Szeredi u32 cache_mask = fuse_get_cache_mask(inode); 1213bcb4be80SMiklos Szeredi 1214bf5c1898SMiklos Szeredi if (flags & AT_STATX_FORCE_SYNC) 1215bf5c1898SMiklos Szeredi sync = true; 1216bf5c1898SMiklos Szeredi else if (flags & AT_STATX_DONT_SYNC) 1217bf5c1898SMiklos Szeredi sync = false; 1218ec855375SMiklos Szeredi else if (request_mask & inval_mask & ~cache_mask) 12192f1e8196SMiklos Szeredi sync = true; 1220bf5c1898SMiklos Szeredi else 1221bf5c1898SMiklos Szeredi sync = time_before64(fi->i_time, get_jiffies_64()); 1222bf5c1898SMiklos Szeredi 1223bf5c1898SMiklos Szeredi if (sync) { 122460bcc88aSSeth Forshee forget_all_cached_acls(inode); 1225bcb4be80SMiklos Szeredi err = fuse_do_getattr(inode, stat, file); 12265b97eeacSMiklos Szeredi } else if (stat) { 1227b74d24f7SChristian Brauner generic_fillattr(&nop_mnt_idmap, inode, stat); 1228bcb4be80SMiklos Szeredi stat->mode = fi->orig_i_mode; 122945c72cd7SPavel Shilovsky stat->ino = fi->orig_ino; 1230bcb4be80SMiklos Szeredi } 1231bcb4be80SMiklos Szeredi 1232bcb4be80SMiklos Szeredi return err; 1233bcb4be80SMiklos Szeredi } 1234bcb4be80SMiklos Szeredi 1235c6c745b8SMiklos Szeredi int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask) 12365b97eeacSMiklos Szeredi { 1237c6c745b8SMiklos Szeredi return fuse_update_get_attr(inode, file, NULL, mask, 0); 12385b97eeacSMiklos Szeredi } 12395b97eeacSMiklos Szeredi 1240fcee216bSMax Reitz int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, 12414f8d3702SMiklos Szeredi u64 child_nodeid, struct qstr *name, u32 flags) 12423b463ae0SJohn Muir { 12433b463ae0SJohn Muir int err = -ENOTDIR; 12443b463ae0SJohn Muir struct inode *parent; 12453b463ae0SJohn Muir struct dentry *dir; 12463b463ae0SJohn Muir struct dentry *entry; 12473b463ae0SJohn Muir 1248fcee216bSMax Reitz parent = fuse_ilookup(fc, parent_nodeid, NULL); 12493b463ae0SJohn Muir if (!parent) 12503b463ae0SJohn Muir return -ENOENT; 12513b463ae0SJohn Muir 1252bda9a719SMiklos Szeredi inode_lock_nested(parent, I_MUTEX_PARENT); 12533b463ae0SJohn Muir if (!S_ISDIR(parent->i_mode)) 12543b463ae0SJohn Muir goto unlock; 12553b463ae0SJohn Muir 12563b463ae0SJohn Muir err = -ENOENT; 12573b463ae0SJohn Muir dir = d_find_alias(parent); 12583b463ae0SJohn Muir if (!dir) 12593b463ae0SJohn Muir goto unlock; 12603b463ae0SJohn Muir 12618387ff25SLinus Torvalds name->hash = full_name_hash(dir, name->name, name->len); 12623b463ae0SJohn Muir entry = d_lookup(dir, name); 12633b463ae0SJohn Muir dput(dir); 12643b463ae0SJohn Muir if (!entry) 12653b463ae0SJohn Muir goto unlock; 12663b463ae0SJohn Muir 1267261aaba7SMiklos Szeredi fuse_dir_changed(parent); 12684f8d3702SMiklos Szeredi if (!(flags & FUSE_EXPIRE_ONLY)) 12694f8d3702SMiklos Szeredi d_invalidate(entry); 12704f8d3702SMiklos Szeredi fuse_invalidate_entry_cache(entry); 1271451d0f59SJohn Muir 12722b0143b5SDavid Howells if (child_nodeid != 0 && d_really_is_positive(entry)) { 12735955102cSAl Viro inode_lock(d_inode(entry)); 12742b0143b5SDavid Howells if (get_node_id(d_inode(entry)) != child_nodeid) { 1275451d0f59SJohn Muir err = -ENOENT; 1276451d0f59SJohn Muir goto badentry; 1277451d0f59SJohn Muir } 1278451d0f59SJohn Muir if (d_mountpoint(entry)) { 1279451d0f59SJohn Muir err = -EBUSY; 1280451d0f59SJohn Muir goto badentry; 1281451d0f59SJohn Muir } 1282e36cb0b8SDavid Howells if (d_is_dir(entry)) { 1283451d0f59SJohn Muir shrink_dcache_parent(entry); 1284451d0f59SJohn Muir if (!simple_empty(entry)) { 1285451d0f59SJohn Muir err = -ENOTEMPTY; 1286451d0f59SJohn Muir goto badentry; 1287451d0f59SJohn Muir } 12882b0143b5SDavid Howells d_inode(entry)->i_flags |= S_DEAD; 1289451d0f59SJohn Muir } 1290451d0f59SJohn Muir dont_mount(entry); 12912b0143b5SDavid Howells clear_nlink(d_inode(entry)); 12923b463ae0SJohn Muir err = 0; 1293451d0f59SJohn Muir badentry: 12945955102cSAl Viro inode_unlock(d_inode(entry)); 1295451d0f59SJohn Muir if (!err) 1296451d0f59SJohn Muir d_delete(entry); 1297451d0f59SJohn Muir } else { 1298451d0f59SJohn Muir err = 0; 1299451d0f59SJohn Muir } 1300451d0f59SJohn Muir dput(entry); 13013b463ae0SJohn Muir 13023b463ae0SJohn Muir unlock: 13035955102cSAl Viro inode_unlock(parent); 13043b463ae0SJohn Muir iput(parent); 13053b463ae0SJohn Muir return err; 13063b463ae0SJohn Muir } 13073b463ae0SJohn Muir 1308b1387777SDave Marchevsky static inline bool fuse_permissible_uidgid(struct fuse_conn *fc) 1309b1387777SDave Marchevsky { 1310b1387777SDave Marchevsky const struct cred *cred = current_cred(); 1311b1387777SDave Marchevsky 1312b1387777SDave Marchevsky return (uid_eq(cred->euid, fc->user_id) && 1313b1387777SDave Marchevsky uid_eq(cred->suid, fc->user_id) && 1314b1387777SDave Marchevsky uid_eq(cred->uid, fc->user_id) && 1315b1387777SDave Marchevsky gid_eq(cred->egid, fc->group_id) && 1316b1387777SDave Marchevsky gid_eq(cred->sgid, fc->group_id) && 1317b1387777SDave Marchevsky gid_eq(cred->gid, fc->group_id)); 1318b1387777SDave Marchevsky } 1319b1387777SDave Marchevsky 132087729a55SMiklos Szeredi /* 132187729a55SMiklos Szeredi * Calling into a user-controlled filesystem gives the filesystem 1322c2132c1bSAnatol Pomozov * daemon ptrace-like capabilities over the current process. This 132387729a55SMiklos Szeredi * means, that the filesystem daemon is able to record the exact 132487729a55SMiklos Szeredi * filesystem operations performed, and can also control the behavior 132587729a55SMiklos Szeredi * of the requester process in otherwise impossible ways. For example 132687729a55SMiklos Szeredi * it can delay the operation for arbitrary length of time allowing 132787729a55SMiklos Szeredi * DoS against the requester. 132887729a55SMiklos Szeredi * 132987729a55SMiklos Szeredi * For this reason only those processes can call into the filesystem, 133087729a55SMiklos Szeredi * for which the owner of the mount has ptrace privilege. This 133187729a55SMiklos Szeredi * excludes processes started by other users, suid or sgid processes. 133287729a55SMiklos Szeredi */ 1333b1387777SDave Marchevsky bool fuse_allow_current_process(struct fuse_conn *fc) 133487729a55SMiklos Szeredi { 1335b1387777SDave Marchevsky bool allow; 13369ccf47b2SDave Marchevsky 133729433a29SMiklos Szeredi if (fc->allow_other) 1338b1387777SDave Marchevsky allow = current_in_userns(fc->user_ns); 1339b1387777SDave Marchevsky else 1340b1387777SDave Marchevsky allow = fuse_permissible_uidgid(fc); 134187729a55SMiklos Szeredi 1342b1387777SDave Marchevsky if (!allow && allow_sys_admin_access && capable(CAP_SYS_ADMIN)) 1343b1387777SDave Marchevsky allow = true; 134487729a55SMiklos Szeredi 1345b1387777SDave Marchevsky return allow; 134687729a55SMiklos Szeredi } 134787729a55SMiklos Szeredi 134831d40d74SMiklos Szeredi static int fuse_access(struct inode *inode, int mask) 134931d40d74SMiklos Szeredi { 1350fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 13517078187aSMiklos Szeredi FUSE_ARGS(args); 135231d40d74SMiklos Szeredi struct fuse_access_in inarg; 135331d40d74SMiklos Szeredi int err; 135431d40d74SMiklos Szeredi 1355698fa1d1SMiklos Szeredi BUG_ON(mask & MAY_NOT_BLOCK); 1356698fa1d1SMiklos Szeredi 1357fcee216bSMax Reitz if (fm->fc->no_access) 135831d40d74SMiklos Szeredi return 0; 135931d40d74SMiklos Szeredi 136031d40d74SMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 1361e6305c43SAl Viro inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC); 1362d5b48543SMiklos Szeredi args.opcode = FUSE_ACCESS; 1363d5b48543SMiklos Szeredi args.nodeid = get_node_id(inode); 1364d5b48543SMiklos Szeredi args.in_numargs = 1; 1365d5b48543SMiklos Szeredi args.in_args[0].size = sizeof(inarg); 1366d5b48543SMiklos Szeredi args.in_args[0].value = &inarg; 1367fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 136831d40d74SMiklos Szeredi if (err == -ENOSYS) { 1369fcee216bSMax Reitz fm->fc->no_access = 1; 137031d40d74SMiklos Szeredi err = 0; 137131d40d74SMiklos Szeredi } 137231d40d74SMiklos Szeredi return err; 137331d40d74SMiklos Szeredi } 137431d40d74SMiklos Szeredi 137510556cb2SAl Viro static int fuse_perm_getattr(struct inode *inode, int mask) 137619690ddbSMiklos Szeredi { 137710556cb2SAl Viro if (mask & MAY_NOT_BLOCK) 137819690ddbSMiklos Szeredi return -ECHILD; 137919690ddbSMiklos Szeredi 138060bcc88aSSeth Forshee forget_all_cached_acls(inode); 138119690ddbSMiklos Szeredi return fuse_do_getattr(inode, NULL, NULL); 138219690ddbSMiklos Szeredi } 138319690ddbSMiklos Szeredi 13846f9f1180SMiklos Szeredi /* 13856f9f1180SMiklos Szeredi * Check permission. The two basic access models of FUSE are: 13866f9f1180SMiklos Szeredi * 13876f9f1180SMiklos Szeredi * 1) Local access checking ('default_permissions' mount option) based 13886f9f1180SMiklos Szeredi * on file mode. This is the plain old disk filesystem permission 13896f9f1180SMiklos Szeredi * modell. 13906f9f1180SMiklos Szeredi * 13916f9f1180SMiklos Szeredi * 2) "Remote" access checking, where server is responsible for 13926f9f1180SMiklos Szeredi * checking permission in each inode operation. An exception to this 13936f9f1180SMiklos Szeredi * is if ->permission() was invoked from sys_access() in which case an 13946f9f1180SMiklos Szeredi * access request is sent. Execute permission is still checked 13956f9f1180SMiklos Szeredi * locally based on file mode. 13966f9f1180SMiklos Szeredi */ 13974609e1f1SChristian Brauner static int fuse_permission(struct mnt_idmap *idmap, 1398549c7297SChristian Brauner struct inode *inode, int mask) 1399e5e5558eSMiklos Szeredi { 1400e5e5558eSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1401244f6385SMiklos Szeredi bool refreshed = false; 1402244f6385SMiklos Szeredi int err = 0; 1403e5e5558eSMiklos Szeredi 14045d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 14055d069dbeSMiklos Szeredi return -EIO; 14065d069dbeSMiklos Szeredi 1407c2132c1bSAnatol Pomozov if (!fuse_allow_current_process(fc)) 1408e5e5558eSMiklos Szeredi return -EACCES; 1409244f6385SMiklos Szeredi 1410244f6385SMiklos Szeredi /* 1411e8e96157SMiklos Szeredi * If attributes are needed, refresh them before proceeding 1412244f6385SMiklos Szeredi */ 141329433a29SMiklos Szeredi if (fc->default_permissions || 1414e8e96157SMiklos Szeredi ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 141519690ddbSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 1416d233c7ddSMiklos Szeredi u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID; 141719690ddbSMiklos Szeredi 1418d233c7ddSMiklos Szeredi if (perm_mask & READ_ONCE(fi->inval_mask) || 1419d233c7ddSMiklos Szeredi time_before64(fi->i_time, get_jiffies_64())) { 142019690ddbSMiklos Szeredi refreshed = true; 142119690ddbSMiklos Szeredi 142210556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1423244f6385SMiklos Szeredi if (err) 1424244f6385SMiklos Szeredi return err; 14251fb69e78SMiklos Szeredi } 142619690ddbSMiklos Szeredi } 1427244f6385SMiklos Szeredi 142829433a29SMiklos Szeredi if (fc->default_permissions) { 14294609e1f1SChristian Brauner err = generic_permission(&nop_mnt_idmap, inode, mask); 14301e9a4ed9SMiklos Szeredi 14311e9a4ed9SMiklos Szeredi /* If permission is denied, try to refresh file 14321e9a4ed9SMiklos Szeredi attributes. This is also needed, because the root 14331e9a4ed9SMiklos Szeredi node will at first have no permissions */ 1434244f6385SMiklos Szeredi if (err == -EACCES && !refreshed) { 143510556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 14361e9a4ed9SMiklos Szeredi if (!err) 14374609e1f1SChristian Brauner err = generic_permission(&nop_mnt_idmap, 143847291baaSChristian Brauner inode, mask); 14391e9a4ed9SMiklos Szeredi } 14401e9a4ed9SMiklos Szeredi 14416f9f1180SMiklos Szeredi /* Note: the opposite of the above test does not 14426f9f1180SMiklos Szeredi exist. So if permissions are revoked this won't be 14436f9f1180SMiklos Szeredi noticed immediately, only after the attribute 14446f9f1180SMiklos Szeredi timeout has expired */ 14459cfcac81SEric Paris } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { 1446e8e96157SMiklos Szeredi err = fuse_access(inode, mask); 1447e8e96157SMiklos Szeredi } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { 1448e8e96157SMiklos Szeredi if (!(inode->i_mode & S_IXUGO)) { 1449e8e96157SMiklos Szeredi if (refreshed) 1450e5e5558eSMiklos Szeredi return -EACCES; 145131d40d74SMiklos Szeredi 145210556cb2SAl Viro err = fuse_perm_getattr(inode, mask); 1453e8e96157SMiklos Szeredi if (!err && !(inode->i_mode & S_IXUGO)) 1454e8e96157SMiklos Szeredi return -EACCES; 1455e8e96157SMiklos Szeredi } 1456e5e5558eSMiklos Szeredi } 1457244f6385SMiklos Szeredi return err; 1458e5e5558eSMiklos Szeredi } 1459e5e5558eSMiklos Szeredi 14605571f1e6SDan Schatzberg static int fuse_readlink_page(struct inode *inode, struct page *page) 1461e5e5558eSMiklos Szeredi { 1462fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 14634c29afecSMiklos Szeredi struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 }; 14644c29afecSMiklos Szeredi struct fuse_args_pages ap = { 14654c29afecSMiklos Szeredi .num_pages = 1, 14664c29afecSMiklos Szeredi .pages = &page, 14674c29afecSMiklos Szeredi .descs = &desc, 14684c29afecSMiklos Szeredi }; 14694c29afecSMiklos Szeredi char *link; 14704c29afecSMiklos Szeredi ssize_t res; 1471e5e5558eSMiklos Szeredi 14724c29afecSMiklos Szeredi ap.args.opcode = FUSE_READLINK; 14734c29afecSMiklos Szeredi ap.args.nodeid = get_node_id(inode); 14744c29afecSMiklos Szeredi ap.args.out_pages = true; 14754c29afecSMiklos Szeredi ap.args.out_argvar = true; 14764c29afecSMiklos Szeredi ap.args.page_zeroing = true; 14774c29afecSMiklos Szeredi ap.args.out_numargs = 1; 14784c29afecSMiklos Szeredi ap.args.out_args[0].size = desc.length; 1479fcee216bSMax Reitz res = fuse_simple_request(fm, &ap.args); 14806b255391SAl Viro 1481451418fcSAndrew Gallagher fuse_invalidate_atime(inode); 14825571f1e6SDan Schatzberg 14834c29afecSMiklos Szeredi if (res < 0) 14844c29afecSMiklos Szeredi return res; 14854c29afecSMiklos Szeredi 14864c29afecSMiklos Szeredi if (WARN_ON(res >= PAGE_SIZE)) 14874c29afecSMiklos Szeredi return -EIO; 14884c29afecSMiklos Szeredi 14894c29afecSMiklos Szeredi link = page_address(page); 14904c29afecSMiklos Szeredi link[res] = '\0'; 14914c29afecSMiklos Szeredi 14924c29afecSMiklos Szeredi return 0; 14935571f1e6SDan Schatzberg } 14945571f1e6SDan Schatzberg 14955571f1e6SDan Schatzberg static const char *fuse_get_link(struct dentry *dentry, struct inode *inode, 14965571f1e6SDan Schatzberg struct delayed_call *callback) 14975571f1e6SDan Schatzberg { 14985571f1e6SDan Schatzberg struct fuse_conn *fc = get_fuse_conn(inode); 14995571f1e6SDan Schatzberg struct page *page; 15005571f1e6SDan Schatzberg int err; 15015571f1e6SDan Schatzberg 15025571f1e6SDan Schatzberg err = -EIO; 15035d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 15045571f1e6SDan Schatzberg goto out_err; 15055571f1e6SDan Schatzberg 15065571f1e6SDan Schatzberg if (fc->cache_symlinks) 15075571f1e6SDan Schatzberg return page_get_link(dentry, inode, callback); 15085571f1e6SDan Schatzberg 15095571f1e6SDan Schatzberg err = -ECHILD; 15105571f1e6SDan Schatzberg if (!dentry) 15115571f1e6SDan Schatzberg goto out_err; 15125571f1e6SDan Schatzberg 15135571f1e6SDan Schatzberg page = alloc_page(GFP_KERNEL); 15145571f1e6SDan Schatzberg err = -ENOMEM; 15155571f1e6SDan Schatzberg if (!page) 15165571f1e6SDan Schatzberg goto out_err; 15175571f1e6SDan Schatzberg 15185571f1e6SDan Schatzberg err = fuse_readlink_page(inode, page); 15195571f1e6SDan Schatzberg if (err) { 15205571f1e6SDan Schatzberg __free_page(page); 15215571f1e6SDan Schatzberg goto out_err; 15225571f1e6SDan Schatzberg } 15235571f1e6SDan Schatzberg 15245571f1e6SDan Schatzberg set_delayed_call(callback, page_put_link, page); 15255571f1e6SDan Schatzberg 15265571f1e6SDan Schatzberg return page_address(page); 15275571f1e6SDan Schatzberg 15285571f1e6SDan Schatzberg out_err: 15295571f1e6SDan Schatzberg return ERR_PTR(err); 1530e5e5558eSMiklos Szeredi } 1531e5e5558eSMiklos Szeredi 1532e5e5558eSMiklos Szeredi static int fuse_dir_open(struct inode *inode, struct file *file) 1533e5e5558eSMiklos Szeredi { 153491fe96b4SMiklos Szeredi return fuse_open_common(inode, file, true); 1535e5e5558eSMiklos Szeredi } 1536e5e5558eSMiklos Szeredi 1537e5e5558eSMiklos Szeredi static int fuse_dir_release(struct inode *inode, struct file *file) 1538e5e5558eSMiklos Szeredi { 15392e64ff15SChad Austin fuse_release_common(file, true); 15408b0797a4SMiklos Szeredi 15418b0797a4SMiklos Szeredi return 0; 1542e5e5558eSMiklos Szeredi } 1543e5e5558eSMiklos Szeredi 154402c24a82SJosef Bacik static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end, 154502c24a82SJosef Bacik int datasync) 154682547981SMiklos Szeredi { 1547a9c2d1e8SMiklos Szeredi struct inode *inode = file->f_mapping->host; 1548a9c2d1e8SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1549a9c2d1e8SMiklos Szeredi int err; 1550a9c2d1e8SMiklos Szeredi 15515d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 1552a9c2d1e8SMiklos Szeredi return -EIO; 1553a9c2d1e8SMiklos Szeredi 1554a9c2d1e8SMiklos Szeredi if (fc->no_fsyncdir) 1555a9c2d1e8SMiklos Szeredi return 0; 1556a9c2d1e8SMiklos Szeredi 1557a9c2d1e8SMiklos Szeredi inode_lock(inode); 1558a9c2d1e8SMiklos Szeredi err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR); 1559a9c2d1e8SMiklos Szeredi if (err == -ENOSYS) { 1560a9c2d1e8SMiklos Szeredi fc->no_fsyncdir = 1; 1561a9c2d1e8SMiklos Szeredi err = 0; 1562a9c2d1e8SMiklos Szeredi } 1563a9c2d1e8SMiklos Szeredi inode_unlock(inode); 1564a9c2d1e8SMiklos Szeredi 1565a9c2d1e8SMiklos Szeredi return err; 156682547981SMiklos Szeredi } 156782547981SMiklos Szeredi 1568b18da0c5SMiklos Szeredi static long fuse_dir_ioctl(struct file *file, unsigned int cmd, 1569b18da0c5SMiklos Szeredi unsigned long arg) 1570b18da0c5SMiklos Szeredi { 1571b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1572b18da0c5SMiklos Szeredi 1573b18da0c5SMiklos Szeredi /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */ 1574b18da0c5SMiklos Szeredi if (fc->minor < 18) 1575b18da0c5SMiklos Szeredi return -ENOTTY; 1576b18da0c5SMiklos Szeredi 1577b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR); 1578b18da0c5SMiklos Szeredi } 1579b18da0c5SMiklos Szeredi 1580b18da0c5SMiklos Szeredi static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd, 1581b18da0c5SMiklos Szeredi unsigned long arg) 1582b18da0c5SMiklos Szeredi { 1583b18da0c5SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host); 1584b18da0c5SMiklos Szeredi 1585b18da0c5SMiklos Szeredi if (fc->minor < 18) 1586b18da0c5SMiklos Szeredi return -ENOTTY; 1587b18da0c5SMiklos Szeredi 1588b18da0c5SMiklos Szeredi return fuse_ioctl_common(file, cmd, arg, 1589b18da0c5SMiklos Szeredi FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR); 1590b18da0c5SMiklos Szeredi } 1591b18da0c5SMiklos Szeredi 1592b0aa7606SMaxim Patlasov static bool update_mtime(unsigned ivalid, bool trust_local_mtime) 159317637cbaSMiklos Szeredi { 159417637cbaSMiklos Szeredi /* Always update if mtime is explicitly set */ 159517637cbaSMiklos Szeredi if (ivalid & ATTR_MTIME_SET) 159617637cbaSMiklos Szeredi return true; 159717637cbaSMiklos Szeredi 1598b0aa7606SMaxim Patlasov /* Or if kernel i_mtime is the official one */ 1599b0aa7606SMaxim Patlasov if (trust_local_mtime) 1600b0aa7606SMaxim Patlasov return true; 1601b0aa7606SMaxim Patlasov 160217637cbaSMiklos Szeredi /* If it's an open(O_TRUNC) or an ftruncate(), don't update */ 160317637cbaSMiklos Szeredi if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE))) 160417637cbaSMiklos Szeredi return false; 160517637cbaSMiklos Szeredi 160617637cbaSMiklos Szeredi /* In all other cases update */ 160717637cbaSMiklos Szeredi return true; 160817637cbaSMiklos Szeredi } 160917637cbaSMiklos Szeredi 16108cb08329SEric W. Biederman static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, 16118cb08329SEric W. Biederman struct fuse_setattr_in *arg, bool trust_local_cmtime) 16129e6268dbSMiklos Szeredi { 16139e6268dbSMiklos Szeredi unsigned ivalid = iattr->ia_valid; 16149e6268dbSMiklos Szeredi 16159e6268dbSMiklos Szeredi if (ivalid & ATTR_MODE) 1616befc649cSMiklos Szeredi arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; 16179e6268dbSMiklos Szeredi if (ivalid & ATTR_UID) 16188cb08329SEric W. Biederman arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); 16199e6268dbSMiklos Szeredi if (ivalid & ATTR_GID) 16208cb08329SEric W. Biederman arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); 16219e6268dbSMiklos Szeredi if (ivalid & ATTR_SIZE) 1622befc649cSMiklos Szeredi arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; 162317637cbaSMiklos Szeredi if (ivalid & ATTR_ATIME) { 162417637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME; 1625befc649cSMiklos Szeredi arg->atime = iattr->ia_atime.tv_sec; 162617637cbaSMiklos Szeredi arg->atimensec = iattr->ia_atime.tv_nsec; 162717637cbaSMiklos Szeredi if (!(ivalid & ATTR_ATIME_SET)) 162817637cbaSMiklos Szeredi arg->valid |= FATTR_ATIME_NOW; 162917637cbaSMiklos Szeredi } 16303ad22c62SMaxim Patlasov if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) { 163117637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME; 1632befc649cSMiklos Szeredi arg->mtime = iattr->ia_mtime.tv_sec; 163317637cbaSMiklos Szeredi arg->mtimensec = iattr->ia_mtime.tv_nsec; 16343ad22c62SMaxim Patlasov if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime) 163517637cbaSMiklos Szeredi arg->valid |= FATTR_MTIME_NOW; 16369e6268dbSMiklos Szeredi } 16373ad22c62SMaxim Patlasov if ((ivalid & ATTR_CTIME) && trust_local_cmtime) { 16383ad22c62SMaxim Patlasov arg->valid |= FATTR_CTIME; 16393ad22c62SMaxim Patlasov arg->ctime = iattr->ia_ctime.tv_sec; 16403ad22c62SMaxim Patlasov arg->ctimensec = iattr->ia_ctime.tv_nsec; 16413ad22c62SMaxim Patlasov } 16429e6268dbSMiklos Szeredi } 16439e6268dbSMiklos Szeredi 16446f9f1180SMiklos Szeredi /* 16453be5a52bSMiklos Szeredi * Prevent concurrent writepages on inode 16463be5a52bSMiklos Szeredi * 16473be5a52bSMiklos Szeredi * This is done by adding a negative bias to the inode write counter 16483be5a52bSMiklos Szeredi * and waiting for all pending writes to finish. 16493be5a52bSMiklos Szeredi */ 16503be5a52bSMiklos Szeredi void fuse_set_nowrite(struct inode *inode) 16513be5a52bSMiklos Szeredi { 16523be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 16533be5a52bSMiklos Szeredi 16545955102cSAl Viro BUG_ON(!inode_is_locked(inode)); 16553be5a52bSMiklos Szeredi 1656f15ecfefSKirill Tkhai spin_lock(&fi->lock); 16573be5a52bSMiklos Szeredi BUG_ON(fi->writectr < 0); 16583be5a52bSMiklos Szeredi fi->writectr += FUSE_NOWRITE; 1659f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 16603be5a52bSMiklos Szeredi wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE); 16613be5a52bSMiklos Szeredi } 16623be5a52bSMiklos Szeredi 16633be5a52bSMiklos Szeredi /* 16643be5a52bSMiklos Szeredi * Allow writepages on inode 16653be5a52bSMiklos Szeredi * 16663be5a52bSMiklos Szeredi * Remove the bias from the writecounter and send any queued 16673be5a52bSMiklos Szeredi * writepages. 16683be5a52bSMiklos Szeredi */ 16693be5a52bSMiklos Szeredi static void __fuse_release_nowrite(struct inode *inode) 16703be5a52bSMiklos Szeredi { 16713be5a52bSMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 16723be5a52bSMiklos Szeredi 16733be5a52bSMiklos Szeredi BUG_ON(fi->writectr != FUSE_NOWRITE); 16743be5a52bSMiklos Szeredi fi->writectr = 0; 16753be5a52bSMiklos Szeredi fuse_flush_writepages(inode); 16763be5a52bSMiklos Szeredi } 16773be5a52bSMiklos Szeredi 16783be5a52bSMiklos Szeredi void fuse_release_nowrite(struct inode *inode) 16793be5a52bSMiklos Szeredi { 1680f15ecfefSKirill Tkhai struct fuse_inode *fi = get_fuse_inode(inode); 16813be5a52bSMiklos Szeredi 1682f15ecfefSKirill Tkhai spin_lock(&fi->lock); 16833be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 1684f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 16853be5a52bSMiklos Szeredi } 16863be5a52bSMiklos Szeredi 16877078187aSMiklos Szeredi static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args, 1688b0aa7606SMaxim Patlasov struct inode *inode, 1689b0aa7606SMaxim Patlasov struct fuse_setattr_in *inarg_p, 1690b0aa7606SMaxim Patlasov struct fuse_attr_out *outarg_p) 1691b0aa7606SMaxim Patlasov { 1692d5b48543SMiklos Szeredi args->opcode = FUSE_SETATTR; 1693d5b48543SMiklos Szeredi args->nodeid = get_node_id(inode); 1694d5b48543SMiklos Szeredi args->in_numargs = 1; 1695d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(*inarg_p); 1696d5b48543SMiklos Szeredi args->in_args[0].value = inarg_p; 1697d5b48543SMiklos Szeredi args->out_numargs = 1; 1698d5b48543SMiklos Szeredi args->out_args[0].size = sizeof(*outarg_p); 1699d5b48543SMiklos Szeredi args->out_args[0].value = outarg_p; 1700b0aa7606SMaxim Patlasov } 1701b0aa7606SMaxim Patlasov 1702b0aa7606SMaxim Patlasov /* 1703b0aa7606SMaxim Patlasov * Flush inode->i_mtime to the server 1704b0aa7606SMaxim Patlasov */ 1705ab9e13f7SMaxim Patlasov int fuse_flush_times(struct inode *inode, struct fuse_file *ff) 1706b0aa7606SMaxim Patlasov { 1707fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 17087078187aSMiklos Szeredi FUSE_ARGS(args); 1709b0aa7606SMaxim Patlasov struct fuse_setattr_in inarg; 1710b0aa7606SMaxim Patlasov struct fuse_attr_out outarg; 1711b0aa7606SMaxim Patlasov 1712b0aa7606SMaxim Patlasov memset(&inarg, 0, sizeof(inarg)); 1713b0aa7606SMaxim Patlasov memset(&outarg, 0, sizeof(outarg)); 1714b0aa7606SMaxim Patlasov 1715ab9e13f7SMaxim Patlasov inarg.valid = FATTR_MTIME; 1716b0aa7606SMaxim Patlasov inarg.mtime = inode->i_mtime.tv_sec; 1717b0aa7606SMaxim Patlasov inarg.mtimensec = inode->i_mtime.tv_nsec; 1718fcee216bSMax Reitz if (fm->fc->minor >= 23) { 1719ab9e13f7SMaxim Patlasov inarg.valid |= FATTR_CTIME; 1720*ceb2d5e9SJeff Layton inarg.ctime = inode_get_ctime(inode).tv_sec; 1721*ceb2d5e9SJeff Layton inarg.ctimensec = inode_get_ctime(inode).tv_nsec; 1722ab9e13f7SMaxim Patlasov } 17231e18bda8SMiklos Szeredi if (ff) { 17241e18bda8SMiklos Szeredi inarg.valid |= FATTR_FH; 17251e18bda8SMiklos Szeredi inarg.fh = ff->fh; 17261e18bda8SMiklos Szeredi } 1727fcee216bSMax Reitz fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg); 1728b0aa7606SMaxim Patlasov 1729fcee216bSMax Reitz return fuse_simple_request(fm, &args); 1730b0aa7606SMaxim Patlasov } 1731b0aa7606SMaxim Patlasov 17323be5a52bSMiklos Szeredi /* 17336f9f1180SMiklos Szeredi * Set attributes, and at the same time refresh them. 17346f9f1180SMiklos Szeredi * 17356f9f1180SMiklos Szeredi * Truncation is slightly complicated, because the 'truncate' request 17366f9f1180SMiklos Szeredi * may fail, in which case we don't want to touch the mapping. 17379ffbb916SMiklos Szeredi * vmtruncate() doesn't allow for this case, so do the rlimit checking 17389ffbb916SMiklos Szeredi * and the actual truncation by hand. 17396f9f1180SMiklos Szeredi */ 174062490330SJan Kara int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, 174149d4914fSMiklos Szeredi struct file *file) 17429e6268dbSMiklos Szeredi { 174362490330SJan Kara struct inode *inode = d_inode(dentry); 1744fcee216bSMax Reitz struct fuse_mount *fm = get_fuse_mount(inode); 1745fcee216bSMax Reitz struct fuse_conn *fc = fm->fc; 174606a7c3c2SMaxim Patlasov struct fuse_inode *fi = get_fuse_inode(inode); 17478bcbbe9cSJan Kara struct address_space *mapping = inode->i_mapping; 17487078187aSMiklos Szeredi FUSE_ARGS(args); 17499e6268dbSMiklos Szeredi struct fuse_setattr_in inarg; 17509e6268dbSMiklos Szeredi struct fuse_attr_out outarg; 17513be5a52bSMiklos Szeredi bool is_truncate = false; 1752c15016b7SMiklos Szeredi bool is_wb = fc->writeback_cache && S_ISREG(inode->i_mode); 17533be5a52bSMiklos Szeredi loff_t oldsize; 17549e6268dbSMiklos Szeredi int err; 1755c15016b7SMiklos Szeredi bool trust_local_cmtime = is_wb; 17566ae330caSVivek Goyal bool fault_blocked = false; 17579e6268dbSMiklos Szeredi 175829433a29SMiklos Szeredi if (!fc->default_permissions) 1759db78b877SChristoph Hellwig attr->ia_valid |= ATTR_FORCE; 1760db78b877SChristoph Hellwig 1761c1632a0fSChristian Brauner err = setattr_prepare(&nop_mnt_idmap, dentry, attr); 17621e9a4ed9SMiklos Szeredi if (err) 17631e9a4ed9SMiklos Szeredi return err; 17641e9a4ed9SMiklos Szeredi 17656ae330caSVivek Goyal if (attr->ia_valid & ATTR_SIZE) { 17666ae330caSVivek Goyal if (WARN_ON(!S_ISREG(inode->i_mode))) 17676ae330caSVivek Goyal return -EIO; 17686ae330caSVivek Goyal is_truncate = true; 17696ae330caSVivek Goyal } 17706ae330caSVivek Goyal 17716ae330caSVivek Goyal if (FUSE_IS_DAX(inode) && is_truncate) { 17728bcbbe9cSJan Kara filemap_invalidate_lock(mapping); 17736ae330caSVivek Goyal fault_blocked = true; 17746ae330caSVivek Goyal err = fuse_dax_break_layouts(inode, 0, 0); 17756ae330caSVivek Goyal if (err) { 17768bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 17776ae330caSVivek Goyal return err; 17786ae330caSVivek Goyal } 17796ae330caSVivek Goyal } 17806ae330caSVivek Goyal 17818d56adddSMiklos Szeredi if (attr->ia_valid & ATTR_OPEN) { 1782df0e91d4SMiklos Szeredi /* This is coming from open(..., ... | O_TRUNC); */ 1783df0e91d4SMiklos Szeredi WARN_ON(!(attr->ia_valid & ATTR_SIZE)); 1784df0e91d4SMiklos Szeredi WARN_ON(attr->ia_size != 0); 1785df0e91d4SMiklos Szeredi if (fc->atomic_o_trunc) { 1786df0e91d4SMiklos Szeredi /* 1787df0e91d4SMiklos Szeredi * No need to send request to userspace, since actual 1788df0e91d4SMiklos Szeredi * truncation has already been done by OPEN. But still 1789df0e91d4SMiklos Szeredi * need to truncate page cache. 1790df0e91d4SMiklos Szeredi */ 1791df0e91d4SMiklos Szeredi i_size_write(inode, 0); 1792df0e91d4SMiklos Szeredi truncate_pagecache(inode, 0); 17936ae330caSVivek Goyal goto out; 1794df0e91d4SMiklos Szeredi } 17958d56adddSMiklos Szeredi file = NULL; 17968d56adddSMiklos Szeredi } 17976ff958edSMiklos Szeredi 1798b24e7598SMiklos Szeredi /* Flush dirty data/metadata before non-truncate SETATTR */ 1799c15016b7SMiklos Szeredi if (is_wb && 1800b24e7598SMiklos Szeredi attr->ia_valid & 1801b24e7598SMiklos Szeredi (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | 1802b24e7598SMiklos Szeredi ATTR_TIMES_SET)) { 1803b24e7598SMiklos Szeredi err = write_inode_now(inode, true); 1804b24e7598SMiklos Szeredi if (err) 1805b24e7598SMiklos Szeredi return err; 1806b24e7598SMiklos Szeredi 1807b24e7598SMiklos Szeredi fuse_set_nowrite(inode); 1808b24e7598SMiklos Szeredi fuse_release_nowrite(inode); 1809b24e7598SMiklos Szeredi } 1810b24e7598SMiklos Szeredi 181106a7c3c2SMaxim Patlasov if (is_truncate) { 18123be5a52bSMiklos Szeredi fuse_set_nowrite(inode); 181306a7c3c2SMaxim Patlasov set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 18143ad22c62SMaxim Patlasov if (trust_local_cmtime && attr->ia_size != inode->i_size) 18153ad22c62SMaxim Patlasov attr->ia_valid |= ATTR_MTIME | ATTR_CTIME; 181606a7c3c2SMaxim Patlasov } 18173be5a52bSMiklos Szeredi 18189e6268dbSMiklos Szeredi memset(&inarg, 0, sizeof(inarg)); 18190e9663eeSMiklos Szeredi memset(&outarg, 0, sizeof(outarg)); 18208cb08329SEric W. Biederman iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); 182149d4914fSMiklos Szeredi if (file) { 182249d4914fSMiklos Szeredi struct fuse_file *ff = file->private_data; 182349d4914fSMiklos Szeredi inarg.valid |= FATTR_FH; 182449d4914fSMiklos Szeredi inarg.fh = ff->fh; 182549d4914fSMiklos Szeredi } 182631792161SVivek Goyal 182731792161SVivek Goyal /* Kill suid/sgid for non-directory chown unconditionally */ 182831792161SVivek Goyal if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) && 182931792161SVivek Goyal attr->ia_valid & (ATTR_UID | ATTR_GID)) 183031792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 183131792161SVivek Goyal 1832f3332114SMiklos Szeredi if (attr->ia_valid & ATTR_SIZE) { 1833f3332114SMiklos Szeredi /* For mandatory locking in truncate */ 1834f3332114SMiklos Szeredi inarg.valid |= FATTR_LOCKOWNER; 1835f3332114SMiklos Szeredi inarg.lock_owner = fuse_lock_owner_id(fc, current->files); 183631792161SVivek Goyal 183731792161SVivek Goyal /* Kill suid/sgid for truncate only if no CAP_FSETID */ 183831792161SVivek Goyal if (fc->handle_killpriv_v2 && !capable(CAP_FSETID)) 183931792161SVivek Goyal inarg.valid |= FATTR_KILL_SUIDGID; 1840f3332114SMiklos Szeredi } 18417078187aSMiklos Szeredi fuse_setattr_fill(fc, &args, inode, &inarg, &outarg); 1842fcee216bSMax Reitz err = fuse_simple_request(fm, &args); 1843e00d2c2dSMiklos Szeredi if (err) { 1844e00d2c2dSMiklos Szeredi if (err == -EINTR) 1845e00d2c2dSMiklos Szeredi fuse_invalidate_attr(inode); 18463be5a52bSMiklos Szeredi goto error; 1847e00d2c2dSMiklos Szeredi } 1848e00d2c2dSMiklos Szeredi 1849eb59bd17SMiklos Szeredi if (fuse_invalid_attr(&outarg.attr) || 18506e3e2c43SAl Viro inode_wrong_type(inode, outarg.attr.mode)) { 18515d069dbeSMiklos Szeredi fuse_make_bad(inode); 18523be5a52bSMiklos Szeredi err = -EIO; 18533be5a52bSMiklos Szeredi goto error; 18549e6268dbSMiklos Szeredi } 18559e6268dbSMiklos Szeredi 1856f15ecfefSKirill Tkhai spin_lock(&fi->lock); 1857b0aa7606SMaxim Patlasov /* the kernel maintains i_mtime locally */ 18583ad22c62SMaxim Patlasov if (trust_local_cmtime) { 18593ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_MTIME) 1860b0aa7606SMaxim Patlasov inode->i_mtime = attr->ia_mtime; 18613ad22c62SMaxim Patlasov if (attr->ia_valid & ATTR_CTIME) 1862*ceb2d5e9SJeff Layton inode_set_ctime_to_ts(inode, attr->ia_ctime); 18631e18bda8SMiklos Szeredi /* FIXME: clear I_DIRTY_SYNC? */ 1864b0aa7606SMaxim Patlasov } 1865b0aa7606SMaxim Patlasov 18663be5a52bSMiklos Szeredi fuse_change_attributes_common(inode, &outarg.attr, 18674b52f059SMiklos Szeredi attr_timeout(&outarg), 18684b52f059SMiklos Szeredi fuse_get_cache_mask(inode)); 18693be5a52bSMiklos Szeredi oldsize = inode->i_size; 18708373200bSPavel Emelyanov /* see the comment in fuse_change_attributes() */ 1871c15016b7SMiklos Szeredi if (!is_wb || is_truncate) 18723be5a52bSMiklos Szeredi i_size_write(inode, outarg.attr.size); 18733be5a52bSMiklos Szeredi 18743be5a52bSMiklos Szeredi if (is_truncate) { 1875f15ecfefSKirill Tkhai /* NOTE: this may release/reacquire fi->lock */ 18763be5a52bSMiklos Szeredi __fuse_release_nowrite(inode); 18773be5a52bSMiklos Szeredi } 1878f15ecfefSKirill Tkhai spin_unlock(&fi->lock); 18793be5a52bSMiklos Szeredi 18803be5a52bSMiklos Szeredi /* 18813be5a52bSMiklos Szeredi * Only call invalidate_inode_pages2() after removing 18822bf06b8eSMatthew Wilcox (Oracle) * FUSE_NOWRITE, otherwise fuse_launder_folio() would deadlock. 18833be5a52bSMiklos Szeredi */ 18848373200bSPavel Emelyanov if ((is_truncate || !is_wb) && 18858373200bSPavel Emelyanov S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) { 18867caef267SKirill A. Shutemov truncate_pagecache(inode, outarg.attr.size); 18878bcbbe9cSJan Kara invalidate_inode_pages2(mapping); 18883be5a52bSMiklos Szeredi } 18893be5a52bSMiklos Szeredi 189006a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 18916ae330caSVivek Goyal out: 18926ae330caSVivek Goyal if (fault_blocked) 18938bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 18946ae330caSVivek Goyal 1895e00d2c2dSMiklos Szeredi return 0; 18963be5a52bSMiklos Szeredi 18973be5a52bSMiklos Szeredi error: 18983be5a52bSMiklos Szeredi if (is_truncate) 18993be5a52bSMiklos Szeredi fuse_release_nowrite(inode); 19003be5a52bSMiklos Szeredi 190106a7c3c2SMaxim Patlasov clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state); 19026ae330caSVivek Goyal 19036ae330caSVivek Goyal if (fault_blocked) 19048bcbbe9cSJan Kara filemap_invalidate_unlock(mapping); 19053be5a52bSMiklos Szeredi return err; 19069e6268dbSMiklos Szeredi } 19079e6268dbSMiklos Szeredi 1908c1632a0fSChristian Brauner static int fuse_setattr(struct mnt_idmap *idmap, struct dentry *entry, 1909549c7297SChristian Brauner struct iattr *attr) 191049d4914fSMiklos Szeredi { 19112b0143b5SDavid Howells struct inode *inode = d_inode(entry); 19125e940c1dSMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1913a09f99edSMiklos Szeredi struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL; 19145e2b8828SMiklos Szeredi int ret; 1915efb9fa9eSMaxim Patlasov 19165d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 19175d069dbeSMiklos Szeredi return -EIO; 19185d069dbeSMiklos Szeredi 1919efb9fa9eSMaxim Patlasov if (!fuse_allow_current_process(get_fuse_conn(inode))) 1920efb9fa9eSMaxim Patlasov return -EACCES; 1921efb9fa9eSMaxim Patlasov 1922a09f99edSMiklos Szeredi if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) { 1923a09f99edSMiklos Szeredi attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | 1924a09f99edSMiklos Szeredi ATTR_MODE); 19255e940c1dSMiklos Szeredi 1926a09f99edSMiklos Szeredi /* 19275e940c1dSMiklos Szeredi * The only sane way to reliably kill suid/sgid is to do it in 19285e940c1dSMiklos Szeredi * the userspace filesystem 19295e940c1dSMiklos Szeredi * 19305e940c1dSMiklos Szeredi * This should be done on write(), truncate() and chown(). 19315e940c1dSMiklos Szeredi */ 19328981bdfdSVivek Goyal if (!fc->handle_killpriv && !fc->handle_killpriv_v2) { 19335e940c1dSMiklos Szeredi /* 19345e940c1dSMiklos Szeredi * ia_mode calculation may have used stale i_mode. 19355e940c1dSMiklos Szeredi * Refresh and recalculate. 1936a09f99edSMiklos Szeredi */ 1937a09f99edSMiklos Szeredi ret = fuse_do_getattr(inode, NULL, file); 1938a09f99edSMiklos Szeredi if (ret) 1939a09f99edSMiklos Szeredi return ret; 1940a09f99edSMiklos Szeredi 1941a09f99edSMiklos Szeredi attr->ia_mode = inode->i_mode; 1942c01638f5SMiklos Szeredi if (inode->i_mode & S_ISUID) { 1943a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1944a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISUID; 1945a09f99edSMiklos Szeredi } 1946c01638f5SMiklos Szeredi if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 1947a09f99edSMiklos Szeredi attr->ia_valid |= ATTR_MODE; 1948a09f99edSMiklos Szeredi attr->ia_mode &= ~S_ISGID; 1949a09f99edSMiklos Szeredi } 1950a09f99edSMiklos Szeredi } 19515e940c1dSMiklos Szeredi } 1952a09f99edSMiklos Szeredi if (!attr->ia_valid) 1953a09f99edSMiklos Szeredi return 0; 1954a09f99edSMiklos Szeredi 1955abb5a14fSLinus Torvalds ret = fuse_do_setattr(entry, attr, file); 19565e2b8828SMiklos Szeredi if (!ret) { 195760bcc88aSSeth Forshee /* 195860bcc88aSSeth Forshee * If filesystem supports acls it may have updated acl xattrs in 195960bcc88aSSeth Forshee * the filesystem, so forget cached acls for the inode. 196060bcc88aSSeth Forshee */ 196160bcc88aSSeth Forshee if (fc->posix_acl) 196260bcc88aSSeth Forshee forget_all_cached_acls(inode); 196360bcc88aSSeth Forshee 19645e2b8828SMiklos Szeredi /* Directory mode changed, may need to revalidate access */ 19655e2b8828SMiklos Szeredi if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE)) 19665e2b8828SMiklos Szeredi fuse_invalidate_entry_cache(entry); 19675e2b8828SMiklos Szeredi } 19685e2b8828SMiklos Szeredi return ret; 196949d4914fSMiklos Szeredi } 197049d4914fSMiklos Szeredi 1971b74d24f7SChristian Brauner static int fuse_getattr(struct mnt_idmap *idmap, 1972549c7297SChristian Brauner const struct path *path, struct kstat *stat, 1973a528d35eSDavid Howells u32 request_mask, unsigned int flags) 1974e5e5558eSMiklos Szeredi { 1975a528d35eSDavid Howells struct inode *inode = d_inode(path->dentry); 1976244f6385SMiklos Szeredi struct fuse_conn *fc = get_fuse_conn(inode); 1977244f6385SMiklos Szeredi 19785d069dbeSMiklos Szeredi if (fuse_is_bad(inode)) 19795d069dbeSMiklos Szeredi return -EIO; 19805d069dbeSMiklos Szeredi 19815157da2cSMiklos Szeredi if (!fuse_allow_current_process(fc)) { 19825157da2cSMiklos Szeredi if (!request_mask) { 19835157da2cSMiklos Szeredi /* 19845157da2cSMiklos Szeredi * If user explicitly requested *nothing* then don't 19855157da2cSMiklos Szeredi * error out, but return st_dev only. 19865157da2cSMiklos Szeredi */ 19875157da2cSMiklos Szeredi stat->result_mask = 0; 19885157da2cSMiklos Szeredi stat->dev = inode->i_sb->s_dev; 19895157da2cSMiklos Szeredi return 0; 19905157da2cSMiklos Szeredi } 1991244f6385SMiklos Szeredi return -EACCES; 19925157da2cSMiklos Szeredi } 1993244f6385SMiklos Szeredi 19942f1e8196SMiklos Szeredi return fuse_update_get_attr(inode, NULL, stat, request_mask, flags); 1995e5e5558eSMiklos Szeredi } 1996e5e5558eSMiklos Szeredi 1997754661f1SArjan van de Ven static const struct inode_operations fuse_dir_inode_operations = { 1998e5e5558eSMiklos Szeredi .lookup = fuse_lookup, 19999e6268dbSMiklos Szeredi .mkdir = fuse_mkdir, 20009e6268dbSMiklos Szeredi .symlink = fuse_symlink, 20019e6268dbSMiklos Szeredi .unlink = fuse_unlink, 20029e6268dbSMiklos Szeredi .rmdir = fuse_rmdir, 20032773bf00SMiklos Szeredi .rename = fuse_rename2, 20049e6268dbSMiklos Szeredi .link = fuse_link, 20059e6268dbSMiklos Szeredi .setattr = fuse_setattr, 20069e6268dbSMiklos Szeredi .create = fuse_create, 2007c8ccbe03SMiklos Szeredi .atomic_open = fuse_atomic_open, 20087d375390SMiklos Szeredi .tmpfile = fuse_tmpfile, 20099e6268dbSMiklos Szeredi .mknod = fuse_mknod, 2010e5e5558eSMiklos Szeredi .permission = fuse_permission, 2011e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 201292a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 2013facd6105SChristian Brauner .get_inode_acl = fuse_get_inode_acl, 2014facd6105SChristian Brauner .get_acl = fuse_get_acl, 201560bcc88aSSeth Forshee .set_acl = fuse_set_acl, 201672227eacSMiklos Szeredi .fileattr_get = fuse_fileattr_get, 201772227eacSMiklos Szeredi .fileattr_set = fuse_fileattr_set, 2018e5e5558eSMiklos Szeredi }; 2019e5e5558eSMiklos Szeredi 20204b6f5d20SArjan van de Ven static const struct file_operations fuse_dir_operations = { 2021b6aeadedSMiklos Szeredi .llseek = generic_file_llseek, 2022e5e5558eSMiklos Szeredi .read = generic_read_dir, 2023d9b3dbdcSAl Viro .iterate_shared = fuse_readdir, 2024e5e5558eSMiklos Szeredi .open = fuse_dir_open, 2025e5e5558eSMiklos Szeredi .release = fuse_dir_release, 202682547981SMiklos Szeredi .fsync = fuse_dir_fsync, 2027b18da0c5SMiklos Szeredi .unlocked_ioctl = fuse_dir_ioctl, 2028b18da0c5SMiklos Szeredi .compat_ioctl = fuse_dir_compat_ioctl, 2029e5e5558eSMiklos Szeredi }; 2030e5e5558eSMiklos Szeredi 2031754661f1SArjan van de Ven static const struct inode_operations fuse_common_inode_operations = { 20329e6268dbSMiklos Szeredi .setattr = fuse_setattr, 2033e5e5558eSMiklos Szeredi .permission = fuse_permission, 2034e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 203592a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 2036facd6105SChristian Brauner .get_inode_acl = fuse_get_inode_acl, 2037facd6105SChristian Brauner .get_acl = fuse_get_acl, 203860bcc88aSSeth Forshee .set_acl = fuse_set_acl, 203972227eacSMiklos Szeredi .fileattr_get = fuse_fileattr_get, 204072227eacSMiklos Szeredi .fileattr_set = fuse_fileattr_set, 2041e5e5558eSMiklos Szeredi }; 2042e5e5558eSMiklos Szeredi 2043754661f1SArjan van de Ven static const struct inode_operations fuse_symlink_inode_operations = { 20449e6268dbSMiklos Szeredi .setattr = fuse_setattr, 20456b255391SAl Viro .get_link = fuse_get_link, 2046e5e5558eSMiklos Szeredi .getattr = fuse_getattr, 204792a8780eSMiklos Szeredi .listxattr = fuse_listxattr, 2048e5e5558eSMiklos Szeredi }; 2049e5e5558eSMiklos Szeredi 2050e5e5558eSMiklos Szeredi void fuse_init_common(struct inode *inode) 2051e5e5558eSMiklos Szeredi { 2052e5e5558eSMiklos Szeredi inode->i_op = &fuse_common_inode_operations; 2053e5e5558eSMiklos Szeredi } 2054e5e5558eSMiklos Szeredi 2055e5e5558eSMiklos Szeredi void fuse_init_dir(struct inode *inode) 2056e5e5558eSMiklos Szeredi { 2057ab2257e9SMiklos Szeredi struct fuse_inode *fi = get_fuse_inode(inode); 2058ab2257e9SMiklos Szeredi 2059e5e5558eSMiklos Szeredi inode->i_op = &fuse_dir_inode_operations; 2060e5e5558eSMiklos Szeredi inode->i_fop = &fuse_dir_operations; 2061ab2257e9SMiklos Szeredi 2062ab2257e9SMiklos Szeredi spin_lock_init(&fi->rdc.lock); 2063ab2257e9SMiklos Szeredi fi->rdc.cached = false; 2064ab2257e9SMiklos Szeredi fi->rdc.size = 0; 2065ab2257e9SMiklos Szeredi fi->rdc.pos = 0; 2066ab2257e9SMiklos Szeredi fi->rdc.version = 0; 2067e5e5558eSMiklos Szeredi } 2068e5e5558eSMiklos Szeredi 20695efd00e4SMatthew Wilcox (Oracle) static int fuse_symlink_read_folio(struct file *null, struct folio *folio) 20705571f1e6SDan Schatzberg { 20715efd00e4SMatthew Wilcox (Oracle) int err = fuse_readlink_page(folio->mapping->host, &folio->page); 20725571f1e6SDan Schatzberg 20735571f1e6SDan Schatzberg if (!err) 20745efd00e4SMatthew Wilcox (Oracle) folio_mark_uptodate(folio); 20755571f1e6SDan Schatzberg 20765efd00e4SMatthew Wilcox (Oracle) folio_unlock(folio); 20775571f1e6SDan Schatzberg 20785571f1e6SDan Schatzberg return err; 20795571f1e6SDan Schatzberg } 20805571f1e6SDan Schatzberg 20815571f1e6SDan Schatzberg static const struct address_space_operations fuse_symlink_aops = { 20825efd00e4SMatthew Wilcox (Oracle) .read_folio = fuse_symlink_read_folio, 20835571f1e6SDan Schatzberg }; 20845571f1e6SDan Schatzberg 2085e5e5558eSMiklos Szeredi void fuse_init_symlink(struct inode *inode) 2086e5e5558eSMiklos Szeredi { 2087e5e5558eSMiklos Szeredi inode->i_op = &fuse_symlink_inode_operations; 20885571f1e6SDan Schatzberg inode->i_data.a_ops = &fuse_symlink_aops; 20895571f1e6SDan Schatzberg inode_nohighmem(inode); 2090e5e5558eSMiklos Szeredi } 2091