ovl: decode connected upper dir file handles
[linux-block.git] / fs / overlayfs / export.c
CommitLineData
8ed5eec9
AG
1/*
2 * Overlayfs NFS export support.
3 *
4 * Amir Goldstein <amir73il@gmail.com>
5 *
6 * Copyright (C) 2017-2018 CTERA Networks. All Rights Reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 */
12
13#include <linux/fs.h>
14#include <linux/cred.h>
15#include <linux/mount.h>
16#include <linux/namei.h>
17#include <linux/xattr.h>
18#include <linux/exportfs.h>
19#include <linux/ratelimit.h>
20#include "overlayfs.h"
21
22static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
23{
24 struct dentry *upper = ovl_dentry_upper(dentry);
25 struct dentry *origin = ovl_dentry_lower(dentry);
26 struct ovl_fh *fh = NULL;
27 int err;
28
29 /*
30 * On overlay with an upper layer, overlay root inode is encoded as
31 * an upper file handle, because upper root dir is not indexed.
32 */
33 if (dentry == dentry->d_sb->s_root && upper)
34 origin = NULL;
35
36 err = -EACCES;
37 if (!upper || origin)
38 goto fail;
39
40 /* TODO: encode non pure-upper by origin */
41 fh = ovl_encode_fh(upper, true);
42
43 err = -EOVERFLOW;
44 if (fh->len > buflen)
45 goto fail;
46
47 memcpy(buf, (char *)fh, fh->len);
48 err = fh->len;
49
50out:
51 kfree(fh);
52 return err;
53
54fail:
55 pr_warn_ratelimited("overlayfs: failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n",
56 dentry, err, buflen, fh ? (int)fh->len : 0,
57 fh ? fh->type : 0);
58 goto out;
59}
60
61static int ovl_dentry_to_fh(struct dentry *dentry, u32 *fid, int *max_len)
62{
63 int res, len = *max_len << 2;
64
65 res = ovl_d_to_fh(dentry, (char *)fid, len);
66 if (res <= 0)
67 return FILEID_INVALID;
68
69 len = res;
70
71 /* Round up to dwords */
72 *max_len = (len + 3) >> 2;
73 return OVL_FILEID;
74}
75
76static int ovl_encode_inode_fh(struct inode *inode, u32 *fid, int *max_len,
77 struct inode *parent)
78{
79 struct dentry *dentry;
80 int type;
81
82 /* TODO: encode connectable file handles */
83 if (parent)
84 return FILEID_INVALID;
85
86 dentry = d_find_any_alias(inode);
87 if (WARN_ON(!dentry))
88 return FILEID_INVALID;
89
90 type = ovl_dentry_to_fh(dentry, fid, max_len);
91
92 dput(dentry);
93 return type;
94}
95
8556a420
AG
96/*
97 * Find or instantiate an overlay dentry from real dentries.
98 */
99static struct dentry *ovl_obtain_alias(struct super_block *sb,
100 struct dentry *upper,
101 struct ovl_path *lowerpath)
102{
103 struct inode *inode;
104 struct dentry *dentry;
105 struct ovl_entry *oe;
106 void *fsdata = &oe;
107
108 /* TODO: obtain non pure-upper */
109 if (lowerpath)
110 return ERR_PTR(-EIO);
111
112 inode = ovl_get_inode(sb, dget(upper), NULL, NULL, 0);
113 if (IS_ERR(inode)) {
114 dput(upper);
115 return ERR_CAST(inode);
116 }
117
118 dentry = d_find_any_alias(inode);
119 if (!dentry) {
120 dentry = d_alloc_anon(inode->i_sb);
121 if (!dentry)
122 goto nomem;
123 oe = ovl_alloc_entry(0);
124 if (!oe)
125 goto nomem;
126
127 dentry->d_fsdata = oe;
128 ovl_dentry_set_upper_alias(dentry);
129 }
130
131 return d_instantiate_anon(dentry, inode);
132
133nomem:
134 iput(inode);
135 dput(dentry);
136 return ERR_PTR(-ENOMEM);
137}
138
3985b70a
AG
139/*
140 * Lookup a child overlay dentry to get a connected overlay dentry whose real
141 * dentry is @real. If @real is on upper layer, we lookup a child overlay
142 * dentry with the same name as the real dentry. Otherwise, we need to consult
143 * index for lookup.
144 */
145static struct dentry *ovl_lookup_real_one(struct dentry *connected,
146 struct dentry *real,
147 struct ovl_layer *layer)
148{
149 struct inode *dir = d_inode(connected);
150 struct dentry *this, *parent = NULL;
151 struct name_snapshot name;
152 int err;
153
154 /* TODO: lookup by lower real dentry */
155 if (layer->idx)
156 return ERR_PTR(-EACCES);
157
158 /*
159 * Lookup child overlay dentry by real name. The dir mutex protects us
160 * from racing with overlay rename. If the overlay dentry that is above
161 * real has already been moved to a parent that is not under the
162 * connected overlay dir, we return -ECHILD and restart the lookup of
163 * connected real path from the top.
164 */
165 inode_lock_nested(dir, I_MUTEX_PARENT);
166 err = -ECHILD;
167 parent = dget_parent(real);
168 if (ovl_dentry_upper(connected) != parent)
169 goto fail;
170
171 /*
172 * We also need to take a snapshot of real dentry name to protect us
173 * from racing with underlying layer rename. In this case, we don't
174 * care about returning ESTALE, only from dereferencing a free name
175 * pointer because we hold no lock on the real dentry.
176 */
177 take_dentry_name_snapshot(&name, real);
178 this = lookup_one_len(name.name, connected, strlen(name.name));
179 err = PTR_ERR(this);
180 if (IS_ERR(this)) {
181 goto fail;
182 } else if (!this || !this->d_inode) {
183 dput(this);
184 err = -ENOENT;
185 goto fail;
186 } else if (ovl_dentry_upper(this) != real) {
187 dput(this);
188 err = -ESTALE;
189 goto fail;
190 }
191
192out:
193 release_dentry_name_snapshot(&name);
194 dput(parent);
195 inode_unlock(dir);
196 return this;
197
198fail:
199 pr_warn_ratelimited("overlayfs: failed to lookup one by real (%pd2, layer=%d, connected=%pd2, err=%i)\n",
200 real, layer->idx, connected, err);
201 this = ERR_PTR(err);
202 goto out;
203}
204
205/*
206 * Lookup a connected overlay dentry whose real dentry is @real.
207 * If @real is on upper layer, we lookup a child overlay dentry with the same
208 * path the real dentry. Otherwise, we need to consult index for lookup.
209 */
210static struct dentry *ovl_lookup_real(struct super_block *sb,
211 struct dentry *real,
212 struct ovl_layer *layer)
213{
214 struct dentry *connected;
215 int err = 0;
216
217 /* TODO: use index when looking up by lower real dentry */
218 if (layer->idx)
219 return ERR_PTR(-EACCES);
220
221 connected = dget(sb->s_root);
222 while (!err) {
223 struct dentry *next, *this;
224 struct dentry *parent = NULL;
225 struct dentry *real_connected = ovl_dentry_upper(connected);
226
227 if (real_connected == real)
228 break;
229
230 /* Find the topmost dentry not yet connected */
231 next = dget(real);
232 for (;;) {
233 parent = dget_parent(next);
234
235 if (parent == real_connected)
236 break;
237
238 /*
239 * If real has been moved out of 'real_connected',
240 * we will not find 'real_connected' and hit the layer
241 * root. In that case, we need to restart connecting.
242 * This game can go on forever in the worst case. We
243 * may want to consider taking s_vfs_rename_mutex if
244 * this happens more than once.
245 */
246 if (parent == layer->mnt->mnt_root) {
247 dput(connected);
248 connected = dget(sb->s_root);
249 break;
250 }
251
252 /*
253 * If real file has been moved out of the layer root
254 * directory, we will eventully hit the real fs root.
255 * This cannot happen by legit overlay rename, so we
256 * return error in that case.
257 */
258 if (parent == next) {
259 err = -EXDEV;
260 break;
261 }
262
263 dput(next);
264 next = parent;
265 }
266
267 if (!err) {
268 this = ovl_lookup_real_one(connected, next, layer);
269 if (IS_ERR(this))
270 err = PTR_ERR(this);
271
272 /*
273 * Lookup of child in overlay can fail when racing with
274 * overlay rename of child away from 'connected' parent.
275 * In this case, we need to restart the lookup from the
276 * top, because we cannot trust that 'real_connected' is
277 * still an ancestor of 'real'.
278 */
279 if (err == -ECHILD) {
280 this = dget(sb->s_root);
281 err = 0;
282 }
283 if (!err) {
284 dput(connected);
285 connected = this;
286 }
287 }
288
289 dput(parent);
290 dput(next);
291 }
292
293 if (err)
294 goto fail;
295
296 return connected;
297
298fail:
299 pr_warn_ratelimited("overlayfs: failed to lookup by real (%pd2, layer=%d, connected=%pd2, err=%i)\n",
300 real, layer->idx, connected, err);
301 dput(connected);
302 return ERR_PTR(err);
303}
304
305/*
306 * Get an overlay dentry from upper/lower real dentries.
307 */
308static struct dentry *ovl_get_dentry(struct super_block *sb,
309 struct dentry *upper,
310 struct ovl_path *lowerpath)
311{
312 struct ovl_fs *ofs = sb->s_fs_info;
313 struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt };
314
315 /* TODO: get non-upper dentry */
316 if (!upper)
317 return ERR_PTR(-EACCES);
318
319 /*
320 * Obtain a disconnected overlay dentry from a non-dir real upper
321 * dentry.
322 */
323 if (!d_is_dir(upper))
324 return ovl_obtain_alias(sb, upper, NULL);
325
326 /* Removed empty directory? */
327 if ((upper->d_flags & DCACHE_DISCONNECTED) || d_unhashed(upper))
328 return ERR_PTR(-ENOENT);
329
330 /*
331 * If real upper dentry is connected and hashed, get a connected
332 * overlay dentry with the same path as the real upper dentry.
333 */
334 return ovl_lookup_real(sb, upper, &upper_layer);
335}
336
8556a420
AG
337static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,
338 struct ovl_fh *fh)
339{
340 struct ovl_fs *ofs = sb->s_fs_info;
341 struct dentry *dentry;
342 struct dentry *upper;
343
344 if (!ofs->upper_mnt)
345 return ERR_PTR(-EACCES);
346
347 upper = ovl_decode_fh(fh, ofs->upper_mnt);
348 if (IS_ERR_OR_NULL(upper))
349 return upper;
350
3985b70a 351 dentry = ovl_get_dentry(sb, upper, NULL);
8556a420
AG
352 dput(upper);
353
354 return dentry;
355}
356
357static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
358 int fh_len, int fh_type)
359{
360 struct dentry *dentry = NULL;
361 struct ovl_fh *fh = (struct ovl_fh *) fid;
362 int len = fh_len << 2;
363 unsigned int flags = 0;
364 int err;
365
366 err = -EINVAL;
367 if (fh_type != OVL_FILEID)
368 goto out_err;
369
370 err = ovl_check_fh_len(fh, len);
371 if (err)
372 goto out_err;
373
374 /* TODO: decode non-upper */
375 flags = fh->flags;
376 if (flags & OVL_FH_FLAG_PATH_UPPER)
377 dentry = ovl_upper_fh_to_d(sb, fh);
378 err = PTR_ERR(dentry);
379 if (IS_ERR(dentry) && err != -ESTALE)
380 goto out_err;
381
382 return dentry;
383
384out_err:
385 pr_warn_ratelimited("overlayfs: failed to decode file handle (len=%d, type=%d, flags=%x, err=%i)\n",
386 len, fh_type, flags, err);
387 return ERR_PTR(err);
388}
389
3985b70a
AG
390static struct dentry *ovl_fh_to_parent(struct super_block *sb, struct fid *fid,
391 int fh_len, int fh_type)
392{
393 pr_warn_ratelimited("overlayfs: connectable file handles not supported; use 'no_subtree_check' exportfs option.\n");
394 return ERR_PTR(-EACCES);
395}
396
397static int ovl_get_name(struct dentry *parent, char *name,
398 struct dentry *child)
399{
400 /*
401 * ovl_fh_to_dentry() returns connected dir overlay dentries and
402 * ovl_fh_to_parent() is not implemented, so we should not get here.
403 */
404 WARN_ON_ONCE(1);
405 return -EIO;
406}
407
408static struct dentry *ovl_get_parent(struct dentry *dentry)
409{
410 /*
411 * ovl_fh_to_dentry() returns connected dir overlay dentries, so we
412 * should not get here.
413 */
414 WARN_ON_ONCE(1);
415 return ERR_PTR(-EIO);
416}
417
8ed5eec9
AG
418const struct export_operations ovl_export_operations = {
419 .encode_fh = ovl_encode_inode_fh,
8556a420 420 .fh_to_dentry = ovl_fh_to_dentry,
3985b70a
AG
421 .fh_to_parent = ovl_fh_to_parent,
422 .get_name = ovl_get_name,
423 .get_parent = ovl_get_parent,
8ed5eec9 424};