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