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