• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * fs/sdcardfs/lookup.c
3  *
4  * Copyright (c) 2013 Samsung Electronics Co. Ltd
5  *   Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
6  *               Sunghwan Yun, Sungjong Seo
7  *
8  * This program has been developed as a stackable file system based on
9  * the WrapFS which written by
10  *
11  * Copyright (c) 1998-2011 Erez Zadok
12  * Copyright (c) 2009     Shrikar Archak
13  * Copyright (c) 2003-2011 Stony Brook University
14  * Copyright (c) 2003-2011 The Research Foundation of SUNY
15  *
16  * This file is dual licensed.  It may be redistributed and/or modified
17  * under the terms of the Apache 2.0 License OR version 2 of the GNU
18  * General Public License.
19  */
20 
21 #include "sdcardfs.h"
22 #include "linux/delay.h"
23 
24 /* The dentry cache is just so we have properly sized dentries */
25 static struct kmem_cache *sdcardfs_dentry_cachep;
26 
sdcardfs_init_dentry_cache(void)27 int sdcardfs_init_dentry_cache(void)
28 {
29 	sdcardfs_dentry_cachep =
30 		kmem_cache_create("sdcardfs_dentry",
31 				  sizeof(struct sdcardfs_dentry_info),
32 				  0, SLAB_RECLAIM_ACCOUNT, NULL);
33 
34 	return sdcardfs_dentry_cachep ? 0 : -ENOMEM;
35 }
36 
sdcardfs_destroy_dentry_cache(void)37 void sdcardfs_destroy_dentry_cache(void)
38 {
39 	kmem_cache_destroy(sdcardfs_dentry_cachep);
40 }
41 
free_dentry_private_data(struct dentry * dentry)42 void free_dentry_private_data(struct dentry *dentry)
43 {
44 	kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata);
45 	dentry->d_fsdata = NULL;
46 }
47 
48 /* allocate new dentry private data */
new_dentry_private_data(struct dentry * dentry)49 int new_dentry_private_data(struct dentry *dentry)
50 {
51 	struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry);
52 
53 	/* use zalloc to init dentry_info.lower_path */
54 	info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC);
55 	if (!info)
56 		return -ENOMEM;
57 
58 	spin_lock_init(&info->lock);
59 	dentry->d_fsdata = info;
60 
61 	return 0;
62 }
63 
64 struct inode_data {
65 	struct inode *lower_inode;
66 	userid_t id;
67 };
68 
sdcardfs_inode_test(struct inode * inode,void * candidate_data)69 static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
70 {
71 	struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
72 	userid_t current_userid = SDCARDFS_I(inode)->data->userid;
73 
74 	if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
75 			current_userid == ((struct inode_data *)candidate_data)->id)
76 		return 1; /* found a match */
77 	else
78 		return 0; /* no match */
79 }
80 
sdcardfs_inode_set(struct inode * inode,void * lower_inode)81 static int sdcardfs_inode_set(struct inode *inode, void *lower_inode)
82 {
83 	/* we do actual inode initialization in sdcardfs_iget */
84 	return 0;
85 }
86 
sdcardfs_iget(struct super_block * sb,struct inode * lower_inode,userid_t id)87 struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
88 {
89 	struct sdcardfs_inode_info *info;
90 	struct inode_data data;
91 	struct inode *inode; /* the new inode to return */
92 
93 	if (!igrab(lower_inode))
94 		return ERR_PTR(-ESTALE);
95 
96 	data.id = id;
97 	data.lower_inode = lower_inode;
98 	inode = iget5_locked(sb, /* our superblock */
99 			     /*
100 			      * hashval: we use inode number, but we can
101 			      * also use "(unsigned long)lower_inode"
102 			      * instead.
103 			      */
104 			     lower_inode->i_ino, /* hashval */
105 			     sdcardfs_inode_test, /* inode comparison function */
106 			     sdcardfs_inode_set, /* inode init function */
107 			     &data); /* data passed to test+set fxns */
108 	if (!inode) {
109 		iput(lower_inode);
110 		return ERR_PTR(-ENOMEM);
111 	}
112 	/* if found a cached inode, then just return it (after iput) */
113 	if (!(inode->i_state & I_NEW)) {
114 		iput(lower_inode);
115 		return inode;
116 	}
117 
118 	/* initialize new inode */
119 	info = SDCARDFS_I(inode);
120 
121 	inode->i_ino = lower_inode->i_ino;
122 	sdcardfs_set_lower_inode(inode, lower_inode);
123 
124 	inode_inc_iversion_raw(inode);
125 
126 	/* use different set of inode ops for symlinks & directories */
127 	if (S_ISDIR(lower_inode->i_mode))
128 		inode->i_op = &sdcardfs_dir_iops;
129 	else if (S_ISLNK(lower_inode->i_mode))
130 		inode->i_op = &sdcardfs_symlink_iops;
131 	else
132 		inode->i_op = &sdcardfs_main_iops;
133 
134 	/* use different set of file ops for directories */
135 	if (S_ISDIR(lower_inode->i_mode))
136 		inode->i_fop = &sdcardfs_dir_fops;
137 	else
138 		inode->i_fop = &sdcardfs_main_fops;
139 
140 	inode->i_mapping->a_ops = &sdcardfs_aops;
141 
142 	inode->i_atime.tv_sec = 0;
143 	inode->i_atime.tv_nsec = 0;
144 	inode->i_mtime.tv_sec = 0;
145 	inode->i_mtime.tv_nsec = 0;
146 	inode->i_ctime.tv_sec = 0;
147 	inode->i_ctime.tv_nsec = 0;
148 
149 	/* properly initialize special inodes */
150 	if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
151 	    S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
152 		init_special_inode(inode, lower_inode->i_mode,
153 				   lower_inode->i_rdev);
154 
155 	/* all well, copy inode attributes */
156 	sdcardfs_copy_and_fix_attrs(inode, lower_inode);
157 	fsstack_copy_inode_size(inode, lower_inode);
158 
159 	unlock_new_inode(inode);
160 	return inode;
161 }
162 
163 /*
164  * Helper interpose routine, called directly by ->lookup to handle
165  * spliced dentries.
166  */
__sdcardfs_interpose(struct dentry * dentry,struct super_block * sb,struct path * lower_path,userid_t id)167 static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
168 					 struct super_block *sb,
169 					 struct path *lower_path,
170 					 userid_t id)
171 {
172 	struct inode *inode;
173 	struct inode *lower_inode;
174 	struct super_block *lower_sb;
175 	struct dentry *ret_dentry;
176 
177 	lower_inode = d_inode(lower_path->dentry);
178 	lower_sb = sdcardfs_lower_super(sb);
179 
180 	/* check that the lower file system didn't cross a mount point */
181 	if (lower_inode->i_sb != lower_sb) {
182 		ret_dentry = ERR_PTR(-EXDEV);
183 		goto out;
184 	}
185 
186 	/*
187 	 * We allocate our new inode below by calling sdcardfs_iget,
188 	 * which will initialize some of the new inode's fields
189 	 */
190 
191 	/* inherit lower inode number for sdcardfs's inode */
192 	inode = sdcardfs_iget(sb, lower_inode, id);
193 	if (IS_ERR(inode)) {
194 		ret_dentry = ERR_CAST(inode);
195 		goto out;
196 	}
197 
198 	ret_dentry = d_splice_alias(inode, dentry);
199 	dentry = ret_dentry ?: dentry;
200 	if (!IS_ERR(dentry))
201 		update_derived_permission_lock(dentry);
202 out:
203 	return ret_dentry;
204 }
205 
206 /*
207  * Connect an sdcardfs inode dentry/inode with several lower ones.  This is
208  * the classic stackable file system "vnode interposition" action.
209  *
210  * @dentry: sdcardfs's dentry which interposes on lower one
211  * @sb: sdcardfs's super_block
212  * @lower_path: the lower path (caller does path_get/put)
213  */
sdcardfs_interpose(struct dentry * dentry,struct super_block * sb,struct path * lower_path,userid_t id)214 int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
215 		     struct path *lower_path, userid_t id)
216 {
217 	struct dentry *ret_dentry;
218 
219 	ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
220 	return PTR_ERR(ret_dentry);
221 }
222 
223 struct sdcardfs_name_data {
224 	struct dir_context ctx;
225 	const struct qstr *to_find;
226 	char *name;
227 	bool found;
228 };
229 
sdcardfs_name_match(struct dir_context * ctx,const char * name,int namelen,loff_t offset,u64 ino,unsigned int d_type)230 static int sdcardfs_name_match(struct dir_context *ctx, const char *name,
231 		int namelen, loff_t offset, u64 ino, unsigned int d_type)
232 {
233 	struct sdcardfs_name_data *buf = container_of(ctx, struct sdcardfs_name_data, ctx);
234 	struct qstr candidate = QSTR_INIT(name, namelen);
235 
236 	if (qstr_case_eq(buf->to_find, &candidate)) {
237 		memcpy(buf->name, name, namelen);
238 		buf->name[namelen] = 0;
239 		buf->found = true;
240 		return 1;
241 	}
242 	return 0;
243 }
244 
245 /*
246  * Main driver function for sdcardfs's lookup.
247  *
248  * Returns: NULL (ok), ERR_PTR if an error occurred.
249  * Fills in lower_parent_path with <dentry,mnt> on success.
250  */
__sdcardfs_lookup(struct dentry * dentry,unsigned int flags,struct path * lower_parent_path,userid_t id)251 static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
252 		unsigned int flags, struct path *lower_parent_path, userid_t id)
253 {
254 	int err = 0;
255 	struct vfsmount *lower_dir_mnt;
256 	struct dentry *lower_dir_dentry = NULL;
257 	struct dentry *lower_dentry;
258 	const struct qstr *name;
259 	struct path lower_path;
260 	struct dentry *ret_dentry = NULL;
261 	struct sdcardfs_sb_info *sbi;
262 
263 	sbi = SDCARDFS_SB(dentry->d_sb);
264 	/* must initialize dentry operations */
265 	d_set_d_op(dentry, &sdcardfs_ci_dops);
266 
267 	if (IS_ROOT(dentry))
268 		goto out;
269 
270 	name = &dentry->d_name;
271 
272 	/* now start the actual lookup procedure */
273 	lower_dir_dentry = lower_parent_path->dentry;
274 	lower_dir_mnt = lower_parent_path->mnt;
275 
276 	/* Use vfs_path_lookup to check if the dentry exists or not */
277 	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
278 				&lower_path);
279 	/* check for other cases */
280 	if (err == -ENOENT) {
281 		struct file *file;
282 		const struct cred *cred = current_cred();
283 
284 		struct sdcardfs_name_data buffer = {
285 			.ctx.actor = sdcardfs_name_match,
286 			.to_find = name,
287 			.name = __getname(),
288 			.found = false,
289 		};
290 
291 		if (!buffer.name) {
292 			err = -ENOMEM;
293 			goto out;
294 		}
295 		file = dentry_open(lower_parent_path, O_RDONLY, cred);
296 		if (IS_ERR(file)) {
297 			err = PTR_ERR(file);
298 			goto put_name;
299 		}
300 		err = iterate_dir(file, &buffer.ctx);
301 		fput(file);
302 		if (err)
303 			goto put_name;
304 
305 		if (buffer.found)
306 			err = vfs_path_lookup(lower_dir_dentry,
307 						lower_dir_mnt,
308 						buffer.name, 0,
309 						&lower_path);
310 		else
311 			err = -ENOENT;
312 put_name:
313 		__putname(buffer.name);
314 	}
315 
316 	/* no error: handle positive dentries */
317 	if (!err) {
318 found:
319 		/* check if the dentry is an obb dentry
320 		 * if true, the lower_inode must be replaced with
321 		 * the inode of the graft path
322 		 */
323 
324 		if (need_graft_path(dentry)) {
325 
326 			/* setup_obb_dentry()
327 			 * The lower_path will be stored to the dentry's orig_path
328 			 * and the base obbpath will be copyed to the lower_path variable.
329 			 * if an error returned, there's no change in the lower_path
330 			 * returns: -ERRNO if error (0: no error)
331 			 */
332 			err = setup_obb_dentry(dentry, &lower_path);
333 
334 			if (err) {
335 				/* if the sbi->obbpath is not available, we can optionally
336 				 * setup the lower_path with its orig_path.
337 				 * but, the current implementation just returns an error
338 				 * because the sdcard daemon also regards this case as
339 				 * a lookup fail.
340 				 */
341 				pr_info("sdcardfs: base obbpath is not available\n");
342 				sdcardfs_put_reset_orig_path(dentry);
343 				goto out;
344 			}
345 		}
346 
347 		sdcardfs_set_lower_path(dentry, &lower_path);
348 		ret_dentry =
349 			__sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
350 		if (IS_ERR(ret_dentry)) {
351 			err = PTR_ERR(ret_dentry);
352 			 /* path_put underlying path on error */
353 			sdcardfs_put_reset_lower_path(dentry);
354 		}
355 		goto out;
356 	}
357 
358 	/*
359 	 * We don't consider ENOENT an error, and we want to return a
360 	 * negative dentry.
361 	 */
362 	if (err && err != -ENOENT)
363 		goto out;
364 
365 	/* get a (very likely) new negative dentry */
366 	lower_dentry = lookup_one_len_unlocked(name->name,
367 					       lower_dir_dentry, name->len);
368 	if (IS_ERR(lower_dentry)) {
369 		err = PTR_ERR(lower_dentry);
370 		goto out;
371 	}
372 
373 	lower_path.dentry = lower_dentry;
374 	lower_path.mnt = mntget(lower_dir_mnt);
375 
376 	/*
377 	 * Check if someone sneakily filled in the dentry when
378 	 * we weren't looking. We'll check again in create.
379 	 */
380 	if (unlikely(d_inode_rcu(lower_dentry))) {
381 		err = 0;
382 		goto found;
383 	}
384 
385 	sdcardfs_set_lower_path(dentry, &lower_path);
386 
387 	/*
388 	 * If the intent is to create a file, then don't return an error, so
389 	 * the VFS will continue the process of making this negative dentry
390 	 * into a positive one.
391 	 */
392 	if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
393 		err = 0;
394 
395 out:
396 	if (err)
397 		return ERR_PTR(err);
398 	return ret_dentry;
399 }
400 
401 /*
402  * On success:
403  * fills dentry object appropriate values and returns NULL.
404  * On fail (== error)
405  * returns error ptr
406  *
407  * @dir : Parent inode.
408  * @dentry : Target dentry to lookup. we should set each of fields.
409  *	     (dentry->d_name is initialized already)
410  * @nd : nameidata of parent inode
411  */
sdcardfs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)412 struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
413 			     unsigned int flags)
414 {
415 	struct dentry *ret = NULL, *parent;
416 	struct path lower_parent_path;
417 	int err = 0;
418 	const struct cred *saved_cred = NULL;
419 
420 	parent = dget_parent(dentry);
421 
422 	if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
423 		ret = ERR_PTR(-EACCES);
424 		goto out_err;
425 	}
426 
427 	/* save current_cred and override it */
428 	saved_cred = override_fsids(SDCARDFS_SB(dir->i_sb),
429 						SDCARDFS_I(dir)->data);
430 	if (!saved_cred) {
431 		ret = ERR_PTR(-ENOMEM);
432 		goto out_err;
433 	}
434 
435 	sdcardfs_get_lower_path(parent, &lower_parent_path);
436 
437 	/* allocate dentry private data.  We free it in ->d_release */
438 	err = new_dentry_private_data(dentry);
439 	if (err) {
440 		ret = ERR_PTR(err);
441 		goto out;
442 	}
443 
444 	ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
445 				SDCARDFS_I(dir)->data->userid);
446 	if (IS_ERR(ret))
447 		goto out;
448 	if (ret)
449 		dentry = ret;
450 	if (d_inode(dentry)) {
451 		fsstack_copy_attr_times(d_inode(dentry),
452 					sdcardfs_lower_inode(d_inode(dentry)));
453 		/* get derived permission */
454 		get_derived_permission(parent, dentry);
455 		fixup_tmp_permissions(d_inode(dentry));
456 		fixup_lower_ownership(dentry, dentry->d_name.name);
457 	}
458 	/* update parent directory's atime */
459 	fsstack_copy_attr_atime(d_inode(parent),
460 				sdcardfs_lower_inode(d_inode(parent)));
461 
462 out:
463 	sdcardfs_put_lower_path(parent, &lower_parent_path);
464 	revert_fsids(saved_cred);
465 out_err:
466 	dput(parent);
467 	return ret;
468 }
469