]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/overlayfs/namei.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[karo-tx-linux.git] / fs / overlayfs / namei.c
1 /*
2  * Copyright (C) 2011 Novell Inc.
3  * Copyright (C) 2016 Red Hat, Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  */
9
10 #include <linux/fs.h>
11 #include <linux/namei.h>
12 #include <linux/xattr.h>
13 #include <linux/ratelimit.h>
14 #include "overlayfs.h"
15 #include "ovl_entry.h"
16
17 struct ovl_lookup_data {
18         struct qstr name;
19         bool is_dir;
20         bool opaque;
21         bool stop;
22         bool last;
23         char *redirect;
24 };
25
26 static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
27                               size_t prelen, const char *post)
28 {
29         int res;
30         char *s, *next, *buf = NULL;
31
32         res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
33         if (res < 0) {
34                 if (res == -ENODATA || res == -EOPNOTSUPP)
35                         return 0;
36                 goto fail;
37         }
38         buf = kzalloc(prelen + res + strlen(post) + 1, GFP_TEMPORARY);
39         if (!buf)
40                 return -ENOMEM;
41
42         if (res == 0)
43                 goto invalid;
44
45         res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
46         if (res < 0)
47                 goto fail;
48         if (res == 0)
49                 goto invalid;
50         if (buf[0] == '/') {
51                 for (s = buf; *s++ == '/'; s = next) {
52                         next = strchrnul(s, '/');
53                         if (s == next)
54                                 goto invalid;
55                 }
56         } else {
57                 if (strchr(buf, '/') != NULL)
58                         goto invalid;
59
60                 memmove(buf + prelen, buf, res);
61                 memcpy(buf, d->name.name, prelen);
62         }
63
64         strcat(buf, post);
65         kfree(d->redirect);
66         d->redirect = buf;
67         d->name.name = d->redirect;
68         d->name.len = strlen(d->redirect);
69
70         return 0;
71
72 err_free:
73         kfree(buf);
74         return 0;
75 fail:
76         pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
77         goto err_free;
78 invalid:
79         pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
80         goto err_free;
81 }
82
83 static bool ovl_is_opaquedir(struct dentry *dentry)
84 {
85         int res;
86         char val;
87
88         if (!d_is_dir(dentry))
89                 return false;
90
91         res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
92         if (res == 1 && val == 'y')
93                 return true;
94
95         return false;
96 }
97
98 static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
99                              const char *name, unsigned int namelen,
100                              size_t prelen, const char *post,
101                              struct dentry **ret)
102 {
103         struct dentry *this;
104         int err;
105
106         this = lookup_one_len_unlocked(name, base, namelen);
107         if (IS_ERR(this)) {
108                 err = PTR_ERR(this);
109                 this = NULL;
110                 if (err == -ENOENT || err == -ENAMETOOLONG)
111                         goto out;
112                 goto out_err;
113         }
114         if (!this->d_inode)
115                 goto put_and_out;
116
117         if (ovl_dentry_weird(this)) {
118                 /* Don't support traversing automounts and other weirdness */
119                 err = -EREMOTE;
120                 goto out_err;
121         }
122         if (ovl_is_whiteout(this)) {
123                 d->stop = d->opaque = true;
124                 goto put_and_out;
125         }
126         if (!d_can_lookup(this)) {
127                 d->stop = true;
128                 if (d->is_dir)
129                         goto put_and_out;
130                 goto out;
131         }
132         d->is_dir = true;
133         if (!d->last && ovl_is_opaquedir(this)) {
134                 d->stop = d->opaque = true;
135                 goto out;
136         }
137         err = ovl_check_redirect(this, d, prelen, post);
138         if (err)
139                 goto out_err;
140 out:
141         *ret = this;
142         return 0;
143
144 put_and_out:
145         dput(this);
146         this = NULL;
147         goto out;
148
149 out_err:
150         dput(this);
151         return err;
152 }
153
154 static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
155                             struct dentry **ret)
156 {
157         const char *s = d->name.name;
158         struct dentry *dentry = NULL;
159         int err;
160
161         if (*s != '/')
162                 return ovl_lookup_single(base, d, d->name.name, d->name.len,
163                                          0, "", ret);
164
165         while (*s++ == '/' && !IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
166                 const char *next = strchrnul(s, '/');
167                 size_t slen = strlen(s);
168
169                 if (WARN_ON(slen > d->name.len) ||
170                     WARN_ON(strcmp(d->name.name + d->name.len - slen, s)))
171                         return -EIO;
172
173                 err = ovl_lookup_single(base, d, s, next - s,
174                                         d->name.len - slen, next, &base);
175                 dput(dentry);
176                 if (err)
177                         return err;
178                 dentry = base;
179                 s = next;
180         }
181         *ret = dentry;
182         return 0;
183 }
184
185 /*
186  * Returns next layer in stack starting from top.
187  * Returns -1 if this is the last layer.
188  */
189 int ovl_path_next(int idx, struct dentry *dentry, struct path *path)
190 {
191         struct ovl_entry *oe = dentry->d_fsdata;
192
193         BUG_ON(idx < 0);
194         if (idx == 0) {
195                 ovl_path_upper(dentry, path);
196                 if (path->dentry)
197                         return oe->numlower ? 1 : -1;
198                 idx++;
199         }
200         BUG_ON(idx > oe->numlower);
201         *path = oe->lowerstack[idx - 1];
202
203         return (idx < oe->numlower) ? idx + 1 : -1;
204 }
205
206 struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
207                           unsigned int flags)
208 {
209         struct ovl_entry *oe;
210         const struct cred *old_cred;
211         struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
212         struct ovl_entry *poe = dentry->d_parent->d_fsdata;
213         struct path *stack = NULL;
214         struct dentry *upperdir, *upperdentry = NULL;
215         unsigned int ctr = 0;
216         struct inode *inode = NULL;
217         bool upperopaque = false;
218         char *upperredirect = NULL;
219         struct dentry *this;
220         unsigned int i;
221         int err;
222         struct ovl_lookup_data d = {
223                 .name = dentry->d_name,
224                 .is_dir = false,
225                 .opaque = false,
226                 .stop = false,
227                 .last = !poe->numlower,
228                 .redirect = NULL,
229         };
230
231         if (dentry->d_name.len > ofs->namelen)
232                 return ERR_PTR(-ENAMETOOLONG);
233
234         old_cred = ovl_override_creds(dentry->d_sb);
235         upperdir = ovl_upperdentry_dereference(poe);
236         if (upperdir) {
237                 err = ovl_lookup_layer(upperdir, &d, &upperdentry);
238                 if (err)
239                         goto out;
240
241                 if (upperdentry && unlikely(ovl_dentry_remote(upperdentry))) {
242                         dput(upperdentry);
243                         err = -EREMOTE;
244                         goto out;
245                 }
246
247                 if (d.redirect) {
248                         upperredirect = kstrdup(d.redirect, GFP_KERNEL);
249                         if (!upperredirect)
250                                 goto out_put_upper;
251                         if (d.redirect[0] == '/')
252                                 poe = dentry->d_sb->s_root->d_fsdata;
253                 }
254                 upperopaque = d.opaque;
255         }
256
257         if (!d.stop && poe->numlower) {
258                 err = -ENOMEM;
259                 stack = kcalloc(ofs->numlower, sizeof(struct path),
260                                 GFP_TEMPORARY);
261                 if (!stack)
262                         goto out_put_upper;
263         }
264
265         for (i = 0; !d.stop && i < poe->numlower; i++) {
266                 struct path lowerpath = poe->lowerstack[i];
267
268                 d.last = i == poe->numlower - 1;
269                 err = ovl_lookup_layer(lowerpath.dentry, &d, &this);
270                 if (err)
271                         goto out_put;
272
273                 if (!this)
274                         continue;
275
276                 stack[ctr].dentry = this;
277                 stack[ctr].mnt = lowerpath.mnt;
278                 ctr++;
279
280                 if (d.stop)
281                         break;
282
283                 if (d.redirect &&
284                     d.redirect[0] == '/' &&
285                     poe != dentry->d_sb->s_root->d_fsdata) {
286                         poe = dentry->d_sb->s_root->d_fsdata;
287
288                         /* Find the current layer on the root dentry */
289                         for (i = 0; i < poe->numlower; i++)
290                                 if (poe->lowerstack[i].mnt == lowerpath.mnt)
291                                         break;
292                         if (WARN_ON(i == poe->numlower))
293                                 break;
294                 }
295         }
296
297         oe = ovl_alloc_entry(ctr);
298         err = -ENOMEM;
299         if (!oe)
300                 goto out_put;
301
302         if (upperdentry || ctr) {
303                 struct dentry *realdentry;
304                 struct inode *realinode;
305
306                 realdentry = upperdentry ? upperdentry : stack[0].dentry;
307                 realinode = d_inode(realdentry);
308
309                 err = -ENOMEM;
310                 if (upperdentry && !d_is_dir(upperdentry)) {
311                         inode = ovl_get_inode(dentry->d_sb, realinode);
312                 } else {
313                         inode = ovl_new_inode(dentry->d_sb, realinode->i_mode,
314                                               realinode->i_rdev);
315                         if (inode)
316                                 ovl_inode_init(inode, realinode, !!upperdentry);
317                 }
318                 if (!inode)
319                         goto out_free_oe;
320                 ovl_copyattr(realdentry->d_inode, inode);
321         }
322
323         revert_creds(old_cred);
324         oe->opaque = upperopaque;
325         oe->redirect = upperredirect;
326         oe->__upperdentry = upperdentry;
327         memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
328         kfree(stack);
329         kfree(d.redirect);
330         dentry->d_fsdata = oe;
331         d_add(dentry, inode);
332
333         return NULL;
334
335 out_free_oe:
336         kfree(oe);
337 out_put:
338         for (i = 0; i < ctr; i++)
339                 dput(stack[i].dentry);
340         kfree(stack);
341 out_put_upper:
342         dput(upperdentry);
343         kfree(upperredirect);
344 out:
345         kfree(d.redirect);
346         revert_creds(old_cred);
347         return ERR_PTR(err);
348 }
349
350 bool ovl_lower_positive(struct dentry *dentry)
351 {
352         struct ovl_entry *oe = dentry->d_fsdata;
353         struct ovl_entry *poe = dentry->d_parent->d_fsdata;
354         const struct qstr *name = &dentry->d_name;
355         unsigned int i;
356         bool positive = false;
357         bool done = false;
358
359         /*
360          * If dentry is negative, then lower is positive iff this is a
361          * whiteout.
362          */
363         if (!dentry->d_inode)
364                 return oe->opaque;
365
366         /* Negative upper -> positive lower */
367         if (!oe->__upperdentry)
368                 return true;
369
370         /* Positive upper -> have to look up lower to see whether it exists */
371         for (i = 0; !done && !positive && i < poe->numlower; i++) {
372                 struct dentry *this;
373                 struct dentry *lowerdir = poe->lowerstack[i].dentry;
374
375                 this = lookup_one_len_unlocked(name->name, lowerdir,
376                                                name->len);
377                 if (IS_ERR(this)) {
378                         switch (PTR_ERR(this)) {
379                         case -ENOENT:
380                         case -ENAMETOOLONG:
381                                 break;
382
383                         default:
384                                 /*
385                                  * Assume something is there, we just couldn't
386                                  * access it.
387                                  */
388                                 positive = true;
389                                 break;
390                         }
391                 } else {
392                         if (this->d_inode) {
393                                 positive = !ovl_is_whiteout(this);
394                                 done = true;
395                         }
396                         dput(this);
397                 }
398         }
399
400         return positive;
401 }