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->i_version++;
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 qstr dname;
261 struct dentry *ret_dentry = NULL;
262 struct sdcardfs_sb_info *sbi;
263
264 sbi = SDCARDFS_SB(dentry->d_sb);
265 /* must initialize dentry operations */
266 d_set_d_op(dentry, &sdcardfs_ci_dops);
267
268 if (IS_ROOT(dentry))
269 goto out;
270
271 name = &dentry->d_name;
272
273 /* now start the actual lookup procedure */
274 lower_dir_dentry = lower_parent_path->dentry;
275 lower_dir_mnt = lower_parent_path->mnt;
276
277 /* Use vfs_path_lookup to check if the dentry exists or not */
278 err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
279 &lower_path);
280 /* check for other cases */
281 if (err == -ENOENT) {
282 struct file *file;
283 const struct cred *cred = current_cred();
284
285 struct sdcardfs_name_data buffer = {
286 .ctx.actor = sdcardfs_name_match,
287 .to_find = name,
288 .name = __getname(),
289 .found = false,
290 };
291
292 if (!buffer.name) {
293 err = -ENOMEM;
294 goto out;
295 }
296 file = dentry_open(lower_parent_path, O_RDONLY, cred);
297 if (IS_ERR(file)) {
298 err = PTR_ERR(file);
299 goto put_name;
300 }
301 err = iterate_dir(file, &buffer.ctx);
302 fput(file);
303 if (err)
304 goto put_name;
305
306 if (buffer.found)
307 err = vfs_path_lookup(lower_dir_dentry,
308 lower_dir_mnt,
309 buffer.name, 0,
310 &lower_path);
311 else
312 err = -ENOENT;
313 put_name:
314 __putname(buffer.name);
315 }
316
317 /* no error: handle positive dentries */
318 if (!err) {
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 /* instatiate a new negative dentry */
366 dname.name = name->name;
367 dname.len = name->len;
368
369 /* See if the low-level filesystem might want
370 * to use its own hash
371 */
372 lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname);
373 if (IS_ERR(lower_dentry))
374 return lower_dentry;
375 if (!lower_dentry) {
376 /* We called vfs_path_lookup earlier, and did not get a negative
377 * dentry then. Don't confuse the lower filesystem by forcing
378 * one on it now...
379 */
380 err = -ENOENT;
381 goto out;
382 }
383
384 lower_path.dentry = lower_dentry;
385 lower_path.mnt = mntget(lower_dir_mnt);
386 sdcardfs_set_lower_path(dentry, &lower_path);
387
388 /*
389 * If the intent is to create a file, then don't return an error, so
390 * the VFS will continue the process of making this negative dentry
391 * into a positive one.
392 */
393 if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
394 err = 0;
395
396 out:
397 if (err)
398 return ERR_PTR(err);
399 return ret_dentry;
400 }
401
402 /*
403 * On success:
404 * fills dentry object appropriate values and returns NULL.
405 * On fail (== error)
406 * returns error ptr
407 *
408 * @dir : Parent inode.
409 * @dentry : Target dentry to lookup. we should set each of fields.
410 * (dentry->d_name is initialized already)
411 * @nd : nameidata of parent inode
412 */
sdcardfs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)413 struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
414 unsigned int flags)
415 {
416 struct dentry *ret = NULL, *parent;
417 struct path lower_parent_path;
418 int err = 0;
419 const struct cred *saved_cred = NULL;
420
421 parent = dget_parent(dentry);
422
423 if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
424 ret = ERR_PTR(-EACCES);
425 goto out_err;
426 }
427
428 /* save current_cred and override it */
429 OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
430
431 sdcardfs_get_lower_path(parent, &lower_parent_path);
432
433 /* allocate dentry private data. We free it in ->d_release */
434 err = new_dentry_private_data(dentry);
435 if (err) {
436 ret = ERR_PTR(err);
437 goto out;
438 }
439
440 ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path,
441 SDCARDFS_I(dir)->data->userid);
442 if (IS_ERR(ret))
443 goto out;
444 if (ret)
445 dentry = ret;
446 if (d_inode(dentry)) {
447 fsstack_copy_attr_times(d_inode(dentry),
448 sdcardfs_lower_inode(d_inode(dentry)));
449 /* get derived permission */
450 get_derived_permission(parent, dentry);
451 fixup_tmp_permissions(d_inode(dentry));
452 fixup_lower_ownership(dentry, dentry->d_name.name);
453 }
454 /* update parent directory's atime */
455 fsstack_copy_attr_atime(d_inode(parent),
456 sdcardfs_lower_inode(d_inode(parent)));
457
458 out:
459 sdcardfs_put_lower_path(parent, &lower_parent_path);
460 REVERT_CRED(saved_cred);
461 out_err:
462 dput(parent);
463 return ret;
464 }
465