xref: /openbmc/linux/fs/overlayfs/namei.c (revision 5b825c3af1d8a0af4deb4a5eb349d0d0050c62e5)
1bbb1e54dSMiklos Szeredi /*
2bbb1e54dSMiklos Szeredi  * Copyright (C) 2011 Novell Inc.
3bbb1e54dSMiklos Szeredi  * Copyright (C) 2016 Red Hat, Inc.
4bbb1e54dSMiklos Szeredi  *
5bbb1e54dSMiklos Szeredi  * This program is free software; you can redistribute it and/or modify it
6bbb1e54dSMiklos Szeredi  * under the terms of the GNU General Public License version 2 as published by
7bbb1e54dSMiklos Szeredi  * the Free Software Foundation.
8bbb1e54dSMiklos Szeredi  */
9bbb1e54dSMiklos Szeredi 
10bbb1e54dSMiklos Szeredi #include <linux/fs.h>
11*5b825c3aSIngo Molnar #include <linux/cred.h>
12bbb1e54dSMiklos Szeredi #include <linux/namei.h>
13bbb1e54dSMiklos Szeredi #include <linux/xattr.h>
1402b69b28SMiklos Szeredi #include <linux/ratelimit.h>
15bbb1e54dSMiklos Szeredi #include "overlayfs.h"
16bbb1e54dSMiklos Szeredi #include "ovl_entry.h"
17bbb1e54dSMiklos Szeredi 
18e28edc46SMiklos Szeredi struct ovl_lookup_data {
19e28edc46SMiklos Szeredi 	struct qstr name;
20e28edc46SMiklos Szeredi 	bool is_dir;
21e28edc46SMiklos Szeredi 	bool opaque;
22e28edc46SMiklos Szeredi 	bool stop;
23e28edc46SMiklos Szeredi 	bool last;
2402b69b28SMiklos Szeredi 	char *redirect;
25e28edc46SMiklos Szeredi };
26bbb1e54dSMiklos Szeredi 
2702b69b28SMiklos Szeredi static int ovl_check_redirect(struct dentry *dentry, struct ovl_lookup_data *d,
2802b69b28SMiklos Szeredi 			      size_t prelen, const char *post)
2902b69b28SMiklos Szeredi {
3002b69b28SMiklos Szeredi 	int res;
3102b69b28SMiklos Szeredi 	char *s, *next, *buf = NULL;
3202b69b28SMiklos Szeredi 
3302b69b28SMiklos Szeredi 	res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, NULL, 0);
3402b69b28SMiklos Szeredi 	if (res < 0) {
3502b69b28SMiklos Szeredi 		if (res == -ENODATA || res == -EOPNOTSUPP)
3602b69b28SMiklos Szeredi 			return 0;
3702b69b28SMiklos Szeredi 		goto fail;
3802b69b28SMiklos Szeredi 	}
3902b69b28SMiklos Szeredi 	buf = kzalloc(prelen + res + strlen(post) + 1, GFP_TEMPORARY);
4002b69b28SMiklos Szeredi 	if (!buf)
4102b69b28SMiklos Szeredi 		return -ENOMEM;
4202b69b28SMiklos Szeredi 
4302b69b28SMiklos Szeredi 	if (res == 0)
4402b69b28SMiklos Szeredi 		goto invalid;
4502b69b28SMiklos Szeredi 
4602b69b28SMiklos Szeredi 	res = vfs_getxattr(dentry, OVL_XATTR_REDIRECT, buf, res);
4702b69b28SMiklos Szeredi 	if (res < 0)
4802b69b28SMiklos Szeredi 		goto fail;
4902b69b28SMiklos Szeredi 	if (res == 0)
5002b69b28SMiklos Szeredi 		goto invalid;
5102b69b28SMiklos Szeredi 	if (buf[0] == '/') {
5202b69b28SMiklos Szeredi 		for (s = buf; *s++ == '/'; s = next) {
5302b69b28SMiklos Szeredi 			next = strchrnul(s, '/');
5402b69b28SMiklos Szeredi 			if (s == next)
5502b69b28SMiklos Szeredi 				goto invalid;
5602b69b28SMiklos Szeredi 		}
5702b69b28SMiklos Szeredi 	} else {
5802b69b28SMiklos Szeredi 		if (strchr(buf, '/') != NULL)
5902b69b28SMiklos Szeredi 			goto invalid;
6002b69b28SMiklos Szeredi 
6102b69b28SMiklos Szeredi 		memmove(buf + prelen, buf, res);
6202b69b28SMiklos Szeredi 		memcpy(buf, d->name.name, prelen);
6302b69b28SMiklos Szeredi 	}
6402b69b28SMiklos Szeredi 
6502b69b28SMiklos Szeredi 	strcat(buf, post);
6602b69b28SMiklos Szeredi 	kfree(d->redirect);
6702b69b28SMiklos Szeredi 	d->redirect = buf;
6802b69b28SMiklos Szeredi 	d->name.name = d->redirect;
6902b69b28SMiklos Szeredi 	d->name.len = strlen(d->redirect);
7002b69b28SMiklos Szeredi 
7102b69b28SMiklos Szeredi 	return 0;
7202b69b28SMiklos Szeredi 
7302b69b28SMiklos Szeredi err_free:
7402b69b28SMiklos Szeredi 	kfree(buf);
7502b69b28SMiklos Szeredi 	return 0;
7602b69b28SMiklos Szeredi fail:
7702b69b28SMiklos Szeredi 	pr_warn_ratelimited("overlayfs: failed to get redirect (%i)\n", res);
7802b69b28SMiklos Szeredi 	goto err_free;
7902b69b28SMiklos Szeredi invalid:
8002b69b28SMiklos Szeredi 	pr_warn_ratelimited("overlayfs: invalid redirect (%s)\n", buf);
8102b69b28SMiklos Szeredi 	goto err_free;
8202b69b28SMiklos Szeredi }
8302b69b28SMiklos Szeredi 
84bbb1e54dSMiklos Szeredi static bool ovl_is_opaquedir(struct dentry *dentry)
85bbb1e54dSMiklos Szeredi {
86bbb1e54dSMiklos Szeredi 	int res;
87bbb1e54dSMiklos Szeredi 	char val;
88bbb1e54dSMiklos Szeredi 
89bbb1e54dSMiklos Szeredi 	if (!d_is_dir(dentry))
90bbb1e54dSMiklos Szeredi 		return false;
91bbb1e54dSMiklos Szeredi 
92bbb1e54dSMiklos Szeredi 	res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
93bbb1e54dSMiklos Szeredi 	if (res == 1 && val == 'y')
94bbb1e54dSMiklos Szeredi 		return true;
95bbb1e54dSMiklos Szeredi 
96bbb1e54dSMiklos Szeredi 	return false;
97bbb1e54dSMiklos Szeredi }
98bbb1e54dSMiklos Szeredi 
99e28edc46SMiklos Szeredi static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
100e28edc46SMiklos Szeredi 			     const char *name, unsigned int namelen,
10102b69b28SMiklos Szeredi 			     size_t prelen, const char *post,
102e28edc46SMiklos Szeredi 			     struct dentry **ret)
103e28edc46SMiklos Szeredi {
104e28edc46SMiklos Szeredi 	struct dentry *this;
105e28edc46SMiklos Szeredi 	int err;
106e28edc46SMiklos Szeredi 
107e28edc46SMiklos Szeredi 	this = lookup_one_len_unlocked(name, base, namelen);
108e28edc46SMiklos Szeredi 	if (IS_ERR(this)) {
109e28edc46SMiklos Szeredi 		err = PTR_ERR(this);
110e28edc46SMiklos Szeredi 		this = NULL;
111e28edc46SMiklos Szeredi 		if (err == -ENOENT || err == -ENAMETOOLONG)
112e28edc46SMiklos Szeredi 			goto out;
113e28edc46SMiklos Szeredi 		goto out_err;
114e28edc46SMiklos Szeredi 	}
115e28edc46SMiklos Szeredi 	if (!this->d_inode)
116e28edc46SMiklos Szeredi 		goto put_and_out;
117e28edc46SMiklos Szeredi 
118e28edc46SMiklos Szeredi 	if (ovl_dentry_weird(this)) {
119e28edc46SMiklos Szeredi 		/* Don't support traversing automounts and other weirdness */
120e28edc46SMiklos Szeredi 		err = -EREMOTE;
121e28edc46SMiklos Szeredi 		goto out_err;
122e28edc46SMiklos Szeredi 	}
123e28edc46SMiklos Szeredi 	if (ovl_is_whiteout(this)) {
124e28edc46SMiklos Szeredi 		d->stop = d->opaque = true;
125e28edc46SMiklos Szeredi 		goto put_and_out;
126e28edc46SMiklos Szeredi 	}
127e28edc46SMiklos Szeredi 	if (!d_can_lookup(this)) {
128e28edc46SMiklos Szeredi 		d->stop = true;
129e28edc46SMiklos Szeredi 		if (d->is_dir)
130e28edc46SMiklos Szeredi 			goto put_and_out;
131e28edc46SMiklos Szeredi 		goto out;
132e28edc46SMiklos Szeredi 	}
133e28edc46SMiklos Szeredi 	d->is_dir = true;
134e28edc46SMiklos Szeredi 	if (!d->last && ovl_is_opaquedir(this)) {
135e28edc46SMiklos Szeredi 		d->stop = d->opaque = true;
136e28edc46SMiklos Szeredi 		goto out;
137e28edc46SMiklos Szeredi 	}
13802b69b28SMiklos Szeredi 	err = ovl_check_redirect(this, d, prelen, post);
13902b69b28SMiklos Szeredi 	if (err)
14002b69b28SMiklos Szeredi 		goto out_err;
141e28edc46SMiklos Szeredi out:
142e28edc46SMiklos Szeredi 	*ret = this;
143e28edc46SMiklos Szeredi 	return 0;
144e28edc46SMiklos Szeredi 
145e28edc46SMiklos Szeredi put_and_out:
146e28edc46SMiklos Szeredi 	dput(this);
147e28edc46SMiklos Szeredi 	this = NULL;
148e28edc46SMiklos Szeredi 	goto out;
149e28edc46SMiklos Szeredi 
150e28edc46SMiklos Szeredi out_err:
151e28edc46SMiklos Szeredi 	dput(this);
152e28edc46SMiklos Szeredi 	return err;
153e28edc46SMiklos Szeredi }
154e28edc46SMiklos Szeredi 
155e28edc46SMiklos Szeredi static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
156e28edc46SMiklos Szeredi 			    struct dentry **ret)
157e28edc46SMiklos Szeredi {
1584c7d0c9cSAmir Goldstein 	/* Counting down from the end, since the prefix can change */
1594c7d0c9cSAmir Goldstein 	size_t rem = d->name.len - 1;
16002b69b28SMiklos Szeredi 	struct dentry *dentry = NULL;
16102b69b28SMiklos Szeredi 	int err;
16202b69b28SMiklos Szeredi 
1634c7d0c9cSAmir Goldstein 	if (d->name.name[0] != '/')
16402b69b28SMiklos Szeredi 		return ovl_lookup_single(base, d, d->name.name, d->name.len,
16502b69b28SMiklos Szeredi 					 0, "", ret);
16602b69b28SMiklos Szeredi 
1674c7d0c9cSAmir Goldstein 	while (!IS_ERR_OR_NULL(base) && d_can_lookup(base)) {
1684c7d0c9cSAmir Goldstein 		const char *s = d->name.name + d->name.len - rem;
16902b69b28SMiklos Szeredi 		const char *next = strchrnul(s, '/');
1704c7d0c9cSAmir Goldstein 		size_t thislen = next - s;
1714c7d0c9cSAmir Goldstein 		bool end = !next[0];
17202b69b28SMiklos Szeredi 
1734c7d0c9cSAmir Goldstein 		/* Verify we did not go off the rails */
1744c7d0c9cSAmir Goldstein 		if (WARN_ON(s[-1] != '/'))
17502b69b28SMiklos Szeredi 			return -EIO;
17602b69b28SMiklos Szeredi 
1774c7d0c9cSAmir Goldstein 		err = ovl_lookup_single(base, d, s, thislen,
1784c7d0c9cSAmir Goldstein 					d->name.len - rem, next, &base);
17902b69b28SMiklos Szeredi 		dput(dentry);
18002b69b28SMiklos Szeredi 		if (err)
18102b69b28SMiklos Szeredi 			return err;
18202b69b28SMiklos Szeredi 		dentry = base;
1834c7d0c9cSAmir Goldstein 		if (end)
1844c7d0c9cSAmir Goldstein 			break;
1854c7d0c9cSAmir Goldstein 
1864c7d0c9cSAmir Goldstein 		rem -= thislen + 1;
1874c7d0c9cSAmir Goldstein 
1884c7d0c9cSAmir Goldstein 		if (WARN_ON(rem >= d->name.len))
1894c7d0c9cSAmir Goldstein 			return -EIO;
19002b69b28SMiklos Szeredi 	}
19102b69b28SMiklos Szeredi 	*ret = dentry;
19202b69b28SMiklos Szeredi 	return 0;
193e28edc46SMiklos Szeredi }
194e28edc46SMiklos Szeredi 
195bbb1e54dSMiklos Szeredi /*
196bbb1e54dSMiklos Szeredi  * Returns next layer in stack starting from top.
197bbb1e54dSMiklos Szeredi  * Returns -1 if this is the last layer.
198bbb1e54dSMiklos Szeredi  */
199bbb1e54dSMiklos Szeredi int ovl_path_next(int idx, struct dentry *dentry, struct path *path)
200bbb1e54dSMiklos Szeredi {
201bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
202bbb1e54dSMiklos Szeredi 
203bbb1e54dSMiklos Szeredi 	BUG_ON(idx < 0);
204bbb1e54dSMiklos Szeredi 	if (idx == 0) {
205bbb1e54dSMiklos Szeredi 		ovl_path_upper(dentry, path);
206bbb1e54dSMiklos Szeredi 		if (path->dentry)
207bbb1e54dSMiklos Szeredi 			return oe->numlower ? 1 : -1;
208bbb1e54dSMiklos Szeredi 		idx++;
209bbb1e54dSMiklos Szeredi 	}
210bbb1e54dSMiklos Szeredi 	BUG_ON(idx > oe->numlower);
211bbb1e54dSMiklos Szeredi 	*path = oe->lowerstack[idx - 1];
212bbb1e54dSMiklos Szeredi 
213bbb1e54dSMiklos Szeredi 	return (idx < oe->numlower) ? idx + 1 : -1;
214bbb1e54dSMiklos Szeredi }
215bbb1e54dSMiklos Szeredi 
216bbb1e54dSMiklos Szeredi struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
217bbb1e54dSMiklos Szeredi 			  unsigned int flags)
218bbb1e54dSMiklos Szeredi {
219bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe;
220bbb1e54dSMiklos Szeredi 	const struct cred *old_cred;
2216b2d5fe4SMiklos Szeredi 	struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
222bbb1e54dSMiklos Szeredi 	struct ovl_entry *poe = dentry->d_parent->d_fsdata;
223bbb1e54dSMiklos Szeredi 	struct path *stack = NULL;
224bbb1e54dSMiklos Szeredi 	struct dentry *upperdir, *upperdentry = NULL;
225bbb1e54dSMiklos Szeredi 	unsigned int ctr = 0;
226bbb1e54dSMiklos Szeredi 	struct inode *inode = NULL;
227bbb1e54dSMiklos Szeredi 	bool upperopaque = false;
22802b69b28SMiklos Szeredi 	char *upperredirect = NULL;
229bbb1e54dSMiklos Szeredi 	struct dentry *this;
230bbb1e54dSMiklos Szeredi 	unsigned int i;
231bbb1e54dSMiklos Szeredi 	int err;
232e28edc46SMiklos Szeredi 	struct ovl_lookup_data d = {
233e28edc46SMiklos Szeredi 		.name = dentry->d_name,
234e28edc46SMiklos Szeredi 		.is_dir = false,
235e28edc46SMiklos Szeredi 		.opaque = false,
236e28edc46SMiklos Szeredi 		.stop = false,
237e28edc46SMiklos Szeredi 		.last = !poe->numlower,
23802b69b28SMiklos Szeredi 		.redirect = NULL,
239e28edc46SMiklos Szeredi 	};
240bbb1e54dSMiklos Szeredi 
2416b2d5fe4SMiklos Szeredi 	if (dentry->d_name.len > ofs->namelen)
2426b2d5fe4SMiklos Szeredi 		return ERR_PTR(-ENAMETOOLONG);
2436b2d5fe4SMiklos Szeredi 
244bbb1e54dSMiklos Szeredi 	old_cred = ovl_override_creds(dentry->d_sb);
245bbb1e54dSMiklos Szeredi 	upperdir = ovl_upperdentry_dereference(poe);
246bbb1e54dSMiklos Szeredi 	if (upperdir) {
247e28edc46SMiklos Szeredi 		err = ovl_lookup_layer(upperdir, &d, &upperdentry);
248e28edc46SMiklos Szeredi 		if (err)
249bbb1e54dSMiklos Szeredi 			goto out;
250bbb1e54dSMiklos Szeredi 
251e28edc46SMiklos Szeredi 		if (upperdentry && unlikely(ovl_dentry_remote(upperdentry))) {
252e28edc46SMiklos Szeredi 			dput(upperdentry);
253bbb1e54dSMiklos Szeredi 			err = -EREMOTE;
254bbb1e54dSMiklos Szeredi 			goto out;
255bbb1e54dSMiklos Szeredi 		}
25602b69b28SMiklos Szeredi 
25702b69b28SMiklos Szeredi 		if (d.redirect) {
25802b69b28SMiklos Szeredi 			upperredirect = kstrdup(d.redirect, GFP_KERNEL);
25902b69b28SMiklos Szeredi 			if (!upperredirect)
26002b69b28SMiklos Szeredi 				goto out_put_upper;
26102b69b28SMiklos Szeredi 			if (d.redirect[0] == '/')
26202b69b28SMiklos Szeredi 				poe = dentry->d_sb->s_root->d_fsdata;
26302b69b28SMiklos Szeredi 		}
264e28edc46SMiklos Szeredi 		upperopaque = d.opaque;
265bbb1e54dSMiklos Szeredi 	}
266bbb1e54dSMiklos Szeredi 
267e28edc46SMiklos Szeredi 	if (!d.stop && poe->numlower) {
268bbb1e54dSMiklos Szeredi 		err = -ENOMEM;
26902b69b28SMiklos Szeredi 		stack = kcalloc(ofs->numlower, sizeof(struct path),
270e28edc46SMiklos Szeredi 				GFP_TEMPORARY);
271bbb1e54dSMiklos Szeredi 		if (!stack)
272bbb1e54dSMiklos Szeredi 			goto out_put_upper;
273bbb1e54dSMiklos Szeredi 	}
274bbb1e54dSMiklos Szeredi 
275e28edc46SMiklos Szeredi 	for (i = 0; !d.stop && i < poe->numlower; i++) {
276bbb1e54dSMiklos Szeredi 		struct path lowerpath = poe->lowerstack[i];
277bbb1e54dSMiklos Szeredi 
278e28edc46SMiklos Szeredi 		d.last = i == poe->numlower - 1;
279e28edc46SMiklos Szeredi 		err = ovl_lookup_layer(lowerpath.dentry, &d, &this);
280e28edc46SMiklos Szeredi 		if (err)
281bbb1e54dSMiklos Szeredi 			goto out_put;
2826b2d5fe4SMiklos Szeredi 
283bbb1e54dSMiklos Szeredi 		if (!this)
284bbb1e54dSMiklos Szeredi 			continue;
285bbb1e54dSMiklos Szeredi 
286bbb1e54dSMiklos Szeredi 		stack[ctr].dentry = this;
287bbb1e54dSMiklos Szeredi 		stack[ctr].mnt = lowerpath.mnt;
288bbb1e54dSMiklos Szeredi 		ctr++;
28902b69b28SMiklos Szeredi 
29002b69b28SMiklos Szeredi 		if (d.stop)
29102b69b28SMiklos Szeredi 			break;
29202b69b28SMiklos Szeredi 
29302b69b28SMiklos Szeredi 		if (d.redirect &&
29402b69b28SMiklos Szeredi 		    d.redirect[0] == '/' &&
29502b69b28SMiklos Szeredi 		    poe != dentry->d_sb->s_root->d_fsdata) {
29602b69b28SMiklos Szeredi 			poe = dentry->d_sb->s_root->d_fsdata;
29702b69b28SMiklos Szeredi 
29802b69b28SMiklos Szeredi 			/* Find the current layer on the root dentry */
29902b69b28SMiklos Szeredi 			for (i = 0; i < poe->numlower; i++)
30002b69b28SMiklos Szeredi 				if (poe->lowerstack[i].mnt == lowerpath.mnt)
30102b69b28SMiklos Szeredi 					break;
30202b69b28SMiklos Szeredi 			if (WARN_ON(i == poe->numlower))
30302b69b28SMiklos Szeredi 				break;
30402b69b28SMiklos Szeredi 		}
305bbb1e54dSMiklos Szeredi 	}
306bbb1e54dSMiklos Szeredi 
307bbb1e54dSMiklos Szeredi 	oe = ovl_alloc_entry(ctr);
308bbb1e54dSMiklos Szeredi 	err = -ENOMEM;
309bbb1e54dSMiklos Szeredi 	if (!oe)
310bbb1e54dSMiklos Szeredi 		goto out_put;
311bbb1e54dSMiklos Szeredi 
312bbb1e54dSMiklos Szeredi 	if (upperdentry || ctr) {
313bbb1e54dSMiklos Szeredi 		struct dentry *realdentry;
314bbb1e54dSMiklos Szeredi 		struct inode *realinode;
315bbb1e54dSMiklos Szeredi 
316bbb1e54dSMiklos Szeredi 		realdentry = upperdentry ? upperdentry : stack[0].dentry;
317bbb1e54dSMiklos Szeredi 		realinode = d_inode(realdentry);
318bbb1e54dSMiklos Szeredi 
319bbb1e54dSMiklos Szeredi 		err = -ENOMEM;
320bbb1e54dSMiklos Szeredi 		if (upperdentry && !d_is_dir(upperdentry)) {
321bbb1e54dSMiklos Szeredi 			inode = ovl_get_inode(dentry->d_sb, realinode);
322bbb1e54dSMiklos Szeredi 		} else {
323bbb1e54dSMiklos Szeredi 			inode = ovl_new_inode(dentry->d_sb, realinode->i_mode,
324bbb1e54dSMiklos Szeredi 					      realinode->i_rdev);
325bbb1e54dSMiklos Szeredi 			if (inode)
326bbb1e54dSMiklos Szeredi 				ovl_inode_init(inode, realinode, !!upperdentry);
327bbb1e54dSMiklos Szeredi 		}
328bbb1e54dSMiklos Szeredi 		if (!inode)
329bbb1e54dSMiklos Szeredi 			goto out_free_oe;
330bbb1e54dSMiklos Szeredi 		ovl_copyattr(realdentry->d_inode, inode);
331bbb1e54dSMiklos Szeredi 	}
332bbb1e54dSMiklos Szeredi 
333bbb1e54dSMiklos Szeredi 	revert_creds(old_cred);
334bbb1e54dSMiklos Szeredi 	oe->opaque = upperopaque;
33502b69b28SMiklos Szeredi 	oe->redirect = upperredirect;
336bbb1e54dSMiklos Szeredi 	oe->__upperdentry = upperdentry;
337bbb1e54dSMiklos Szeredi 	memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
338bbb1e54dSMiklos Szeredi 	kfree(stack);
33902b69b28SMiklos Szeredi 	kfree(d.redirect);
340bbb1e54dSMiklos Szeredi 	dentry->d_fsdata = oe;
341bbb1e54dSMiklos Szeredi 	d_add(dentry, inode);
342bbb1e54dSMiklos Szeredi 
343bbb1e54dSMiklos Szeredi 	return NULL;
344bbb1e54dSMiklos Szeredi 
345bbb1e54dSMiklos Szeredi out_free_oe:
346bbb1e54dSMiklos Szeredi 	kfree(oe);
347bbb1e54dSMiklos Szeredi out_put:
348bbb1e54dSMiklos Szeredi 	for (i = 0; i < ctr; i++)
349bbb1e54dSMiklos Szeredi 		dput(stack[i].dentry);
350bbb1e54dSMiklos Szeredi 	kfree(stack);
351bbb1e54dSMiklos Szeredi out_put_upper:
352bbb1e54dSMiklos Szeredi 	dput(upperdentry);
35302b69b28SMiklos Szeredi 	kfree(upperredirect);
354bbb1e54dSMiklos Szeredi out:
35502b69b28SMiklos Szeredi 	kfree(d.redirect);
356bbb1e54dSMiklos Szeredi 	revert_creds(old_cred);
357bbb1e54dSMiklos Szeredi 	return ERR_PTR(err);
358bbb1e54dSMiklos Szeredi }
359bbb1e54dSMiklos Szeredi 
360bbb1e54dSMiklos Szeredi bool ovl_lower_positive(struct dentry *dentry)
361bbb1e54dSMiklos Szeredi {
362bbb1e54dSMiklos Szeredi 	struct ovl_entry *oe = dentry->d_fsdata;
363bbb1e54dSMiklos Szeredi 	struct ovl_entry *poe = dentry->d_parent->d_fsdata;
364bbb1e54dSMiklos Szeredi 	const struct qstr *name = &dentry->d_name;
365bbb1e54dSMiklos Szeredi 	unsigned int i;
366bbb1e54dSMiklos Szeredi 	bool positive = false;
367bbb1e54dSMiklos Szeredi 	bool done = false;
368bbb1e54dSMiklos Szeredi 
369bbb1e54dSMiklos Szeredi 	/*
370bbb1e54dSMiklos Szeredi 	 * If dentry is negative, then lower is positive iff this is a
371bbb1e54dSMiklos Szeredi 	 * whiteout.
372bbb1e54dSMiklos Szeredi 	 */
373bbb1e54dSMiklos Szeredi 	if (!dentry->d_inode)
374bbb1e54dSMiklos Szeredi 		return oe->opaque;
375bbb1e54dSMiklos Szeredi 
376bbb1e54dSMiklos Szeredi 	/* Negative upper -> positive lower */
377bbb1e54dSMiklos Szeredi 	if (!oe->__upperdentry)
378bbb1e54dSMiklos Szeredi 		return true;
379bbb1e54dSMiklos Szeredi 
380bbb1e54dSMiklos Szeredi 	/* Positive upper -> have to look up lower to see whether it exists */
381bbb1e54dSMiklos Szeredi 	for (i = 0; !done && !positive && i < poe->numlower; i++) {
382bbb1e54dSMiklos Szeredi 		struct dentry *this;
383bbb1e54dSMiklos Szeredi 		struct dentry *lowerdir = poe->lowerstack[i].dentry;
384bbb1e54dSMiklos Szeredi 
385bbb1e54dSMiklos Szeredi 		this = lookup_one_len_unlocked(name->name, lowerdir,
386bbb1e54dSMiklos Szeredi 					       name->len);
387bbb1e54dSMiklos Szeredi 		if (IS_ERR(this)) {
388bbb1e54dSMiklos Szeredi 			switch (PTR_ERR(this)) {
389bbb1e54dSMiklos Szeredi 			case -ENOENT:
390bbb1e54dSMiklos Szeredi 			case -ENAMETOOLONG:
391bbb1e54dSMiklos Szeredi 				break;
392bbb1e54dSMiklos Szeredi 
393bbb1e54dSMiklos Szeredi 			default:
394bbb1e54dSMiklos Szeredi 				/*
395bbb1e54dSMiklos Szeredi 				 * Assume something is there, we just couldn't
396bbb1e54dSMiklos Szeredi 				 * access it.
397bbb1e54dSMiklos Szeredi 				 */
398bbb1e54dSMiklos Szeredi 				positive = true;
399bbb1e54dSMiklos Szeredi 				break;
400bbb1e54dSMiklos Szeredi 			}
401bbb1e54dSMiklos Szeredi 		} else {
402bbb1e54dSMiklos Szeredi 			if (this->d_inode) {
403bbb1e54dSMiklos Szeredi 				positive = !ovl_is_whiteout(this);
404bbb1e54dSMiklos Szeredi 				done = true;
405bbb1e54dSMiklos Szeredi 			}
406bbb1e54dSMiklos Szeredi 			dput(this);
407bbb1e54dSMiklos Szeredi 		}
408bbb1e54dSMiklos Szeredi 	}
409bbb1e54dSMiklos Szeredi 
410bbb1e54dSMiklos Szeredi 	return positive;
411bbb1e54dSMiklos Szeredi }
412