]> asedeno.scripts.mit.edu Git - linux.git/blob - fs/overlayfs/namei.c
2e0b84c68ef638bc255cd23558dccfe0f416b4a1
[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 "overlayfs.h"
14 #include "ovl_entry.h"
15
16 static struct dentry *ovl_lookup_real(struct dentry *dir,
17                                       const struct qstr *name)
18 {
19         struct dentry *dentry;
20
21         dentry = lookup_one_len_unlocked(name->name, dir, name->len);
22         if (IS_ERR(dentry)) {
23                 if (PTR_ERR(dentry) == -ENOENT ||
24                     PTR_ERR(dentry) == -ENAMETOOLONG)
25                         dentry = NULL;
26         } else if (!dentry->d_inode) {
27                 dput(dentry);
28                 dentry = NULL;
29         } else if (ovl_dentry_weird(dentry)) {
30                 dput(dentry);
31                 /* Don't support traversing automounts and other weirdness */
32                 dentry = ERR_PTR(-EREMOTE);
33         }
34         return dentry;
35 }
36
37 static bool ovl_is_opaquedir(struct dentry *dentry)
38 {
39         int res;
40         char val;
41
42         if (!d_is_dir(dentry))
43                 return false;
44
45         res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
46         if (res == 1 && val == 'y')
47                 return true;
48
49         return false;
50 }
51
52 /*
53  * Returns next layer in stack starting from top.
54  * Returns -1 if this is the last layer.
55  */
56 int ovl_path_next(int idx, struct dentry *dentry, struct path *path)
57 {
58         struct ovl_entry *oe = dentry->d_fsdata;
59
60         BUG_ON(idx < 0);
61         if (idx == 0) {
62                 ovl_path_upper(dentry, path);
63                 if (path->dentry)
64                         return oe->numlower ? 1 : -1;
65                 idx++;
66         }
67         BUG_ON(idx > oe->numlower);
68         *path = oe->lowerstack[idx - 1];
69
70         return (idx < oe->numlower) ? idx + 1 : -1;
71 }
72
73 struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
74                           unsigned int flags)
75 {
76         struct ovl_entry *oe;
77         const struct cred *old_cred;
78         struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
79         struct ovl_entry *poe = dentry->d_parent->d_fsdata;
80         struct path *stack = NULL;
81         struct dentry *upperdir, *upperdentry = NULL;
82         unsigned int ctr = 0;
83         struct inode *inode = NULL;
84         bool upperopaque = false;
85         bool stop = false;
86         bool isdir = false;
87         struct dentry *this;
88         unsigned int i;
89         int err;
90
91         if (dentry->d_name.len > ofs->namelen)
92                 return ERR_PTR(-ENAMETOOLONG);
93
94         old_cred = ovl_override_creds(dentry->d_sb);
95         upperdir = ovl_upperdentry_dereference(poe);
96         if (upperdir) {
97                 this = ovl_lookup_real(upperdir, &dentry->d_name);
98                 err = PTR_ERR(this);
99                 if (IS_ERR(this))
100                         goto out;
101
102                 if (this) {
103                         if (unlikely(ovl_dentry_remote(this))) {
104                                 dput(this);
105                                 err = -EREMOTE;
106                                 goto out;
107                         }
108                         if (ovl_is_whiteout(this)) {
109                                 dput(this);
110                                 this = NULL;
111                                 stop = upperopaque = true;
112                         } else if (!d_is_dir(this)) {
113                                 stop = true;
114                         } else {
115                                 isdir = true;
116                                 if (poe->numlower && ovl_is_opaquedir(this))
117                                         stop = upperopaque = true;
118                         }
119                 }
120                 upperdentry = this;
121         }
122
123         if (!stop && poe->numlower) {
124                 err = -ENOMEM;
125                 stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL);
126                 if (!stack)
127                         goto out_put_upper;
128         }
129
130         for (i = 0; !stop && i < poe->numlower; i++) {
131                 struct path lowerpath = poe->lowerstack[i];
132
133                 this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
134                 err = PTR_ERR(this);
135                 if (IS_ERR(this))
136                         goto out_put;
137
138                 if (!this)
139                         continue;
140                 if (ovl_is_whiteout(this)) {
141                         dput(this);
142                         break;
143                 }
144                 /*
145                  * If this is a non-directory then stop here.
146                  */
147                 if (!d_is_dir(this)) {
148                         if (isdir) {
149                                 dput(this);
150                                 break;
151                         }
152                         stop = true;
153                 } else {
154                         /*
155                          * Only makes sense to check opaque dir if this is not
156                          * the lowermost layer.
157                          */
158                         if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
159                                 stop = true;
160                 }
161
162                 stack[ctr].dentry = this;
163                 stack[ctr].mnt = lowerpath.mnt;
164                 ctr++;
165         }
166
167         oe = ovl_alloc_entry(ctr);
168         err = -ENOMEM;
169         if (!oe)
170                 goto out_put;
171
172         if (upperdentry || ctr) {
173                 struct dentry *realdentry;
174                 struct inode *realinode;
175
176                 realdentry = upperdentry ? upperdentry : stack[0].dentry;
177                 realinode = d_inode(realdentry);
178
179                 err = -ENOMEM;
180                 if (upperdentry && !d_is_dir(upperdentry)) {
181                         inode = ovl_get_inode(dentry->d_sb, realinode);
182                 } else {
183                         inode = ovl_new_inode(dentry->d_sb, realinode->i_mode,
184                                               realinode->i_rdev);
185                         if (inode)
186                                 ovl_inode_init(inode, realinode, !!upperdentry);
187                 }
188                 if (!inode)
189                         goto out_free_oe;
190                 ovl_copyattr(realdentry->d_inode, inode);
191         }
192
193         revert_creds(old_cred);
194         oe->opaque = upperopaque;
195         oe->__upperdentry = upperdentry;
196         memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
197         kfree(stack);
198         dentry->d_fsdata = oe;
199         d_add(dentry, inode);
200
201         return NULL;
202
203 out_free_oe:
204         kfree(oe);
205 out_put:
206         for (i = 0; i < ctr; i++)
207                 dput(stack[i].dentry);
208         kfree(stack);
209 out_put_upper:
210         dput(upperdentry);
211 out:
212         revert_creds(old_cred);
213         return ERR_PTR(err);
214 }
215
216 bool ovl_lower_positive(struct dentry *dentry)
217 {
218         struct ovl_entry *oe = dentry->d_fsdata;
219         struct ovl_entry *poe = dentry->d_parent->d_fsdata;
220         const struct qstr *name = &dentry->d_name;
221         unsigned int i;
222         bool positive = false;
223         bool done = false;
224
225         /*
226          * If dentry is negative, then lower is positive iff this is a
227          * whiteout.
228          */
229         if (!dentry->d_inode)
230                 return oe->opaque;
231
232         /* Negative upper -> positive lower */
233         if (!oe->__upperdentry)
234                 return true;
235
236         /* Positive upper -> have to look up lower to see whether it exists */
237         for (i = 0; !done && !positive && i < poe->numlower; i++) {
238                 struct dentry *this;
239                 struct dentry *lowerdir = poe->lowerstack[i].dentry;
240
241                 this = lookup_one_len_unlocked(name->name, lowerdir,
242                                                name->len);
243                 if (IS_ERR(this)) {
244                         switch (PTR_ERR(this)) {
245                         case -ENOENT:
246                         case -ENAMETOOLONG:
247                                 break;
248
249                         default:
250                                 /*
251                                  * Assume something is there, we just couldn't
252                                  * access it.
253                                  */
254                                 positive = true;
255                                 break;
256                         }
257                 } else {
258                         if (this->d_inode) {
259                                 positive = !ovl_is_whiteout(this);
260                                 done = true;
261                         }
262                         dput(this);
263                 }
264         }
265
266         return positive;
267 }