blob: 656e921f3506bd75e4d6f2f133a9ae72e95a18d6 [file] [log] [blame]
Miklos Szeredie5e55582005-09-09 13:10:28 -07001/*
2 FUSE: Filesystem in Userspace
Miklos Szeredi1729a162008-11-26 12:03:54 +01003 Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredie5e55582005-09-09 13:10:28 -07004
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7*/
8
9#include "fuse_i.h"
10
11#include <linux/pagemap.h>
12#include <linux/file.h>
Max Reitzbf109c62020-04-21 14:47:15 +020013#include <linux/fs_context.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070014#include <linux/sched.h>
15#include <linux/namei.h>
Miklos Szeredi07e77dc2010-12-07 20:16:56 +010016#include <linux/slab.h>
Seth Forshee703c7362016-08-29 08:46:36 -050017#include <linux/xattr.h>
Miklos Szeredi261aaba72018-10-01 10:07:05 +020018#include <linux/iversion.h>
Seth Forshee60bcc882016-08-29 08:46:37 -050019#include <linux/posix_acl.h>
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -050020#include <linux/security.h>
21#include <linux/types.h>
22#include <linux/kernel.h>
Miklos Szeredie5e55582005-09-09 13:10:28 -070023
Feng Shuo4582a4a2013-01-15 11:23:28 +080024static void fuse_advise_use_readdirplus(struct inode *dir)
25{
26 struct fuse_inode *fi = get_fuse_inode(dir);
27
28 set_bit(FUSE_I_ADVISE_RDPLUS, &fi->state);
29}
30
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070031#if BITS_PER_LONG >= 64
32static inline void __fuse_dentry_settime(struct dentry *entry, u64 time)
33{
34 entry->d_fsdata = (void *) time;
35}
36
37static inline u64 fuse_dentry_time(const struct dentry *entry)
38{
39 return (u64)entry->d_fsdata;
40}
41
42#else
Miklos Szeredif75fdf22016-10-01 07:32:32 +020043union fuse_dentry {
44 u64 time;
45 struct rcu_head rcu;
46};
47
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070048static inline void __fuse_dentry_settime(struct dentry *dentry, u64 time)
49{
50 ((union fuse_dentry *) dentry->d_fsdata)->time = time;
51}
52
53static inline u64 fuse_dentry_time(const struct dentry *entry)
54{
55 return ((union fuse_dentry *) entry->d_fsdata)->time;
56}
57#endif
58
Miklos Szeredi8fab0102018-08-15 17:42:34 +020059static void fuse_dentry_settime(struct dentry *dentry, u64 time)
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070060{
Miklos Szeredi8fab0102018-08-15 17:42:34 +020061 struct fuse_conn *fc = get_fuse_conn_super(dentry->d_sb);
62 bool delete = !time && fc->delete_stale;
63 /*
64 * Mess with DCACHE_OP_DELETE because dput() will be faster without it.
65 * Don't care about races, either way it's just an optimization
66 */
67 if ((!delete && (dentry->d_flags & DCACHE_OP_DELETE)) ||
68 (delete && !(dentry->d_flags & DCACHE_OP_DELETE))) {
69 spin_lock(&dentry->d_lock);
70 if (!delete)
71 dentry->d_flags &= ~DCACHE_OP_DELETE;
72 else
73 dentry->d_flags |= DCACHE_OP_DELETE;
74 spin_unlock(&dentry->d_lock);
75 }
76
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -070077 __fuse_dentry_settime(dentry, time);
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070078}
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070079
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080080/*
81 * FUSE caches dentries and attributes with separate timeout. The
82 * time in jiffies until the dentry/attributes are valid is stored in
Miklos Szeredif75fdf22016-10-01 07:32:32 +020083 * dentry->d_fsdata and fuse_inode->i_time respectively.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -080084 */
85
86/*
87 * Calculate the time in jiffies until a dentry/attributes are valid
88 */
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020089static u64 time_to_jiffies(u64 sec, u32 nsec)
Miklos Szeredie5e55582005-09-09 13:10:28 -070090{
Miklos Szeredi685d16d2006-07-30 03:04:08 -070091 if (sec || nsec) {
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020092 struct timespec64 ts = {
93 sec,
David Sheets21067522017-01-13 15:58:30 +000094 min_t(u32, nsec, NSEC_PER_SEC - 1)
Miklos Szeredibcb6f6d2016-10-01 07:32:32 +020095 };
96
97 return get_jiffies_64() + timespec64_to_jiffies(&ts);
Miklos Szeredi685d16d2006-07-30 03:04:08 -070098 } else
Miklos Szeredi0a0898c2006-07-30 03:04:10 -070099 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700100}
101
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800102/*
103 * Set dentry and possibly attribute timeouts from the lookup/mk*
104 * replies
105 */
Miklos Szeredid123d8e2018-09-28 16:43:23 +0200106void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o)
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800107{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700108 fuse_dentry_settime(entry,
109 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700110}
111
112static u64 attr_timeout(struct fuse_attr_out *o)
113{
114 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
115}
116
Miklos Szeredid123d8e2018-09-28 16:43:23 +0200117u64 entry_attr_timeout(struct fuse_entry_out *o)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700118{
119 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800120}
121
Miklos Szeredifa5eee52021-10-22 17:03:02 +0200122void fuse_invalidate_attr_mask(struct inode *inode, u32 mask)
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200123{
124 set_mask_bits(&get_fuse_inode(inode)->inval_mask, 0, mask);
125}
126
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800127/*
128 * Mark the attributes as stale, so that at the next call to
129 * ->getattr() they will be fetched from userspace
130 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800131void fuse_invalidate_attr(struct inode *inode)
132{
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200133 fuse_invalidate_attr_mask(inode, STATX_BASIC_STATS);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800134}
135
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200136static void fuse_dir_changed(struct inode *dir)
137{
138 fuse_invalidate_attr(dir);
139 inode_maybe_inc_iversion(dir, false);
140}
141
Andrew Gallagher451418f2013-11-05 03:55:43 -0800142/**
143 * Mark the attributes as stale due to an atime change. Avoid the invalidate if
144 * atime is not used.
145 */
146void fuse_invalidate_atime(struct inode *inode)
147{
148 if (!IS_RDONLY(inode))
Miklos Szeredi2f1e8192018-10-15 15:43:06 +0200149 fuse_invalidate_attr_mask(inode, STATX_ATIME);
Andrew Gallagher451418f2013-11-05 03:55:43 -0800150}
151
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800152/*
153 * Just mark the entry as stale, so that a next attempt to look it up
154 * will result in a new lookup call to userspace
155 *
156 * This is called when a dentry is about to become negative and the
157 * timeout is unknown (unlink, rmdir, rename and in some cases
158 * lookup)
159 */
Miklos Szeredidbd561d2008-07-25 01:49:00 -0700160void fuse_invalidate_entry_cache(struct dentry *entry)
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800161{
Miklos Szeredi0a0898c2006-07-30 03:04:10 -0700162 fuse_dentry_settime(entry, 0);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800163}
164
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800165/*
166 * Same as fuse_invalidate_entry_cache(), but also try to remove the
167 * dentry from the hash
168 */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800169static void fuse_invalidate_entry(struct dentry *entry)
170{
171 d_invalidate(entry);
172 fuse_invalidate_entry_cache(entry);
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800173}
174
Miklos Szeredi70781872014-12-12 09:49:05 +0100175static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args,
Al Viro13983d02016-07-20 22:34:44 -0400176 u64 nodeid, const struct qstr *name,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700177 struct fuse_entry_out *outarg)
178{
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700179 memset(outarg, 0, sizeof(struct fuse_entry_out));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200180 args->opcode = FUSE_LOOKUP;
181 args->nodeid = nodeid;
182 args->in_numargs = 1;
183 args->in_args[0].size = name->len + 1;
184 args->in_args[0].value = name->name;
185 args->out_numargs = 1;
186 args->out_args[0].size = sizeof(struct fuse_entry_out);
187 args->out_args[0].value = outarg;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700188}
189
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800190/*
191 * Check whether the dentry is still valid
192 *
193 * If the entry validity timeout has expired and the dentry is
194 * positive, try to redo the lookup. If the lookup results in a
195 * different inode, then let the VFS invalidate the dentry and redo
196 * the lookup once more. If the lookup results in the same inode,
197 * then refresh the attributes, timeouts and mark the dentry valid.
198 */
Al Viro0b728e12012-06-10 16:03:43 -0400199static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700200{
Nick Piggin34286d62011-01-07 17:49:57 +1100201 struct inode *inode;
Miklos Szeredi28420da2013-06-03 14:40:22 +0200202 struct dentry *parent;
Max Reitzfcee2162020-05-06 17:44:12 +0200203 struct fuse_mount *fm;
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200204 struct fuse_inode *fi;
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200205 int ret;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800206
David Howells2b0143b2015-03-17 22:25:59 +0000207 inode = d_inode_rcu(entry);
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100208 if (inode && fuse_is_bad(inode))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200209 goto invalid;
Anand Avati154210c2014-06-26 20:21:57 -0400210 else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) ||
Miklos Szeredidf8629a2020-11-11 17:22:32 +0100211 (flags & (LOOKUP_EXCL | LOOKUP_REVAL))) {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700212 struct fuse_entry_out outarg;
Miklos Szeredi70781872014-12-12 09:49:05 +0100213 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100214 struct fuse_forget_link *forget;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700215 u64 attr_version;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800216
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800217 /* For negative dentries, always do a fresh lookup */
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800218 if (!inode)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200219 goto invalid;
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800220
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200221 ret = -ECHILD;
Al Viro0b728e12012-06-10 16:03:43 -0400222 if (flags & LOOKUP_RCU)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200223 goto out;
Miklos Szeredie7c0a162011-03-21 13:58:06 +0100224
Max Reitzfcee2162020-05-06 17:44:12 +0200225 fm = get_fuse_mount(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700226
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100227 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100228 ret = -ENOMEM;
229 if (!forget)
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200230 goto out;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800231
Max Reitzfcee2162020-05-06 17:44:12 +0200232 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700233
Miklos Szeredie956edd2006-10-17 00:10:12 -0700234 parent = dget_parent(entry);
Max Reitzfcee2162020-05-06 17:44:12 +0200235 fuse_lookup_init(fm->fc, &args, get_node_id(d_inode(parent)),
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700236 &entry->d_name, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +0200237 ret = fuse_simple_request(fm, &args);
Miklos Szeredie956edd2006-10-17 00:10:12 -0700238 dput(parent);
Miklos Szeredi50322fe2006-02-28 16:59:03 -0800239 /* Zero nodeid is same as -ENOENT */
Miklos Szeredi70781872014-12-12 09:49:05 +0100240 if (!ret && !outarg.nodeid)
241 ret = -ENOENT;
242 if (!ret) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200243 fi = get_fuse_inode(inode);
Max Reitzbf109c62020-04-21 14:47:15 +0200244 if (outarg.nodeid != get_node_id(inode) ||
245 (bool) IS_AUTOMOUNT(inode) != (bool) (outarg.attr.flags & FUSE_ATTR_SUBMOUNT)) {
Max Reitzfcee2162020-05-06 17:44:12 +0200246 fuse_queue_forget(fm->fc, forget,
247 outarg.nodeid, 1);
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200248 goto invalid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700249 }
Kirill Tkhaic9d8f5f2018-11-09 13:33:27 +0300250 spin_lock(&fi->lock);
Miklos Szeredi1729a162008-11-26 12:03:54 +0100251 fi->nlookup++;
Kirill Tkhaic9d8f5f2018-11-09 13:33:27 +0300252 spin_unlock(&fi->lock);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700253 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100254 kfree(forget);
Miklos Szeredi70781872014-12-12 09:49:05 +0100255 if (ret == -ENOMEM)
256 goto out;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100257 if (ret || fuse_invalid_attr(&outarg.attr) ||
Amir Goldstein15db1682021-06-21 14:03:53 +0300258 fuse_stale_inode(inode, outarg.generation, &outarg.attr))
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200259 goto invalid;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700260
Seth Forshee60bcc882016-08-29 08:46:37 -0500261 forget_all_cached_acls(inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700262 fuse_change_attributes(inode, &outarg.attr,
263 entry_attr_timeout(&outarg),
264 attr_version);
265 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi28420da2013-06-03 14:40:22 +0200266 } else if (inode) {
Miklos Szeredi6314efe2013-10-01 16:41:22 +0200267 fi = get_fuse_inode(inode);
268 if (flags & LOOKUP_RCU) {
269 if (test_bit(FUSE_I_INIT_RDPLUS, &fi->state))
270 return -ECHILD;
271 } else if (test_and_clear_bit(FUSE_I_INIT_RDPLUS, &fi->state)) {
Miklos Szeredi28420da2013-06-03 14:40:22 +0200272 parent = dget_parent(entry);
David Howells2b0143b2015-03-17 22:25:59 +0000273 fuse_advise_use_readdirplus(d_inode(parent));
Miklos Szeredi28420da2013-06-03 14:40:22 +0200274 dput(parent);
275 }
Miklos Szeredie5e55582005-09-09 13:10:28 -0700276 }
Miklos Szeredie2a6b952013-09-05 11:44:43 +0200277 ret = 1;
278out:
279 return ret;
280
281invalid:
282 ret = 0;
283 goto out;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700284}
285
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700286#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200287static int fuse_dentry_init(struct dentry *dentry)
288{
Khazhismel Kumykovdc69e982019-09-17 12:35:33 -0700289 dentry->d_fsdata = kzalloc(sizeof(union fuse_dentry),
290 GFP_KERNEL_ACCOUNT | __GFP_RECLAIMABLE);
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200291
292 return dentry->d_fsdata ? 0 : -ENOMEM;
293}
294static void fuse_dentry_release(struct dentry *dentry)
295{
296 union fuse_dentry *fd = dentry->d_fsdata;
297
298 kfree_rcu(fd, rcu);
299}
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700300#endif
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200301
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200302static int fuse_dentry_delete(const struct dentry *dentry)
303{
304 return time_before64(fuse_dentry_time(dentry), get_jiffies_64());
305}
306
Max Reitzbf109c62020-04-21 14:47:15 +0200307/*
308 * Create a fuse_mount object with a new superblock (with path->dentry
309 * as the root), and return that mount so it can be auto-mounted on
310 * @path.
311 */
312static struct vfsmount *fuse_dentry_automount(struct path *path)
313{
314 struct fs_context *fsc;
Max Reitzbf109c62020-04-21 14:47:15 +0200315 struct vfsmount *mnt;
316 struct fuse_inode *mp_fi = get_fuse_inode(d_inode(path->dentry));
Max Reitzbf109c62020-04-21 14:47:15 +0200317
318 fsc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry);
Greg Kurz29e0e4d2021-06-04 18:11:55 +0200319 if (IS_ERR(fsc))
320 return ERR_CAST(fsc);
Max Reitzbf109c62020-04-21 14:47:15 +0200321
Greg Kurz266eb3f22021-06-04 18:11:54 +0200322 /* Pass the FUSE inode of the mount for fuse_get_tree_submount() */
323 fsc->fs_private = mp_fi;
324
Max Reitzbf109c62020-04-21 14:47:15 +0200325 /* Create the submount */
Greg Kurz29e0e4d2021-06-04 18:11:55 +0200326 mnt = fc_mount(fsc);
327 if (!IS_ERR(mnt))
328 mntget(mnt);
329
Max Reitzbf109c62020-04-21 14:47:15 +0200330 put_fs_context(fsc);
331 return mnt;
Max Reitzbf109c62020-04-21 14:47:15 +0200332}
333
Al Viro42695902009-02-20 05:59:13 +0000334const struct dentry_operations fuse_dentry_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -0700335 .d_revalidate = fuse_dentry_revalidate,
Miklos Szeredi8fab0102018-08-15 17:42:34 +0200336 .d_delete = fuse_dentry_delete,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700337#if BITS_PER_LONG < 64
Miklos Szeredif75fdf22016-10-01 07:32:32 +0200338 .d_init = fuse_dentry_init,
339 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700340#endif
Max Reitzbf109c62020-04-21 14:47:15 +0200341 .d_automount = fuse_dentry_automount,
Miklos Szeredie5e55582005-09-09 13:10:28 -0700342};
343
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200344const struct dentry_operations fuse_root_dentry_operations = {
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700345#if BITS_PER_LONG < 64
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200346 .d_init = fuse_dentry_init,
347 .d_release = fuse_dentry_release,
Khazhismel Kumykov30c6a232019-09-16 16:56:41 -0700348#endif
Miklos Szeredi0ce267f2016-10-18 15:36:48 +0200349};
350
Timo Savolaa5bfffac2007-04-08 16:04:00 -0700351int fuse_valid_type(int m)
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800352{
353 return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
354 S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
355}
356
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100357bool fuse_invalid_attr(struct fuse_attr *attr)
358{
359 return !fuse_valid_type(attr->mode) ||
360 attr->size > LLONG_MAX;
361}
362
Al Viro13983d02016-07-20 22:34:44 -0400363int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name,
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700364 struct fuse_entry_out *outarg, struct inode **inode)
365{
Max Reitzfcee2162020-05-06 17:44:12 +0200366 struct fuse_mount *fm = get_fuse_mount_super(sb);
Miklos Szeredi70781872014-12-12 09:49:05 +0100367 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100368 struct fuse_forget_link *forget;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700369 u64 attr_version;
370 int err;
371
372 *inode = NULL;
373 err = -ENAMETOOLONG;
374 if (name->len > FUSE_NAME_MAX)
375 goto out;
376
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700377
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100378 forget = fuse_alloc_forget();
379 err = -ENOMEM;
Miklos Szeredi70781872014-12-12 09:49:05 +0100380 if (!forget)
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700381 goto out;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700382
Max Reitzfcee2162020-05-06 17:44:12 +0200383 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700384
Max Reitzfcee2162020-05-06 17:44:12 +0200385 fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
386 err = fuse_simple_request(fm, &args);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700387 /* Zero nodeid is same as -ENOENT, but with valid timeout */
388 if (err || !outarg->nodeid)
389 goto out_put_forget;
390
391 err = -EIO;
392 if (!outarg->nodeid)
393 goto out_put_forget;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100394 if (fuse_invalid_attr(&outarg->attr))
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700395 goto out_put_forget;
396
397 *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
398 &outarg->attr, entry_attr_timeout(outarg),
399 attr_version);
400 err = -ENOMEM;
401 if (!*inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200402 fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700403 goto out;
404 }
405 err = 0;
406
407 out_put_forget:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100408 kfree(forget);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700409 out:
410 return err;
411}
412
Miklos Szeredi0aa7c692006-01-06 00:19:34 -0800413static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400414 unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -0700415{
416 int err;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700417 struct fuse_entry_out outarg;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700418 struct inode *inode;
Miklos Szeredi0de62562008-07-25 01:48:59 -0700419 struct dentry *newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700420 bool outarg_valid = true;
Miklos Szeredi63576c12018-07-26 16:13:11 +0200421 bool locked;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700422
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100423 if (fuse_is_bad(dir))
424 return ERR_PTR(-EIO);
425
Miklos Szeredi63576c12018-07-26 16:13:11 +0200426 locked = fuse_lock_inode(dir);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700427 err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name,
428 &outarg, &inode);
Miklos Szeredi63576c12018-07-26 16:13:11 +0200429 fuse_unlock_inode(dir, locked);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700430 if (err == -ENOENT) {
431 outarg_valid = false;
432 err = 0;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800433 }
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700434 if (err)
435 goto out_err;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800436
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700437 err = -EIO;
438 if (inode && get_node_id(inode) == FUSE_ROOT_ID)
439 goto out_iput;
Miklos Szeredie5e55582005-09-09 13:10:28 -0700440
Al Viro41d28bc2014-10-12 22:24:21 -0400441 newent = d_splice_alias(inode, entry);
Miklos Szeredi5835f332013-09-05 11:44:42 +0200442 err = PTR_ERR(newent);
443 if (IS_ERR(newent))
444 goto out_err;
Miklos Szeredid2a85162006-10-17 00:10:11 -0700445
Miklos Szeredi0de62562008-07-25 01:48:59 -0700446 entry = newent ? newent : entry;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700447 if (outarg_valid)
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700448 fuse_change_entry_timeout(entry, &outarg);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800449 else
450 fuse_invalidate_entry_cache(entry);
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700451
Miklos Szeredi6c26f712019-10-21 15:57:07 +0200452 if (inode)
453 fuse_advise_use_readdirplus(dir);
Miklos Szeredi0de62562008-07-25 01:48:59 -0700454 return newent;
Miklos Szeredic180eeb2008-07-25 01:49:01 -0700455
456 out_iput:
457 iput(inode);
458 out_err:
459 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -0700460}
461
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500462static int get_security_context(struct dentry *entry, umode_t mode,
463 void **security_ctx, u32 *security_ctxlen)
464{
465 struct fuse_secctx *fctx;
466 struct fuse_secctx_header *header;
467 void *ctx = NULL, *ptr;
468 u32 ctxlen, total_len = sizeof(*header);
469 int err, nr_ctx = 0;
470 const char *name;
471 size_t namelen;
472
473 err = security_dentry_init_security(entry, mode, &entry->d_name,
474 &name, &ctx, &ctxlen);
475 if (err) {
476 if (err != -EOPNOTSUPP)
477 goto out_err;
478 /* No LSM is supporting this security hook. Ignore error */
479 ctxlen = 0;
480 ctx = NULL;
481 }
482
483 if (ctxlen) {
484 nr_ctx = 1;
485 namelen = strlen(name) + 1;
486 err = -EIO;
487 if (WARN_ON(namelen > XATTR_NAME_MAX + 1 || ctxlen > S32_MAX))
488 goto out_err;
489 total_len += FUSE_REC_ALIGN(sizeof(*fctx) + namelen + ctxlen);
490 }
491
492 err = -ENOMEM;
493 header = ptr = kzalloc(total_len, GFP_KERNEL);
494 if (!ptr)
495 goto out_err;
496
497 header->nr_secctx = nr_ctx;
498 header->size = total_len;
499 ptr += sizeof(*header);
500 if (nr_ctx) {
501 fctx = ptr;
502 fctx->size = ctxlen;
503 ptr += sizeof(*fctx);
504
505 strcpy(ptr, name);
506 ptr += namelen;
507
508 memcpy(ptr, ctx, ctxlen);
509 }
510 *security_ctxlen = total_len;
511 *security_ctx = header;
512 err = 0;
513out_err:
514 kfree(ctx);
515 return err;
516}
517
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800518/*
519 * Atomic create+open operation
520 *
521 * If the filesystem doesn't support this, then fall back to separate
522 * 'mknod' + 'open' requests.
523 */
Al Virod9585272012-06-22 12:39:14 +0400524static int fuse_create_open(struct inode *dir, struct dentry *entry,
Miklos Szeredi54d601c2021-04-07 14:36:45 +0200525 struct file *file, unsigned int flags,
Al Virob452a452018-06-08 13:06:28 -0400526 umode_t mode)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800527{
528 int err;
529 struct inode *inode;
Max Reitzfcee2162020-05-06 17:44:12 +0200530 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100531 FUSE_ARGS(args);
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100532 struct fuse_forget_link *forget;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200533 struct fuse_create_in inarg;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800534 struct fuse_open_out outopen;
535 struct fuse_entry_out outentry;
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300536 struct fuse_inode *fi;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800537 struct fuse_file *ff;
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500538 void *security_ctx = NULL;
539 u32 security_ctxlen;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800540
Miklos Szerediaf109bc2012-08-15 13:01:24 +0200541 /* Userspace expects S_IFREG in create mode */
542 BUG_ON((mode & S_IFMT) != S_IFREG);
543
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100544 forget = fuse_alloc_forget();
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200545 err = -ENOMEM;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100546 if (!forget)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200547 goto out_err;
Miklos Szeredi51eb01e2006-06-25 05:48:50 -0700548
Miklos Szeredice1d5a42006-04-10 22:54:58 -0700549 err = -ENOMEM;
Max Reitzfcee2162020-05-06 17:44:12 +0200550 ff = fuse_file_alloc(fm);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800551 if (!ff)
Miklos Szeredi70781872014-12-12 09:49:05 +0100552 goto out_put_forget_req;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800553
Max Reitzfcee2162020-05-06 17:44:12 +0200554 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200555 mode &= ~current_umask();
556
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800557 flags &= ~O_NOCTTY;
558 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700559 memset(&outentry, 0, sizeof(outentry));
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800560 inarg.flags = flags;
561 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200562 inarg.umask = current_umask();
Vivek Goyal643a6662020-10-09 14:15:11 -0400563
564 if (fm->fc->handle_killpriv_v2 && (flags & O_TRUNC) &&
565 !(flags & O_EXCL) && !capable(CAP_FSETID)) {
566 inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
567 }
568
Miklos Szeredid5b48542019-09-10 15:04:08 +0200569 args.opcode = FUSE_CREATE;
570 args.nodeid = get_node_id(dir);
571 args.in_numargs = 2;
572 args.in_args[0].size = sizeof(inarg);
573 args.in_args[0].value = &inarg;
574 args.in_args[1].size = entry->d_name.len + 1;
575 args.in_args[1].value = entry->d_name.name;
576 args.out_numargs = 2;
577 args.out_args[0].size = sizeof(outentry);
578 args.out_args[0].value = &outentry;
579 args.out_args[1].size = sizeof(outopen);
580 args.out_args[1].value = &outopen;
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500581
582 if (fm->fc->init_security) {
583 err = get_security_context(entry, mode, &security_ctx,
584 &security_ctxlen);
585 if (err)
586 goto out_put_forget_req;
587
588 args.in_numargs = 3;
589 args.in_args[2].size = security_ctxlen;
590 args.in_args[2].value = security_ctx;
591 }
592
Max Reitzfcee2162020-05-06 17:44:12 +0200593 err = fuse_simple_request(fm, &args);
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500594 kfree(security_ctx);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200595 if (err)
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800596 goto out_free_ff;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800597
598 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100599 if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid) ||
600 fuse_invalid_attr(&outentry.attr))
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800601 goto out_free_ff;
602
Miklos Szeredic7b71432009-04-28 16:56:37 +0200603 ff->fh = outopen.fh;
604 ff->nodeid = outentry.nodeid;
605 ff->open_flags = outopen.open_flags;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800606 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700607 &outentry.attr, entry_attr_timeout(&outentry), 0);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800608 if (!inode) {
609 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300610 fuse_sync_release(NULL, ff, flags);
Max Reitzfcee2162020-05-06 17:44:12 +0200611 fuse_queue_forget(fm->fc, forget, outentry.nodeid, 1);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200612 err = -ENOMEM;
613 goto out_err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800614 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100615 kfree(forget);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800616 d_instantiate(entry, inode);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700617 fuse_change_entry_timeout(entry, &outentry);
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200618 fuse_dir_changed(dir);
Al Virobe12af32018-06-08 11:44:56 -0400619 err = finish_open(file, entry, generic_file_open);
Al Viro30d90492012-06-22 12:40:19 +0400620 if (err) {
Kirill Tkhaiebf84d02018-11-09 13:33:11 +0300621 fi = get_fuse_inode(inode);
622 fuse_sync_release(fi, ff, flags);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200623 } else {
Miklos Szeredi267d8442017-02-22 20:08:25 +0100624 file->private_data = ff;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200625 fuse_finish_open(inode, file);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800626 }
Al Virod9585272012-06-22 12:39:14 +0400627 return err;
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800628
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200629out_free_ff:
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800630 fuse_file_free(ff);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200631out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100632 kfree(forget);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200633out_err:
Al Virod9585272012-06-22 12:39:14 +0400634 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200635}
636
Christian Brauner549c7292021-01-21 14:19:43 +0100637static int fuse_mknod(struct user_namespace *, struct inode *, struct dentry *,
638 umode_t, dev_t);
Al Virod9585272012-06-22 12:39:14 +0400639static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
Al Viro30d90492012-06-22 12:40:19 +0400640 struct file *file, unsigned flags,
Al Viro44907d72018-06-08 13:32:02 -0400641 umode_t mode)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200642{
643 int err;
644 struct fuse_conn *fc = get_fuse_conn(dir);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200645 struct dentry *res = NULL;
646
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100647 if (fuse_is_bad(dir))
648 return -EIO;
649
Al Viro00699ad2016-07-05 09:44:53 -0400650 if (d_in_lookup(entry)) {
Al Viro00cd8dd2012-06-10 17:13:09 -0400651 res = fuse_lookup(dir, entry, 0);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200652 if (IS_ERR(res))
Al Virod9585272012-06-22 12:39:14 +0400653 return PTR_ERR(res);
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200654
655 if (res)
656 entry = res;
657 }
658
David Howells2b0143b2015-03-17 22:25:59 +0000659 if (!(flags & O_CREAT) || d_really_is_positive(entry))
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200660 goto no_open;
661
662 /* Only creates */
Al Viro73a09dd2018-06-08 13:22:02 -0400663 file->f_mode |= FMODE_CREATED;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200664
665 if (fc->no_create)
666 goto mknod;
667
Al Virob452a452018-06-08 13:06:28 -0400668 err = fuse_create_open(dir, entry, file, flags, mode);
Al Virod9585272012-06-22 12:39:14 +0400669 if (err == -ENOSYS) {
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200670 fc->no_create = 1;
671 goto mknod;
672 }
673out_dput:
674 dput(res);
Al Virod9585272012-06-22 12:39:14 +0400675 return err;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200676
677mknod:
Christian Brauner549c7292021-01-21 14:19:43 +0100678 err = fuse_mknod(&init_user_ns, dir, entry, mode, 0);
Al Virod9585272012-06-22 12:39:14 +0400679 if (err)
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200680 goto out_dput;
Miklos Szeredic8ccbe02012-06-05 15:10:22 +0200681no_open:
Al Viroe45198a2012-06-10 06:48:09 -0400682 return finish_no_open(file, res);
Miklos Szeredifd72faa2005-11-07 00:59:51 -0800683}
684
Miklos Szeredi6f9f1182006-01-06 00:19:39 -0800685/*
686 * Code shared between mknod, mkdir, symlink and link
687 */
Max Reitzfcee2162020-05-06 17:44:12 +0200688static int create_new_entry(struct fuse_mount *fm, struct fuse_args *args,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700689 struct inode *dir, struct dentry *entry,
Al Viro541af6a2011-07-26 03:17:33 -0400690 umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700691{
692 struct fuse_entry_out outarg;
693 struct inode *inode;
Al Viroc971e6a2018-05-28 18:27:19 -0400694 struct dentry *d;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700695 int err;
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100696 struct fuse_forget_link *forget;
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500697 void *security_ctx = NULL;
698 u32 security_ctxlen;
Miklos Szeredi2d510132006-11-25 11:09:20 -0800699
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100700 if (fuse_is_bad(dir))
701 return -EIO;
702
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100703 forget = fuse_alloc_forget();
Miklos Szeredi70781872014-12-12 09:49:05 +0100704 if (!forget)
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100705 return -ENOMEM;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700706
Miklos Szeredi0e9663e2007-10-18 03:07:05 -0700707 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredid5b48542019-09-10 15:04:08 +0200708 args->nodeid = get_node_id(dir);
709 args->out_numargs = 1;
710 args->out_args[0].size = sizeof(outarg);
711 args->out_args[0].value = &outarg;
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500712
713 if (fm->fc->init_security && args->opcode != FUSE_LINK) {
714 err = get_security_context(entry, mode, &security_ctx,
715 &security_ctxlen);
716 if (err)
717 goto out_put_forget_req;
718
719 BUG_ON(args->in_numargs != 2);
720
721 args->in_numargs = 3;
722 args->in_args[2].size = security_ctxlen;
723 args->in_args[2].value = security_ctx;
724 }
725
Max Reitzfcee2162020-05-06 17:44:12 +0200726 err = fuse_simple_request(fm, args);
Vivek Goyal3e2b6fd2021-11-11 09:32:49 -0500727 kfree(security_ctx);
Miklos Szeredi2d510132006-11-25 11:09:20 -0800728 if (err)
729 goto out_put_forget_req;
730
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800731 err = -EIO;
Miklos Szeredieb59bd12019-11-12 11:49:04 +0100732 if (invalid_nodeid(outarg.nodeid) || fuse_invalid_attr(&outarg.attr))
Miklos Szeredi2d510132006-11-25 11:09:20 -0800733 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800734
735 if ((outarg.attr.mode ^ mode) & S_IFMT)
Miklos Szeredi2d510132006-11-25 11:09:20 -0800736 goto out_put_forget_req;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800737
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700738 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
Miklos Szeredi1fb69e72007-10-18 03:06:58 -0700739 &outarg.attr, entry_attr_timeout(&outarg), 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700740 if (!inode) {
Max Reitzfcee2162020-05-06 17:44:12 +0200741 fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700742 return -ENOMEM;
743 }
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100744 kfree(forget);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700745
Al Viroc971e6a2018-05-28 18:27:19 -0400746 d_drop(entry);
747 d = d_splice_alias(inode, entry);
748 if (IS_ERR(d))
749 return PTR_ERR(d);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700750
Al Viroc971e6a2018-05-28 18:27:19 -0400751 if (d) {
752 fuse_change_entry_timeout(d, &outarg);
753 dput(d);
754 } else {
755 fuse_change_entry_timeout(entry, &outarg);
756 }
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200757 fuse_dir_changed(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700758 return 0;
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800759
Miklos Szeredi2d510132006-11-25 11:09:20 -0800760 out_put_forget_req:
Miklos Szeredi07e77dc2010-12-07 20:16:56 +0100761 kfree(forget);
Miklos Szeredi39ee0592006-01-06 00:19:43 -0800762 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700763}
764
Christian Brauner549c7292021-01-21 14:19:43 +0100765static int fuse_mknod(struct user_namespace *mnt_userns, struct inode *dir,
766 struct dentry *entry, umode_t mode, dev_t rdev)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700767{
768 struct fuse_mknod_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200769 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100770 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700771
Max Reitzfcee2162020-05-06 17:44:12 +0200772 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200773 mode &= ~current_umask();
774
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700775 memset(&inarg, 0, sizeof(inarg));
776 inarg.mode = mode;
777 inarg.rdev = new_encode_dev(rdev);
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200778 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200779 args.opcode = FUSE_MKNOD;
780 args.in_numargs = 2;
781 args.in_args[0].size = sizeof(inarg);
782 args.in_args[0].value = &inarg;
783 args.in_args[1].size = entry->d_name.len + 1;
784 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200785 return create_new_entry(fm, &args, dir, entry, mode);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700786}
787
Christian Brauner549c7292021-01-21 14:19:43 +0100788static int fuse_create(struct user_namespace *mnt_userns, struct inode *dir,
789 struct dentry *entry, umode_t mode, bool excl)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700790{
Christian Brauner549c7292021-01-21 14:19:43 +0100791 return fuse_mknod(&init_user_ns, dir, entry, mode, 0);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700792}
793
Christian Brauner549c7292021-01-21 14:19:43 +0100794static int fuse_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
795 struct dentry *entry, umode_t mode)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700796{
797 struct fuse_mkdir_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200798 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100799 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700800
Max Reitzfcee2162020-05-06 17:44:12 +0200801 if (!fm->fc->dont_mask)
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200802 mode &= ~current_umask();
803
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700804 memset(&inarg, 0, sizeof(inarg));
805 inarg.mode = mode;
Miklos Szeredie0a43dd2009-06-30 20:12:23 +0200806 inarg.umask = current_umask();
Miklos Szeredid5b48542019-09-10 15:04:08 +0200807 args.opcode = FUSE_MKDIR;
808 args.in_numargs = 2;
809 args.in_args[0].size = sizeof(inarg);
810 args.in_args[0].value = &inarg;
811 args.in_args[1].size = entry->d_name.len + 1;
812 args.in_args[1].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200813 return create_new_entry(fm, &args, dir, entry, S_IFDIR);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700814}
815
Christian Brauner549c7292021-01-21 14:19:43 +0100816static int fuse_symlink(struct user_namespace *mnt_userns, struct inode *dir,
817 struct dentry *entry, const char *link)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700818{
Max Reitzfcee2162020-05-06 17:44:12 +0200819 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700820 unsigned len = strlen(link) + 1;
Miklos Szeredi70781872014-12-12 09:49:05 +0100821 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700822
Miklos Szeredid5b48542019-09-10 15:04:08 +0200823 args.opcode = FUSE_SYMLINK;
824 args.in_numargs = 2;
825 args.in_args[0].size = entry->d_name.len + 1;
826 args.in_args[0].value = entry->d_name.name;
827 args.in_args[1].size = len;
828 args.in_args[1].value = link;
Max Reitzfcee2162020-05-06 17:44:12 +0200829 return create_new_entry(fm, &args, dir, entry, S_IFLNK);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700830}
831
Miklos Szeredi5c791fe2021-10-22 17:03:01 +0200832void fuse_flush_time_update(struct inode *inode)
833{
834 int err = sync_inode_metadata(inode, 1);
835
836 mapping_set_error(inode->i_mapping, err);
837}
838
Miklos Szeredi97f044f2021-10-22 17:03:02 +0200839static void fuse_update_ctime_in_cache(struct inode *inode)
Maxim Patlasov31f32672014-04-28 14:19:24 +0200840{
841 if (!IS_NOCMTIME(inode)) {
Deepa Dinamanic2050a42016-09-14 07:48:06 -0700842 inode->i_ctime = current_time(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200843 mark_inode_dirty_sync(inode);
Miklos Szeredi5c791fe2021-10-22 17:03:01 +0200844 fuse_flush_time_update(inode);
Maxim Patlasov31f32672014-04-28 14:19:24 +0200845 }
846}
847
Miklos Szeredi97f044f2021-10-22 17:03:02 +0200848void fuse_update_ctime(struct inode *inode)
849{
Miklos Szeredifa5eee52021-10-22 17:03:02 +0200850 fuse_invalidate_attr_mask(inode, STATX_CTIME);
Miklos Szeredi97f044f2021-10-22 17:03:02 +0200851 fuse_update_ctime_in_cache(inode);
852}
853
Miklos Szeredicefd1b82021-10-22 17:03:02 +0200854static void fuse_entry_unlinked(struct dentry *entry)
855{
856 struct inode *inode = d_inode(entry);
857 struct fuse_conn *fc = get_fuse_conn(inode);
858 struct fuse_inode *fi = get_fuse_inode(inode);
859
860 spin_lock(&fi->lock);
861 fi->attr_version = atomic64_inc_return(&fc->attr_version);
862 /*
863 * If i_nlink == 0 then unlink doesn't make sense, yet this can
864 * happen if userspace filesystem is careless. It would be
865 * difficult to enforce correct nlink usage so just ignore this
866 * condition here
867 */
868 if (S_ISDIR(inode->i_mode))
869 clear_nlink(inode);
870 else if (inode->i_nlink > 0)
871 drop_nlink(inode);
872 spin_unlock(&fi->lock);
873 fuse_invalidate_entry_cache(entry);
874 fuse_update_ctime(inode);
875}
876
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700877static int fuse_unlink(struct inode *dir, struct dentry *entry)
878{
879 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200880 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100881 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700882
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100883 if (fuse_is_bad(dir))
884 return -EIO;
885
Miklos Szeredid5b48542019-09-10 15:04:08 +0200886 args.opcode = FUSE_UNLINK;
887 args.nodeid = get_node_id(dir);
888 args.in_numargs = 1;
889 args.in_args[0].size = entry->d_name.len + 1;
890 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200891 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700892 if (!err) {
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200893 fuse_dir_changed(dir);
Miklos Szeredicefd1b82021-10-22 17:03:02 +0200894 fuse_entry_unlinked(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700895 } else if (err == -EINTR)
896 fuse_invalidate_entry(entry);
897 return err;
898}
899
900static int fuse_rmdir(struct inode *dir, struct dentry *entry)
901{
902 int err;
Max Reitzfcee2162020-05-06 17:44:12 +0200903 struct fuse_mount *fm = get_fuse_mount(dir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100904 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700905
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100906 if (fuse_is_bad(dir))
907 return -EIO;
908
Miklos Szeredid5b48542019-09-10 15:04:08 +0200909 args.opcode = FUSE_RMDIR;
910 args.nodeid = get_node_id(dir);
911 args.in_numargs = 1;
912 args.in_args[0].size = entry->d_name.len + 1;
913 args.in_args[0].value = entry->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200914 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700915 if (!err) {
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200916 fuse_dir_changed(dir);
Miklos Szeredicefd1b82021-10-22 17:03:02 +0200917 fuse_entry_unlinked(entry);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700918 } else if (err == -EINTR)
919 fuse_invalidate_entry(entry);
920 return err;
921}
922
Miklos Szeredi1560c972014-04-28 16:43:44 +0200923static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
924 struct inode *newdir, struct dentry *newent,
925 unsigned int flags, int opcode, size_t argsize)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700926{
927 int err;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200928 struct fuse_rename2_in inarg;
Max Reitzfcee2162020-05-06 17:44:12 +0200929 struct fuse_mount *fm = get_fuse_mount(olddir);
Miklos Szeredi70781872014-12-12 09:49:05 +0100930 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700931
Miklos Szeredi1560c972014-04-28 16:43:44 +0200932 memset(&inarg, 0, argsize);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700933 inarg.newdir = get_node_id(newdir);
Miklos Szeredi1560c972014-04-28 16:43:44 +0200934 inarg.flags = flags;
Miklos Szeredid5b48542019-09-10 15:04:08 +0200935 args.opcode = opcode;
936 args.nodeid = get_node_id(olddir);
937 args.in_numargs = 3;
938 args.in_args[0].size = argsize;
939 args.in_args[0].value = &inarg;
940 args.in_args[1].size = oldent->d_name.len + 1;
941 args.in_args[1].value = oldent->d_name.name;
942 args.in_args[2].size = newent->d_name.len + 1;
943 args.in_args[2].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +0200944 err = fuse_simple_request(fm, &args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700945 if (!err) {
Miklos Szeredi08b63302007-11-28 16:22:03 -0800946 /* ctime changes */
David Howells2b0143b2015-03-17 22:25:59 +0000947 fuse_update_ctime(d_inode(oldent));
Miklos Szeredi08b63302007-11-28 16:22:03 -0800948
Miklos Szeredi371e8fd2021-10-22 17:03:01 +0200949 if (flags & RENAME_EXCHANGE)
David Howells2b0143b2015-03-17 22:25:59 +0000950 fuse_update_ctime(d_inode(newent));
Miklos Szeredi1560c972014-04-28 16:43:44 +0200951
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200952 fuse_dir_changed(olddir);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700953 if (olddir != newdir)
Miklos Szeredi261aaba72018-10-01 10:07:05 +0200954 fuse_dir_changed(newdir);
Miklos Szeredi8cbdf1e2006-01-06 00:19:38 -0800955
956 /* newent will end up negative */
Miklos Szeredicefd1b82021-10-22 17:03:02 +0200957 if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent))
958 fuse_entry_unlinked(newent);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700959 } else if (err == -EINTR) {
960 /* If request was interrupted, DEITY only knows if the
961 rename actually took place. If the invalidation
962 fails (e.g. some process has CWD under the renamed
963 directory), then there can be inconsistency between
964 the dcache and the real filesystem. Tough luck. */
965 fuse_invalidate_entry(oldent);
David Howells2b0143b2015-03-17 22:25:59 +0000966 if (d_really_is_positive(newent))
Miklos Szeredi9e6268d2005-09-09 13:10:29 -0700967 fuse_invalidate_entry(newent);
968 }
969
970 return err;
971}
972
Christian Brauner549c7292021-01-21 14:19:43 +0100973static int fuse_rename2(struct user_namespace *mnt_userns, struct inode *olddir,
974 struct dentry *oldent, struct inode *newdir,
975 struct dentry *newent, unsigned int flags)
Miklos Szeredi1560c972014-04-28 16:43:44 +0200976{
977 struct fuse_conn *fc = get_fuse_conn(olddir);
978 int err;
979
Miklos Szeredi5d069db2020-12-10 15:33:14 +0100980 if (fuse_is_bad(olddir))
981 return -EIO;
982
Vivek Goyal519525f2020-02-05 08:15:46 -0500983 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
Miklos Szeredi1560c972014-04-28 16:43:44 +0200984 return -EINVAL;
985
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200986 if (flags) {
987 if (fc->no_rename2 || fc->minor < 23)
988 return -EINVAL;
Miklos Szeredi1560c972014-04-28 16:43:44 +0200989
Miklos Szeredi4237ba42014-07-10 10:50:19 +0200990 err = fuse_rename_common(olddir, oldent, newdir, newent, flags,
991 FUSE_RENAME2,
992 sizeof(struct fuse_rename2_in));
993 if (err == -ENOSYS) {
994 fc->no_rename2 = 1;
995 err = -EINVAL;
996 }
997 } else {
998 err = fuse_rename_common(olddir, oldent, newdir, newent, 0,
999 FUSE_RENAME,
1000 sizeof(struct fuse_rename_in));
Miklos Szeredi1560c972014-04-28 16:43:44 +02001001 }
Miklos Szeredi1560c972014-04-28 16:43:44 +02001002
Miklos Szeredi4237ba42014-07-10 10:50:19 +02001003 return err;
1004}
1005
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001006static int fuse_link(struct dentry *entry, struct inode *newdir,
1007 struct dentry *newent)
1008{
1009 int err;
1010 struct fuse_link_in inarg;
David Howells2b0143b2015-03-17 22:25:59 +00001011 struct inode *inode = d_inode(entry);
Max Reitzfcee2162020-05-06 17:44:12 +02001012 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001013 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001014
1015 memset(&inarg, 0, sizeof(inarg));
1016 inarg.oldnodeid = get_node_id(inode);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001017 args.opcode = FUSE_LINK;
1018 args.in_numargs = 2;
1019 args.in_args[0].size = sizeof(inarg);
1020 args.in_args[0].value = &inarg;
1021 args.in_args[1].size = newent->d_name.len + 1;
1022 args.in_args[1].value = newent->d_name.name;
Max Reitzfcee2162020-05-06 17:44:12 +02001023 err = create_new_entry(fm, &args, newdir, newent, inode->i_mode);
Miklos Szeredi97f044f2021-10-22 17:03:02 +02001024 if (!err)
1025 fuse_update_ctime_in_cache(inode);
1026 else if (err == -EINTR)
Miklos Szerediac45d612012-03-05 15:48:11 +01001027 fuse_invalidate_attr(inode);
Miklos Szeredi97f044f2021-10-22 17:03:02 +02001028
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001029 return err;
1030}
1031
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001032static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
1033 struct kstat *stat)
1034{
Miklos Szeredi203627b2012-05-10 19:49:38 +04001035 unsigned int blkbits;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001036 struct fuse_conn *fc = get_fuse_conn(inode);
1037
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001038 stat->dev = inode->i_sb->s_dev;
1039 stat->ino = attr->ino;
1040 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
1041 stat->nlink = attr->nlink;
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001042 stat->uid = make_kuid(fc->user_ns, attr->uid);
1043 stat->gid = make_kgid(fc->user_ns, attr->gid);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001044 stat->rdev = inode->i_rdev;
1045 stat->atime.tv_sec = attr->atime;
1046 stat->atime.tv_nsec = attr->atimensec;
1047 stat->mtime.tv_sec = attr->mtime;
1048 stat->mtime.tv_nsec = attr->mtimensec;
1049 stat->ctime.tv_sec = attr->ctime;
1050 stat->ctime.tv_nsec = attr->ctimensec;
1051 stat->size = attr->size;
1052 stat->blocks = attr->blocks;
Miklos Szeredi203627b2012-05-10 19:49:38 +04001053
1054 if (attr->blksize != 0)
1055 blkbits = ilog2(attr->blksize);
1056 else
1057 blkbits = inode->i_sb->s_blocksize_bits;
1058
1059 stat->blksize = 1 << blkbits;
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001060}
1061
Miklos Szeredic79e3222007-10-18 03:06:59 -07001062static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
1063 struct file *file)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001064{
1065 int err;
Miklos Szeredic79e3222007-10-18 03:06:59 -07001066 struct fuse_getattr_in inarg;
1067 struct fuse_attr_out outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001068 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001069 FUSE_ARGS(args);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001070 u64 attr_version;
1071
Max Reitzfcee2162020-05-06 17:44:12 +02001072 attr_version = fuse_get_attr_version(fm->fc);
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001073
Miklos Szeredic79e3222007-10-18 03:06:59 -07001074 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001075 memset(&outarg, 0, sizeof(outarg));
Miklos Szeredic79e3222007-10-18 03:06:59 -07001076 /* Directories have separate file-handle space */
1077 if (file && S_ISREG(inode->i_mode)) {
1078 struct fuse_file *ff = file->private_data;
1079
1080 inarg.getattr_flags |= FUSE_GETATTR_FH;
1081 inarg.fh = ff->fh;
1082 }
Miklos Szeredid5b48542019-09-10 15:04:08 +02001083 args.opcode = FUSE_GETATTR;
1084 args.nodeid = get_node_id(inode);
1085 args.in_numargs = 1;
1086 args.in_args[0].size = sizeof(inarg);
1087 args.in_args[0].value = &inarg;
1088 args.out_numargs = 1;
1089 args.out_args[0].size = sizeof(outarg);
1090 args.out_args[0].value = &outarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001091 err = fuse_simple_request(fm, &args);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001092 if (!err) {
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001093 if (fuse_invalid_attr(&outarg.attr) ||
Al Viro6e3e2c42021-03-01 20:37:10 -05001094 inode_wrong_type(inode, outarg.attr.mode)) {
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001095 fuse_make_bad(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001096 err = -EIO;
1097 } else {
Miklos Szeredic79e3222007-10-18 03:06:59 -07001098 fuse_change_attributes(inode, &outarg.attr,
1099 attr_timeout(&outarg),
Miklos Szeredi1fb69e72007-10-18 03:06:58 -07001100 attr_version);
1101 if (stat)
Miklos Szeredic79e3222007-10-18 03:06:59 -07001102 fuse_fillattr(inode, &outarg.attr, stat);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001103 }
1104 }
1105 return err;
1106}
1107
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001108static int fuse_update_get_attr(struct inode *inode, struct file *file,
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001109 struct kstat *stat, u32 request_mask,
1110 unsigned int flags)
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001111{
1112 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001113 int err = 0;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001114 bool sync;
Miklos Szerediec855372021-10-22 17:03:03 +02001115 u32 inval_mask = READ_ONCE(fi->inval_mask);
1116 u32 cache_mask = fuse_get_cache_mask(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001117
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001118 if (flags & AT_STATX_FORCE_SYNC)
1119 sync = true;
1120 else if (flags & AT_STATX_DONT_SYNC)
1121 sync = false;
Miklos Szerediec855372021-10-22 17:03:03 +02001122 else if (request_mask & inval_mask & ~cache_mask)
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001123 sync = true;
Miklos Szeredibf5c1892018-03-20 17:11:44 +01001124 else
1125 sync = time_before64(fi->i_time, get_jiffies_64());
1126
1127 if (sync) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001128 forget_all_cached_acls(inode);
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001129 err = fuse_do_getattr(inode, stat, file);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001130 } else if (stat) {
Christian Brauner0d56a452021-01-21 14:19:30 +01001131 generic_fillattr(&init_user_ns, inode, stat);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001132 stat->mode = fi->orig_i_mode;
1133 stat->ino = fi->orig_ino;
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001134 }
1135
Miklos Szeredibcb4be82007-11-28 16:21:59 -08001136 return err;
1137}
1138
Miklos Szeredic6c745b2021-10-22 17:03:03 +02001139int fuse_update_attributes(struct inode *inode, struct file *file, u32 mask)
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001140{
Miklos Szeredic6c745b2021-10-22 17:03:03 +02001141 return fuse_update_get_attr(inode, file, NULL, mask, 0);
Miklos Szeredi5b97eea2017-09-12 16:57:54 +02001142}
1143
Max Reitzfcee2162020-05-06 17:44:12 +02001144int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid,
John Muir451d0f52011-12-06 21:50:06 +01001145 u64 child_nodeid, struct qstr *name)
John Muir3b463ae2009-05-31 11:13:57 -04001146{
1147 int err = -ENOTDIR;
1148 struct inode *parent;
1149 struct dentry *dir;
1150 struct dentry *entry;
1151
Max Reitzfcee2162020-05-06 17:44:12 +02001152 parent = fuse_ilookup(fc, parent_nodeid, NULL);
John Muir3b463ae2009-05-31 11:13:57 -04001153 if (!parent)
1154 return -ENOENT;
1155
Miklos Szeredibda9a712021-10-22 17:03:01 +02001156 inode_lock_nested(parent, I_MUTEX_PARENT);
John Muir3b463ae2009-05-31 11:13:57 -04001157 if (!S_ISDIR(parent->i_mode))
1158 goto unlock;
1159
1160 err = -ENOENT;
1161 dir = d_find_alias(parent);
1162 if (!dir)
1163 goto unlock;
1164
Linus Torvalds8387ff22016-06-10 07:51:30 -07001165 name->hash = full_name_hash(dir, name->name, name->len);
John Muir3b463ae2009-05-31 11:13:57 -04001166 entry = d_lookup(dir, name);
1167 dput(dir);
1168 if (!entry)
1169 goto unlock;
1170
Miklos Szeredi261aaba72018-10-01 10:07:05 +02001171 fuse_dir_changed(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001172 fuse_invalidate_entry(entry);
John Muir451d0f52011-12-06 21:50:06 +01001173
David Howells2b0143b2015-03-17 22:25:59 +00001174 if (child_nodeid != 0 && d_really_is_positive(entry)) {
Al Viro59551022016-01-22 15:40:57 -05001175 inode_lock(d_inode(entry));
David Howells2b0143b2015-03-17 22:25:59 +00001176 if (get_node_id(d_inode(entry)) != child_nodeid) {
John Muir451d0f52011-12-06 21:50:06 +01001177 err = -ENOENT;
1178 goto badentry;
1179 }
1180 if (d_mountpoint(entry)) {
1181 err = -EBUSY;
1182 goto badentry;
1183 }
David Howellse36cb0b2015-01-29 12:02:35 +00001184 if (d_is_dir(entry)) {
John Muir451d0f52011-12-06 21:50:06 +01001185 shrink_dcache_parent(entry);
1186 if (!simple_empty(entry)) {
1187 err = -ENOTEMPTY;
1188 goto badentry;
1189 }
David Howells2b0143b2015-03-17 22:25:59 +00001190 d_inode(entry)->i_flags |= S_DEAD;
John Muir451d0f52011-12-06 21:50:06 +01001191 }
1192 dont_mount(entry);
David Howells2b0143b2015-03-17 22:25:59 +00001193 clear_nlink(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001194 err = 0;
1195 badentry:
Al Viro59551022016-01-22 15:40:57 -05001196 inode_unlock(d_inode(entry));
John Muir451d0f52011-12-06 21:50:06 +01001197 if (!err)
1198 d_delete(entry);
1199 } else {
1200 err = 0;
1201 }
John Muir3b463ae2009-05-31 11:13:57 -04001202 dput(entry);
John Muir3b463ae2009-05-31 11:13:57 -04001203
1204 unlock:
Al Viro59551022016-01-22 15:40:57 -05001205 inode_unlock(parent);
John Muir3b463ae2009-05-31 11:13:57 -04001206 iput(parent);
1207 return err;
1208}
1209
Miklos Szeredi87729a52005-09-09 13:10:34 -07001210/*
1211 * Calling into a user-controlled filesystem gives the filesystem
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001212 * daemon ptrace-like capabilities over the current process. This
Miklos Szeredi87729a52005-09-09 13:10:34 -07001213 * means, that the filesystem daemon is able to record the exact
1214 * filesystem operations performed, and can also control the behavior
1215 * of the requester process in otherwise impossible ways. For example
1216 * it can delay the operation for arbitrary length of time allowing
1217 * DoS against the requester.
1218 *
1219 * For this reason only those processes can call into the filesystem,
1220 * for which the owner of the mount has ptrace privilege. This
1221 * excludes processes started by other users, suid or sgid processes.
1222 */
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001223int fuse_allow_current_process(struct fuse_conn *fc)
Miklos Szeredi87729a52005-09-09 13:10:34 -07001224{
David Howellsc69e8d92008-11-14 10:39:19 +11001225 const struct cred *cred;
David Howellsc69e8d92008-11-14 10:39:19 +11001226
Miklos Szeredi29433a22016-10-01 07:32:32 +02001227 if (fc->allow_other)
Seth Forshee73f03c22017-12-22 15:32:33 +01001228 return current_in_userns(fc->user_ns);
Miklos Szeredi87729a52005-09-09 13:10:34 -07001229
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001230 cred = current_cred();
Eric W. Biederman499dcf22012-02-07 16:26:03 -08001231 if (uid_eq(cred->euid, fc->user_id) &&
1232 uid_eq(cred->suid, fc->user_id) &&
1233 uid_eq(cred->uid, fc->user_id) &&
1234 gid_eq(cred->egid, fc->group_id) &&
1235 gid_eq(cred->sgid, fc->group_id) &&
1236 gid_eq(cred->gid, fc->group_id))
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001237 return 1;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001238
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001239 return 0;
Miklos Szeredi87729a52005-09-09 13:10:34 -07001240}
1241
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001242static int fuse_access(struct inode *inode, int mask)
1243{
Max Reitzfcee2162020-05-06 17:44:12 +02001244 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001245 FUSE_ARGS(args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001246 struct fuse_access_in inarg;
1247 int err;
1248
Miklos Szeredi698fa1d2013-10-01 16:41:23 +02001249 BUG_ON(mask & MAY_NOT_BLOCK);
1250
Max Reitzfcee2162020-05-06 17:44:12 +02001251 if (fm->fc->no_access)
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001252 return 0;
1253
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001254 memset(&inarg, 0, sizeof(inarg));
Al Viroe6305c42008-07-15 21:03:57 -04001255 inarg.mask = mask & (MAY_READ | MAY_WRITE | MAY_EXEC);
Miklos Szeredid5b48542019-09-10 15:04:08 +02001256 args.opcode = FUSE_ACCESS;
1257 args.nodeid = get_node_id(inode);
1258 args.in_numargs = 1;
1259 args.in_args[0].size = sizeof(inarg);
1260 args.in_args[0].value = &inarg;
Max Reitzfcee2162020-05-06 17:44:12 +02001261 err = fuse_simple_request(fm, &args);
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001262 if (err == -ENOSYS) {
Max Reitzfcee2162020-05-06 17:44:12 +02001263 fm->fc->no_access = 1;
Miklos Szeredi31d40d72005-11-07 00:59:50 -08001264 err = 0;
1265 }
1266 return err;
1267}
1268
Al Viro10556cb22011-06-20 19:28:19 -04001269static int fuse_perm_getattr(struct inode *inode, int mask)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001270{
Al Viro10556cb22011-06-20 19:28:19 -04001271 if (mask & MAY_NOT_BLOCK)
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001272 return -ECHILD;
1273
Seth Forshee60bcc882016-08-29 08:46:37 -05001274 forget_all_cached_acls(inode);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001275 return fuse_do_getattr(inode, NULL, NULL);
1276}
1277
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001278/*
1279 * Check permission. The two basic access models of FUSE are:
1280 *
1281 * 1) Local access checking ('default_permissions' mount option) based
1282 * on file mode. This is the plain old disk filesystem permission
1283 * modell.
1284 *
1285 * 2) "Remote" access checking, where server is responsible for
1286 * checking permission in each inode operation. An exception to this
1287 * is if ->permission() was invoked from sys_access() in which case an
1288 * access request is sent. Execute permission is still checked
1289 * locally based on file mode.
1290 */
Christian Brauner549c7292021-01-21 14:19:43 +01001291static int fuse_permission(struct user_namespace *mnt_userns,
1292 struct inode *inode, int mask)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001293{
1294 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001295 bool refreshed = false;
1296 int err = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001297
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001298 if (fuse_is_bad(inode))
1299 return -EIO;
1300
Anatol Pomozovc2132c12013-01-14 22:30:00 -08001301 if (!fuse_allow_current_process(fc))
Miklos Szeredie5e55582005-09-09 13:10:28 -07001302 return -EACCES;
Miklos Szeredi244f6382007-10-16 23:31:02 -07001303
1304 /*
Miklos Szeredie8e96152007-10-16 23:31:06 -07001305 * If attributes are needed, refresh them before proceeding
Miklos Szeredi244f6382007-10-16 23:31:02 -07001306 */
Miklos Szeredi29433a22016-10-01 07:32:32 +02001307 if (fc->default_permissions ||
Miklos Szeredie8e96152007-10-16 23:31:06 -07001308 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001309 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001310 u32 perm_mask = STATX_MODE | STATX_UID | STATX_GID;
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001311
Miklos Szeredid233c7d2018-12-03 10:14:43 +01001312 if (perm_mask & READ_ONCE(fi->inval_mask) ||
1313 time_before64(fi->i_time, get_jiffies_64())) {
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001314 refreshed = true;
1315
Al Viro10556cb22011-06-20 19:28:19 -04001316 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi19690dd2011-03-21 13:58:06 +01001317 if (err)
1318 return err;
1319 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001320 }
1321
Miklos Szeredi29433a22016-10-01 07:32:32 +02001322 if (fc->default_permissions) {
Christian Brauner47291ba2021-01-21 14:19:24 +01001323 err = generic_permission(&init_user_ns, inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001324
1325 /* If permission is denied, try to refresh file
1326 attributes. This is also needed, because the root
1327 node will at first have no permissions */
Miklos Szeredi244f6382007-10-16 23:31:02 -07001328 if (err == -EACCES && !refreshed) {
Al Viro10556cb22011-06-20 19:28:19 -04001329 err = fuse_perm_getattr(inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001330 if (!err)
Christian Brauner47291ba2021-01-21 14:19:24 +01001331 err = generic_permission(&init_user_ns,
1332 inode, mask);
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001333 }
1334
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001335 /* Note: the opposite of the above test does not
1336 exist. So if permissions are revoked this won't be
1337 noticed immediately, only after the attribute
1338 timeout has expired */
Eric Paris9cfcac82010-07-23 11:43:51 -04001339 } else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
Miklos Szeredie8e96152007-10-16 23:31:06 -07001340 err = fuse_access(inode, mask);
1341 } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
1342 if (!(inode->i_mode & S_IXUGO)) {
1343 if (refreshed)
1344 return -EACCES;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001345
Al Viro10556cb22011-06-20 19:28:19 -04001346 err = fuse_perm_getattr(inode, mask);
Miklos Szeredie8e96152007-10-16 23:31:06 -07001347 if (!err && !(inode->i_mode & S_IXUGO))
1348 return -EACCES;
1349 }
Miklos Szeredie5e55582005-09-09 13:10:28 -07001350 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001351 return err;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001352}
1353
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001354static int fuse_readlink_page(struct inode *inode, struct page *page)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001355{
Max Reitzfcee2162020-05-06 17:44:12 +02001356 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001357 struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1358 struct fuse_args_pages ap = {
1359 .num_pages = 1,
1360 .pages = &page,
1361 .descs = &desc,
1362 };
1363 char *link;
1364 ssize_t res;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001365
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001366 ap.args.opcode = FUSE_READLINK;
1367 ap.args.nodeid = get_node_id(inode);
1368 ap.args.out_pages = true;
1369 ap.args.out_argvar = true;
1370 ap.args.page_zeroing = true;
1371 ap.args.out_numargs = 1;
1372 ap.args.out_args[0].size = desc.length;
Max Reitzfcee2162020-05-06 17:44:12 +02001373 res = fuse_simple_request(fm, &ap.args);
Al Viro6b255392015-11-17 10:20:54 -05001374
Andrew Gallagher451418f2013-11-05 03:55:43 -08001375 fuse_invalidate_atime(inode);
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001376
Miklos Szeredi4c29afe2019-09-10 15:04:09 +02001377 if (res < 0)
1378 return res;
1379
1380 if (WARN_ON(res >= PAGE_SIZE))
1381 return -EIO;
1382
1383 link = page_address(page);
1384 link[res] = '\0';
1385
1386 return 0;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001387}
1388
1389static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
1390 struct delayed_call *callback)
1391{
1392 struct fuse_conn *fc = get_fuse_conn(inode);
1393 struct page *page;
1394 int err;
1395
1396 err = -EIO;
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001397 if (fuse_is_bad(inode))
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001398 goto out_err;
1399
1400 if (fc->cache_symlinks)
1401 return page_get_link(dentry, inode, callback);
1402
1403 err = -ECHILD;
1404 if (!dentry)
1405 goto out_err;
1406
1407 page = alloc_page(GFP_KERNEL);
1408 err = -ENOMEM;
1409 if (!page)
1410 goto out_err;
1411
1412 err = fuse_readlink_page(inode, page);
1413 if (err) {
1414 __free_page(page);
1415 goto out_err;
1416 }
1417
1418 set_delayed_call(callback, page_put_link, page);
1419
1420 return page_address(page);
1421
1422out_err:
1423 return ERR_PTR(err);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001424}
1425
Miklos Szeredie5e55582005-09-09 13:10:28 -07001426static int fuse_dir_open(struct inode *inode, struct file *file)
1427{
Miklos Szeredi91fe96b2009-04-28 16:56:37 +02001428 return fuse_open_common(inode, file, true);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001429}
1430
1431static int fuse_dir_release(struct inode *inode, struct file *file)
1432{
Chad Austin2e64ff12018-12-10 10:54:52 -08001433 fuse_release_common(file, true);
Miklos Szeredi8b0797a2009-04-28 16:56:39 +02001434
1435 return 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001436}
1437
Josef Bacik02c24a82011-07-16 20:44:56 -04001438static int fuse_dir_fsync(struct file *file, loff_t start, loff_t end,
1439 int datasync)
Miklos Szeredi82547982005-09-09 13:10:38 -07001440{
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001441 struct inode *inode = file->f_mapping->host;
1442 struct fuse_conn *fc = get_fuse_conn(inode);
1443 int err;
1444
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001445 if (fuse_is_bad(inode))
Miklos Szeredia9c2d1e2018-12-03 10:14:43 +01001446 return -EIO;
1447
1448 if (fc->no_fsyncdir)
1449 return 0;
1450
1451 inode_lock(inode);
1452 err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNCDIR);
1453 if (err == -ENOSYS) {
1454 fc->no_fsyncdir = 1;
1455 err = 0;
1456 }
1457 inode_unlock(inode);
1458
1459 return err;
Miklos Szeredi82547982005-09-09 13:10:38 -07001460}
1461
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001462static long fuse_dir_ioctl(struct file *file, unsigned int cmd,
1463 unsigned long arg)
1464{
1465 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1466
1467 /* FUSE_IOCTL_DIR only supported for API version >= 7.18 */
1468 if (fc->minor < 18)
1469 return -ENOTTY;
1470
1471 return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_DIR);
1472}
1473
1474static long fuse_dir_compat_ioctl(struct file *file, unsigned int cmd,
1475 unsigned long arg)
1476{
1477 struct fuse_conn *fc = get_fuse_conn(file->f_mapping->host);
1478
1479 if (fc->minor < 18)
1480 return -ENOTTY;
1481
1482 return fuse_ioctl_common(file, cmd, arg,
1483 FUSE_IOCTL_COMPAT | FUSE_IOCTL_DIR);
1484}
1485
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001486static bool update_mtime(unsigned ivalid, bool trust_local_mtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001487{
1488 /* Always update if mtime is explicitly set */
1489 if (ivalid & ATTR_MTIME_SET)
1490 return true;
1491
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001492 /* Or if kernel i_mtime is the official one */
1493 if (trust_local_mtime)
1494 return true;
1495
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001496 /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
1497 if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
1498 return false;
1499
1500 /* In all other cases update */
1501 return true;
1502}
1503
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001504static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr,
1505 struct fuse_setattr_in *arg, bool trust_local_cmtime)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001506{
1507 unsigned ivalid = iattr->ia_valid;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001508
1509 if (ivalid & ATTR_MODE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001510 arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001511 if (ivalid & ATTR_UID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001512 arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001513 if (ivalid & ATTR_GID)
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001514 arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001515 if (ivalid & ATTR_SIZE)
Miklos Szeredibefc6492005-11-07 00:59:52 -08001516 arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001517 if (ivalid & ATTR_ATIME) {
1518 arg->valid |= FATTR_ATIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001519 arg->atime = iattr->ia_atime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001520 arg->atimensec = iattr->ia_atime.tv_nsec;
1521 if (!(ivalid & ATTR_ATIME_SET))
1522 arg->valid |= FATTR_ATIME_NOW;
1523 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001524 if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, trust_local_cmtime)) {
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001525 arg->valid |= FATTR_MTIME;
Miklos Szeredibefc6492005-11-07 00:59:52 -08001526 arg->mtime = iattr->ia_mtime.tv_sec;
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001527 arg->mtimensec = iattr->ia_mtime.tv_nsec;
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001528 if (!(ivalid & ATTR_MTIME_SET) && !trust_local_cmtime)
Miklos Szeredi17637cb2007-10-18 03:07:01 -07001529 arg->valid |= FATTR_MTIME_NOW;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001530 }
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001531 if ((ivalid & ATTR_CTIME) && trust_local_cmtime) {
1532 arg->valid |= FATTR_CTIME;
1533 arg->ctime = iattr->ia_ctime.tv_sec;
1534 arg->ctimensec = iattr->ia_ctime.tv_nsec;
1535 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001536}
1537
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001538/*
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001539 * Prevent concurrent writepages on inode
1540 *
1541 * This is done by adding a negative bias to the inode write counter
1542 * and waiting for all pending writes to finish.
1543 */
1544void fuse_set_nowrite(struct inode *inode)
1545{
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001546 struct fuse_inode *fi = get_fuse_inode(inode);
1547
Al Viro59551022016-01-22 15:40:57 -05001548 BUG_ON(!inode_is_locked(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001549
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001550 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001551 BUG_ON(fi->writectr < 0);
1552 fi->writectr += FUSE_NOWRITE;
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001553 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001554 wait_event(fi->page_waitq, fi->writectr == FUSE_NOWRITE);
1555}
1556
1557/*
1558 * Allow writepages on inode
1559 *
1560 * Remove the bias from the writecounter and send any queued
1561 * writepages.
1562 */
1563static void __fuse_release_nowrite(struct inode *inode)
1564{
1565 struct fuse_inode *fi = get_fuse_inode(inode);
1566
1567 BUG_ON(fi->writectr != FUSE_NOWRITE);
1568 fi->writectr = 0;
1569 fuse_flush_writepages(inode);
1570}
1571
1572void fuse_release_nowrite(struct inode *inode)
1573{
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001574 struct fuse_inode *fi = get_fuse_inode(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001575
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001576 spin_lock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001577 __fuse_release_nowrite(inode);
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001578 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001579}
1580
Miklos Szeredi70781872014-12-12 09:49:05 +01001581static void fuse_setattr_fill(struct fuse_conn *fc, struct fuse_args *args,
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001582 struct inode *inode,
1583 struct fuse_setattr_in *inarg_p,
1584 struct fuse_attr_out *outarg_p)
1585{
Miklos Szeredid5b48542019-09-10 15:04:08 +02001586 args->opcode = FUSE_SETATTR;
1587 args->nodeid = get_node_id(inode);
1588 args->in_numargs = 1;
1589 args->in_args[0].size = sizeof(*inarg_p);
1590 args->in_args[0].value = inarg_p;
1591 args->out_numargs = 1;
1592 args->out_args[0].size = sizeof(*outarg_p);
1593 args->out_args[0].value = outarg_p;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001594}
1595
1596/*
1597 * Flush inode->i_mtime to the server
1598 */
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001599int fuse_flush_times(struct inode *inode, struct fuse_file *ff)
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001600{
Max Reitzfcee2162020-05-06 17:44:12 +02001601 struct fuse_mount *fm = get_fuse_mount(inode);
Miklos Szeredi70781872014-12-12 09:49:05 +01001602 FUSE_ARGS(args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001603 struct fuse_setattr_in inarg;
1604 struct fuse_attr_out outarg;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001605
1606 memset(&inarg, 0, sizeof(inarg));
1607 memset(&outarg, 0, sizeof(outarg));
1608
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001609 inarg.valid = FATTR_MTIME;
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001610 inarg.mtime = inode->i_mtime.tv_sec;
1611 inarg.mtimensec = inode->i_mtime.tv_nsec;
Max Reitzfcee2162020-05-06 17:44:12 +02001612 if (fm->fc->minor >= 23) {
Maxim Patlasovab9e13f2014-04-28 14:19:24 +02001613 inarg.valid |= FATTR_CTIME;
1614 inarg.ctime = inode->i_ctime.tv_sec;
1615 inarg.ctimensec = inode->i_ctime.tv_nsec;
1616 }
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001617 if (ff) {
1618 inarg.valid |= FATTR_FH;
1619 inarg.fh = ff->fh;
1620 }
Max Reitzfcee2162020-05-06 17:44:12 +02001621 fuse_setattr_fill(fm->fc, &args, inode, &inarg, &outarg);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001622
Max Reitzfcee2162020-05-06 17:44:12 +02001623 return fuse_simple_request(fm, &args);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001624}
1625
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001626/*
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001627 * Set attributes, and at the same time refresh them.
1628 *
1629 * Truncation is slightly complicated, because the 'truncate' request
1630 * may fail, in which case we don't want to touch the mapping.
Miklos Szeredi9ffbb912006-10-17 00:10:06 -07001631 * vmtruncate() doesn't allow for this case, so do the rlimit checking
1632 * and the actual truncation by hand.
Miklos Szeredi6f9f1182006-01-06 00:19:39 -08001633 */
Jan Kara62490332016-05-26 17:12:41 +02001634int fuse_do_setattr(struct dentry *dentry, struct iattr *attr,
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001635 struct file *file)
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001636{
Jan Kara62490332016-05-26 17:12:41 +02001637 struct inode *inode = d_inode(dentry);
Max Reitzfcee2162020-05-06 17:44:12 +02001638 struct fuse_mount *fm = get_fuse_mount(inode);
1639 struct fuse_conn *fc = fm->fc;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001640 struct fuse_inode *fi = get_fuse_inode(inode);
Jan Kara8bcbbe92021-04-21 17:18:39 +02001641 struct address_space *mapping = inode->i_mapping;
Miklos Szeredi70781872014-12-12 09:49:05 +01001642 FUSE_ARGS(args);
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001643 struct fuse_setattr_in inarg;
1644 struct fuse_attr_out outarg;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001645 bool is_truncate = false;
Miklos Szeredic15016b2021-10-22 17:03:03 +02001646 bool is_wb = fc->writeback_cache && S_ISREG(inode->i_mode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001647 loff_t oldsize;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001648 int err;
Miklos Szeredic15016b2021-10-22 17:03:03 +02001649 bool trust_local_cmtime = is_wb;
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001650 bool fault_blocked = false;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001651
Miklos Szeredi29433a22016-10-01 07:32:32 +02001652 if (!fc->default_permissions)
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001653 attr->ia_valid |= ATTR_FORCE;
1654
Christian Brauner2f221d62021-01-21 14:19:26 +01001655 err = setattr_prepare(&init_user_ns, dentry, attr);
Christoph Hellwigdb78b872010-06-04 11:30:03 +02001656 if (err)
1657 return err;
Miklos Szeredi1e9a4ed2005-09-09 13:10:31 -07001658
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001659 if (attr->ia_valid & ATTR_SIZE) {
1660 if (WARN_ON(!S_ISREG(inode->i_mode)))
1661 return -EIO;
1662 is_truncate = true;
1663 }
1664
1665 if (FUSE_IS_DAX(inode) && is_truncate) {
Jan Kara8bcbbe92021-04-21 17:18:39 +02001666 filemap_invalidate_lock(mapping);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001667 fault_blocked = true;
1668 err = fuse_dax_break_layouts(inode, 0, 0);
1669 if (err) {
Jan Kara8bcbbe92021-04-21 17:18:39 +02001670 filemap_invalidate_unlock(mapping);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001671 return err;
1672 }
1673 }
1674
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001675 if (attr->ia_valid & ATTR_OPEN) {
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001676 /* This is coming from open(..., ... | O_TRUNC); */
1677 WARN_ON(!(attr->ia_valid & ATTR_SIZE));
1678 WARN_ON(attr->ia_size != 0);
1679 if (fc->atomic_o_trunc) {
1680 /*
1681 * No need to send request to userspace, since actual
1682 * truncation has already been done by OPEN. But still
1683 * need to truncate page cache.
1684 */
1685 i_size_write(inode, 0);
1686 truncate_pagecache(inode, 0);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001687 goto out;
Miklos Szeredidf0e91d2018-02-08 15:17:38 +01001688 }
Miklos Szeredi8d56add2011-02-25 14:44:58 +01001689 file = NULL;
1690 }
Miklos Szeredi6ff958e2007-10-18 03:07:02 -07001691
Miklos Szeredib24e7592019-10-23 14:26:37 +02001692 /* Flush dirty data/metadata before non-truncate SETATTR */
Miklos Szeredic15016b2021-10-22 17:03:03 +02001693 if (is_wb &&
Miklos Szeredib24e7592019-10-23 14:26:37 +02001694 attr->ia_valid &
1695 (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET |
1696 ATTR_TIMES_SET)) {
1697 err = write_inode_now(inode, true);
1698 if (err)
1699 return err;
1700
1701 fuse_set_nowrite(inode);
1702 fuse_release_nowrite(inode);
1703 }
1704
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001705 if (is_truncate) {
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001706 fuse_set_nowrite(inode);
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001707 set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001708 if (trust_local_cmtime && attr->ia_size != inode->i_size)
1709 attr->ia_valid |= ATTR_MTIME | ATTR_CTIME;
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001710 }
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001711
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001712 memset(&inarg, 0, sizeof(inarg));
Miklos Szeredi0e9663e2007-10-18 03:07:05 -07001713 memset(&outarg, 0, sizeof(outarg));
Eric W. Biederman8cb08322018-02-21 11:18:07 -06001714 iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime);
Miklos Szeredi49d49142007-10-18 03:07:00 -07001715 if (file) {
1716 struct fuse_file *ff = file->private_data;
1717 inarg.valid |= FATTR_FH;
1718 inarg.fh = ff->fh;
1719 }
Vivek Goyal31792162020-10-09 14:15:09 -04001720
1721 /* Kill suid/sgid for non-directory chown unconditionally */
1722 if (fc->handle_killpriv_v2 && !S_ISDIR(inode->i_mode) &&
1723 attr->ia_valid & (ATTR_UID | ATTR_GID))
1724 inarg.valid |= FATTR_KILL_SUIDGID;
1725
Miklos Szeredif3332112007-10-18 03:07:04 -07001726 if (attr->ia_valid & ATTR_SIZE) {
1727 /* For mandatory locking in truncate */
1728 inarg.valid |= FATTR_LOCKOWNER;
1729 inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
Vivek Goyal31792162020-10-09 14:15:09 -04001730
1731 /* Kill suid/sgid for truncate only if no CAP_FSETID */
1732 if (fc->handle_killpriv_v2 && !capable(CAP_FSETID))
1733 inarg.valid |= FATTR_KILL_SUIDGID;
Miklos Szeredif3332112007-10-18 03:07:04 -07001734 }
Miklos Szeredi70781872014-12-12 09:49:05 +01001735 fuse_setattr_fill(fc, &args, inode, &inarg, &outarg);
Max Reitzfcee2162020-05-06 17:44:12 +02001736 err = fuse_simple_request(fm, &args);
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001737 if (err) {
1738 if (err == -EINTR)
1739 fuse_invalidate_attr(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001740 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001741 }
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001742
Miklos Szeredieb59bd12019-11-12 11:49:04 +01001743 if (fuse_invalid_attr(&outarg.attr) ||
Al Viro6e3e2c42021-03-01 20:37:10 -05001744 inode_wrong_type(inode, outarg.attr.mode)) {
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001745 fuse_make_bad(inode);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001746 err = -EIO;
1747 goto error;
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001748 }
1749
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001750 spin_lock(&fi->lock);
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001751 /* the kernel maintains i_mtime locally */
Maxim Patlasov3ad22c62014-04-28 14:19:25 +02001752 if (trust_local_cmtime) {
1753 if (attr->ia_valid & ATTR_MTIME)
1754 inode->i_mtime = attr->ia_mtime;
1755 if (attr->ia_valid & ATTR_CTIME)
1756 inode->i_ctime = attr->ia_ctime;
Miklos Szeredi1e18bda2014-04-28 14:19:23 +02001757 /* FIXME: clear I_DIRTY_SYNC? */
Maxim Patlasovb0aa7602013-12-26 19:51:11 +04001758 }
1759
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001760 fuse_change_attributes_common(inode, &outarg.attr,
Miklos Szeredi4b52f052021-10-22 17:03:03 +02001761 attr_timeout(&outarg),
1762 fuse_get_cache_mask(inode));
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001763 oldsize = inode->i_size;
Pavel Emelyanov83732002013-10-10 17:10:46 +04001764 /* see the comment in fuse_change_attributes() */
Miklos Szeredic15016b2021-10-22 17:03:03 +02001765 if (!is_wb || is_truncate)
Pavel Emelyanov83732002013-10-10 17:10:46 +04001766 i_size_write(inode, outarg.attr.size);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001767
1768 if (is_truncate) {
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001769 /* NOTE: this may release/reacquire fi->lock */
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001770 __fuse_release_nowrite(inode);
1771 }
Kirill Tkhaif15ecfe2018-11-09 13:33:22 +03001772 spin_unlock(&fi->lock);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001773
1774 /*
1775 * Only call invalidate_inode_pages2() after removing
1776 * FUSE_NOWRITE, otherwise fuse_launder_page() would deadlock.
1777 */
Pavel Emelyanov83732002013-10-10 17:10:46 +04001778 if ((is_truncate || !is_wb) &&
1779 S_ISREG(inode->i_mode) && oldsize != outarg.attr.size) {
Kirill A. Shutemov7caef262013-09-12 15:13:56 -07001780 truncate_pagecache(inode, outarg.attr.size);
Jan Kara8bcbbe92021-04-21 17:18:39 +02001781 invalidate_inode_pages2(mapping);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001782 }
1783
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001784 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001785out:
1786 if (fault_blocked)
Jan Kara8bcbbe92021-04-21 17:18:39 +02001787 filemap_invalidate_unlock(mapping);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001788
Miklos Szeredie00d2c22007-10-16 23:31:01 -07001789 return 0;
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001790
1791error:
1792 if (is_truncate)
1793 fuse_release_nowrite(inode);
1794
Maxim Patlasov06a7c3c2013-08-30 17:06:04 +04001795 clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
Vivek Goyal6ae330c2020-08-19 18:19:54 -04001796
1797 if (fault_blocked)
Jan Kara8bcbbe92021-04-21 17:18:39 +02001798 filemap_invalidate_unlock(mapping);
Miklos Szeredi3be5a522008-04-30 00:54:41 -07001799 return err;
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001800}
1801
Christian Brauner549c7292021-01-21 14:19:43 +01001802static int fuse_setattr(struct user_namespace *mnt_userns, struct dentry *entry,
1803 struct iattr *attr)
Miklos Szeredi49d49142007-10-18 03:07:00 -07001804{
David Howells2b0143b2015-03-17 22:25:59 +00001805 struct inode *inode = d_inode(entry);
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001806 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001807 struct file *file = (attr->ia_valid & ATTR_FILE) ? attr->ia_file : NULL;
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001808 int ret;
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001809
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001810 if (fuse_is_bad(inode))
1811 return -EIO;
1812
Maxim Patlasovefb9fa92012-12-18 14:05:08 +04001813 if (!fuse_allow_current_process(get_fuse_conn(inode)))
1814 return -EACCES;
1815
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001816 if (attr->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) {
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001817 attr->ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID |
1818 ATTR_MODE);
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001819
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001820 /*
1821 * The only sane way to reliably kill suid/sgid is to do it in
1822 * the userspace filesystem
1823 *
1824 * This should be done on write(), truncate() and chown().
1825 */
Vivek Goyal8981bdf2020-10-09 14:15:10 -04001826 if (!fc->handle_killpriv && !fc->handle_killpriv_v2) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001827 /*
1828 * ia_mode calculation may have used stale i_mode.
1829 * Refresh and recalculate.
1830 */
1831 ret = fuse_do_getattr(inode, NULL, file);
1832 if (ret)
1833 return ret;
1834
1835 attr->ia_mode = inode->i_mode;
Miklos Szeredic01638f2016-12-06 16:18:45 +01001836 if (inode->i_mode & S_ISUID) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001837 attr->ia_valid |= ATTR_MODE;
1838 attr->ia_mode &= ~S_ISUID;
1839 }
Miklos Szeredic01638f2016-12-06 16:18:45 +01001840 if ((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
Miklos Szeredi5e940c12016-10-01 07:32:32 +02001841 attr->ia_valid |= ATTR_MODE;
1842 attr->ia_mode &= ~S_ISGID;
1843 }
Miklos Szeredia09f99e2016-10-01 07:32:32 +02001844 }
1845 }
1846 if (!attr->ia_valid)
1847 return 0;
1848
Linus Torvaldsabb5a142016-10-10 13:04:49 -07001849 ret = fuse_do_setattr(entry, attr, file);
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001850 if (!ret) {
Seth Forshee60bcc882016-08-29 08:46:37 -05001851 /*
1852 * If filesystem supports acls it may have updated acl xattrs in
1853 * the filesystem, so forget cached acls for the inode.
1854 */
1855 if (fc->posix_acl)
1856 forget_all_cached_acls(inode);
1857
Miklos Szeredi5e2b8822016-10-01 07:32:32 +02001858 /* Directory mode changed, may need to revalidate access */
1859 if (d_is_dir(entry) && (attr->ia_valid & ATTR_MODE))
1860 fuse_invalidate_entry_cache(entry);
1861 }
1862 return ret;
Miklos Szeredi49d49142007-10-18 03:07:00 -07001863}
1864
Christian Brauner549c7292021-01-21 14:19:43 +01001865static int fuse_getattr(struct user_namespace *mnt_userns,
1866 const struct path *path, struct kstat *stat,
David Howellsa528d352017-01-31 16:46:22 +00001867 u32 request_mask, unsigned int flags)
Miklos Szeredie5e55582005-09-09 13:10:28 -07001868{
David Howellsa528d352017-01-31 16:46:22 +00001869 struct inode *inode = d_inode(path->dentry);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001870 struct fuse_conn *fc = get_fuse_conn(inode);
Miklos Szeredi244f6382007-10-16 23:31:02 -07001871
Miklos Szeredi5d069db2020-12-10 15:33:14 +01001872 if (fuse_is_bad(inode))
1873 return -EIO;
1874
Miklos Szeredi5157da22020-05-19 14:50:37 +02001875 if (!fuse_allow_current_process(fc)) {
1876 if (!request_mask) {
1877 /*
1878 * If user explicitly requested *nothing* then don't
1879 * error out, but return st_dev only.
1880 */
1881 stat->result_mask = 0;
1882 stat->dev = inode->i_sb->s_dev;
1883 return 0;
1884 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001885 return -EACCES;
Miklos Szeredi5157da22020-05-19 14:50:37 +02001886 }
Miklos Szeredi244f6382007-10-16 23:31:02 -07001887
Miklos Szeredi2f1e8192018-10-15 15:43:06 +02001888 return fuse_update_get_attr(inode, NULL, stat, request_mask, flags);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001889}
1890
Arjan van de Ven754661f2007-02-12 00:55:38 -08001891static const struct inode_operations fuse_dir_inode_operations = {
Miklos Szeredie5e55582005-09-09 13:10:28 -07001892 .lookup = fuse_lookup,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001893 .mkdir = fuse_mkdir,
1894 .symlink = fuse_symlink,
1895 .unlink = fuse_unlink,
1896 .rmdir = fuse_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +02001897 .rename = fuse_rename2,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001898 .link = fuse_link,
1899 .setattr = fuse_setattr,
1900 .create = fuse_create,
Miklos Szeredic8ccbe02012-06-05 15:10:22 +02001901 .atomic_open = fuse_atomic_open,
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001902 .mknod = fuse_mknod,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001903 .permission = fuse_permission,
1904 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001905 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001906 .get_acl = fuse_get_acl,
1907 .set_acl = fuse_set_acl,
Miklos Szeredi72227ea2021-04-08 11:11:19 +02001908 .fileattr_get = fuse_fileattr_get,
1909 .fileattr_set = fuse_fileattr_set,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001910};
1911
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -08001912static const struct file_operations fuse_dir_operations = {
Miklos Szeredib6aeade2005-09-09 13:10:30 -07001913 .llseek = generic_file_llseek,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001914 .read = generic_read_dir,
Al Virod9b3dbd2016-04-20 17:30:32 -04001915 .iterate_shared = fuse_readdir,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001916 .open = fuse_dir_open,
1917 .release = fuse_dir_release,
Miklos Szeredi82547982005-09-09 13:10:38 -07001918 .fsync = fuse_dir_fsync,
Miklos Szeredib18da0c2011-12-13 11:58:49 +01001919 .unlocked_ioctl = fuse_dir_ioctl,
1920 .compat_ioctl = fuse_dir_compat_ioctl,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001921};
1922
Arjan van de Ven754661f2007-02-12 00:55:38 -08001923static const struct inode_operations fuse_common_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001924 .setattr = fuse_setattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001925 .permission = fuse_permission,
1926 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001927 .listxattr = fuse_listxattr,
Seth Forshee60bcc882016-08-29 08:46:37 -05001928 .get_acl = fuse_get_acl,
1929 .set_acl = fuse_set_acl,
Miklos Szeredi72227ea2021-04-08 11:11:19 +02001930 .fileattr_get = fuse_fileattr_get,
1931 .fileattr_set = fuse_fileattr_set,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001932};
1933
Arjan van de Ven754661f2007-02-12 00:55:38 -08001934static const struct inode_operations fuse_symlink_inode_operations = {
Miklos Szeredi9e6268d2005-09-09 13:10:29 -07001935 .setattr = fuse_setattr,
Al Viro6b255392015-11-17 10:20:54 -05001936 .get_link = fuse_get_link,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001937 .getattr = fuse_getattr,
Miklos Szeredi92a87802005-09-09 13:10:31 -07001938 .listxattr = fuse_listxattr,
Miklos Szeredie5e55582005-09-09 13:10:28 -07001939};
1940
1941void fuse_init_common(struct inode *inode)
1942{
1943 inode->i_op = &fuse_common_inode_operations;
1944}
1945
1946void fuse_init_dir(struct inode *inode)
1947{
Miklos Szerediab2257e2018-10-01 10:07:05 +02001948 struct fuse_inode *fi = get_fuse_inode(inode);
1949
Miklos Szeredie5e55582005-09-09 13:10:28 -07001950 inode->i_op = &fuse_dir_inode_operations;
1951 inode->i_fop = &fuse_dir_operations;
Miklos Szerediab2257e2018-10-01 10:07:05 +02001952
1953 spin_lock_init(&fi->rdc.lock);
1954 fi->rdc.cached = false;
1955 fi->rdc.size = 0;
1956 fi->rdc.pos = 0;
1957 fi->rdc.version = 0;
Miklos Szeredie5e55582005-09-09 13:10:28 -07001958}
1959
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001960static int fuse_symlink_readpage(struct file *null, struct page *page)
1961{
1962 int err = fuse_readlink_page(page->mapping->host, page);
1963
1964 if (!err)
1965 SetPageUptodate(page);
1966
1967 unlock_page(page);
1968
1969 return err;
1970}
1971
1972static const struct address_space_operations fuse_symlink_aops = {
1973 .readpage = fuse_symlink_readpage,
1974};
1975
Miklos Szeredie5e55582005-09-09 13:10:28 -07001976void fuse_init_symlink(struct inode *inode)
1977{
1978 inode->i_op = &fuse_symlink_inode_operations;
Dan Schatzberg5571f1e2018-10-11 08:17:00 -07001979 inode->i_data.a_ops = &fuse_symlink_aops;
1980 inode_nohighmem(inode);
Miklos Szeredie5e55582005-09-09 13:10:28 -07001981}