Android: sdcardfs: Change cache GID value
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / fs / sdcardfs / lookup.c
... / ...
CommitLineData
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 */
25static struct kmem_cache *sdcardfs_dentry_cachep;
26
27int 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
37void sdcardfs_destroy_dentry_cache(void)
38{
39 kmem_cache_destroy(sdcardfs_dentry_cachep);
40}
41
42void free_dentry_private_data(struct dentry *dentry)
43{
44 if (!dentry || !dentry->d_fsdata)
45 return;
46 kmem_cache_free(sdcardfs_dentry_cachep, dentry->d_fsdata);
47 dentry->d_fsdata = NULL;
48}
49
50/* allocate new dentry private data */
51int new_dentry_private_data(struct dentry *dentry)
52{
53 struct sdcardfs_dentry_info *info = SDCARDFS_D(dentry);
54
55 /* use zalloc to init dentry_info.lower_path */
56 info = kmem_cache_zalloc(sdcardfs_dentry_cachep, GFP_ATOMIC);
57 if (!info)
58 return -ENOMEM;
59
60 spin_lock_init(&info->lock);
61 dentry->d_fsdata = info;
62
63 return 0;
64}
65
66struct inode_data {
67 struct inode *lower_inode;
68 userid_t id;
69};
70
71static int sdcardfs_inode_test(struct inode *inode, void *candidate_data/*void *candidate_lower_inode*/)
72{
73 struct inode *current_lower_inode = sdcardfs_lower_inode(inode);
74 userid_t current_userid = SDCARDFS_I(inode)->userid;
75
76 if (current_lower_inode == ((struct inode_data *)candidate_data)->lower_inode &&
77 current_userid == ((struct inode_data *)candidate_data)->id)
78 return 1; /* found a match */
79 else
80 return 0; /* no match */
81}
82
83static int sdcardfs_inode_set(struct inode *inode, void *lower_inode)
84{
85 /* we do actual inode initialization in sdcardfs_iget */
86 return 0;
87}
88
89struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, userid_t id)
90{
91 struct sdcardfs_inode_info *info;
92 struct inode_data data;
93 struct inode *inode; /* the new inode to return */
94 int err;
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 err = -EACCES;
110 iput(lower_inode);
111 return ERR_PTR(err);
112 }
113 /* if found a cached inode, then just return it */
114 if (!(inode->i_state & I_NEW))
115 return inode;
116
117 /* initialize new inode */
118 info = SDCARDFS_I(inode);
119
120 inode->i_ino = lower_inode->i_ino;
121 if (!igrab(lower_inode)) {
122 err = -ESTALE;
123 return ERR_PTR(err);
124 }
125 sdcardfs_set_lower_inode(inode, lower_inode);
126
127 inode->i_version++;
128
129 /* use different set of inode ops for symlinks & directories */
130 if (S_ISDIR(lower_inode->i_mode))
131 inode->i_op = &sdcardfs_dir_iops;
132 else if (S_ISLNK(lower_inode->i_mode))
133 inode->i_op = &sdcardfs_symlink_iops;
134 else
135 inode->i_op = &sdcardfs_main_iops;
136
137 /* use different set of file ops for directories */
138 if (S_ISDIR(lower_inode->i_mode))
139 inode->i_fop = &sdcardfs_dir_fops;
140 else
141 inode->i_fop = &sdcardfs_main_fops;
142
143 inode->i_mapping->a_ops = &sdcardfs_aops;
144
145 inode->i_atime.tv_sec = 0;
146 inode->i_atime.tv_nsec = 0;
147 inode->i_mtime.tv_sec = 0;
148 inode->i_mtime.tv_nsec = 0;
149 inode->i_ctime.tv_sec = 0;
150 inode->i_ctime.tv_nsec = 0;
151
152 /* properly initialize special inodes */
153 if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
154 S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
155 init_special_inode(inode, lower_inode->i_mode,
156 lower_inode->i_rdev);
157
158 /* all well, copy inode attributes */
159 sdcardfs_copy_and_fix_attrs(inode, lower_inode);
160 fsstack_copy_inode_size(inode, lower_inode);
161
162 unlock_new_inode(inode);
163 return inode;
164}
165
166/*
167 * Helper interpose routine, called directly by ->lookup to handle
168 * spliced dentries.
169 */
170static struct dentry *__sdcardfs_interpose(struct dentry *dentry,
171 struct super_block *sb,
172 struct path *lower_path,
173 userid_t id)
174{
175 struct inode *inode;
176 struct inode *lower_inode;
177 struct super_block *lower_sb;
178 struct dentry *ret_dentry;
179
180 lower_inode = lower_path->dentry->d_inode;
181 lower_sb = sdcardfs_lower_super(sb);
182
183 /* check that the lower file system didn't cross a mount point */
184 if (lower_inode->i_sb != lower_sb) {
185 ret_dentry = ERR_PTR(-EXDEV);
186 goto out;
187 }
188
189 /*
190 * We allocate our new inode below by calling sdcardfs_iget,
191 * which will initialize some of the new inode's fields
192 */
193
194 /* inherit lower inode number for sdcardfs's inode */
195 inode = sdcardfs_iget(sb, lower_inode, id);
196 if (IS_ERR(inode)) {
197 ret_dentry = ERR_CAST(inode);
198 goto out;
199 }
200
201 ret_dentry = d_splice_alias(inode, dentry);
202 dentry = ret_dentry ?: dentry;
203 update_derived_permission_lock(dentry);
204out:
205 return ret_dentry;
206}
207
208/*
209 * Connect an sdcardfs inode dentry/inode with several lower ones. This is
210 * the classic stackable file system "vnode interposition" action.
211 *
212 * @dentry: sdcardfs's dentry which interposes on lower one
213 * @sb: sdcardfs's super_block
214 * @lower_path: the lower path (caller does path_get/put)
215 */
216int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
217 struct path *lower_path, userid_t id)
218{
219 struct dentry *ret_dentry;
220
221 ret_dentry = __sdcardfs_interpose(dentry, sb, lower_path, id);
222 return PTR_ERR(ret_dentry);
223}
224
225struct sdcardfs_name_data {
226 struct dir_context ctx;
227 const struct qstr *to_find;
228 char *name;
229 bool found;
230};
231
232static int sdcardfs_name_match(void *__buf, const char *name, int namelen,
233 loff_t offset, u64 ino, unsigned int d_type)
234{
235 struct sdcardfs_name_data *buf = (struct sdcardfs_name_data *) __buf;
236 struct qstr candidate = QSTR_INIT(name, namelen);
237
238 if (qstr_case_eq(buf->to_find, &candidate)) {
239 memcpy(buf->name, name, namelen);
240 buf->name[namelen] = 0;
241 buf->found = true;
242 return 1;
243 }
244 return 0;
245}
246
247/*
248 * Main driver function for sdcardfs's lookup.
249 *
250 * Returns: NULL (ok), ERR_PTR if an error occurred.
251 * Fills in lower_parent_path with <dentry,mnt> on success.
252 */
253static struct dentry *__sdcardfs_lookup(struct dentry *dentry,
254 unsigned int flags, struct path *lower_parent_path, userid_t id)
255{
256 int err = 0;
257 struct vfsmount *lower_dir_mnt;
258 struct dentry *lower_dir_dentry = NULL;
259 struct dentry *lower_dentry;
260 const struct qstr *name;
261 struct path lower_path;
262 struct qstr dname;
263 struct dentry *ret_dentry = NULL;
264 struct sdcardfs_sb_info *sbi;
265
266 sbi = SDCARDFS_SB(dentry->d_sb);
267 /* must initialize dentry operations */
268 d_set_d_op(dentry, &sdcardfs_ci_dops);
269
270 if (IS_ROOT(dentry))
271 goto out;
272
273 name = &dentry->d_name;
274
275 /* now start the actual lookup procedure */
276 lower_dir_dentry = lower_parent_path->dentry;
277 lower_dir_mnt = lower_parent_path->mnt;
278
279 /* Use vfs_path_lookup to check if the dentry exists or not */
280 err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
281 &lower_path);
282 /* check for other cases */
283 if (err == -ENOENT) {
284 struct file *file;
285 const struct cred *cred = current_cred();
286
287 struct sdcardfs_name_data buffer = {
288 .ctx.actor = sdcardfs_name_match,
289 .to_find = name,
290 .name = __getname(),
291 .found = false,
292 };
293
294 if (!buffer.name) {
295 err = -ENOMEM;
296 goto out;
297 }
298 file = dentry_open(lower_parent_path, O_RDONLY, cred);
299 if (IS_ERR(file)) {
300 err = PTR_ERR(file);
301 goto put_name;
302 }
303 err = iterate_dir(file, &buffer.ctx);
304 fput(file);
305 if (err)
306 goto put_name;
307
308 if (buffer.found)
309 err = vfs_path_lookup(lower_dir_dentry,
310 lower_dir_mnt,
311 buffer.name, 0,
312 &lower_path);
313 else
314 err = -ENOENT;
315put_name:
316 __putname(buffer.name);
317 }
318
319 /* no error: handle positive dentries */
320 if (!err) {
321 /* check if the dentry is an obb dentry
322 * if true, the lower_inode must be replaced with
323 * the inode of the graft path
324 */
325
326 if (need_graft_path(dentry)) {
327
328 /* setup_obb_dentry()
329 * The lower_path will be stored to the dentry's orig_path
330 * and the base obbpath will be copyed to the lower_path variable.
331 * if an error returned, there's no change in the lower_path
332 * returns: -ERRNO if error (0: no error)
333 */
334 err = setup_obb_dentry(dentry, &lower_path);
335
336 if (err) {
337 /* if the sbi->obbpath is not available, we can optionally
338 * setup the lower_path with its orig_path.
339 * but, the current implementation just returns an error
340 * because the sdcard daemon also regards this case as
341 * a lookup fail.
342 */
343 pr_info("sdcardfs: base obbpath is not available\n");
344 sdcardfs_put_reset_orig_path(dentry);
345 goto out;
346 }
347 }
348
349 sdcardfs_set_lower_path(dentry, &lower_path);
350 ret_dentry =
351 __sdcardfs_interpose(dentry, dentry->d_sb, &lower_path, id);
352 if (IS_ERR(ret_dentry)) {
353 err = PTR_ERR(ret_dentry);
354 /* path_put underlying path on error */
355 sdcardfs_put_reset_lower_path(dentry);
356 }
357 goto out;
358 }
359
360 /*
361 * We don't consider ENOENT an error, and we want to return a
362 * negative dentry.
363 */
364 if (err && err != -ENOENT)
365 goto out;
366
367 /* instatiate a new negative dentry */
368 dname.name = name->name;
369 dname.len = name->len;
370 dname.hash = full_name_hash(dname.name, dname.len);
371 lower_dentry = d_lookup(lower_dir_dentry, &dname);
372 if (lower_dentry)
373 goto setup_lower;
374
375 lower_dentry = d_alloc(lower_dir_dentry, &dname);
376 if (!lower_dentry) {
377 err = -ENOMEM;
378 goto out;
379 }
380 d_add(lower_dentry, NULL); /* instantiate and hash */
381
382setup_lower:
383 lower_path.dentry = lower_dentry;
384 lower_path.mnt = mntget(lower_dir_mnt);
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
395out:
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. It is locked (dir->i_mutex)
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 */
412struct 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(parent->d_inode, &dentry->d_name)) {
423 ret = ERR_PTR(-EACCES);
424 goto out_err;
425 }
426
427 /* save current_cred and override it */
428 OVERRIDE_CRED_PTR(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(dir));
429
430 sdcardfs_get_lower_path(parent, &lower_parent_path);
431
432 /* allocate dentry private data. We free it in ->d_release */
433 err = new_dentry_private_data(dentry);
434 if (err) {
435 ret = ERR_PTR(err);
436 goto out;
437 }
438
439 ret = __sdcardfs_lookup(dentry, flags, &lower_parent_path, SDCARDFS_I(dir)->userid);
440 if (IS_ERR(ret))
441 goto out;
442 if (ret)
443 dentry = ret;
444 if (dentry->d_inode) {
445 fsstack_copy_attr_times(dentry->d_inode,
446 sdcardfs_lower_inode(dentry->d_inode));
447 /* get derived permission */
448 get_derived_permission(parent, dentry);
449 fixup_tmp_permissions(dentry->d_inode);
450 fixup_lower_ownership(dentry, dentry->d_name.name);
451 }
452 /* update parent directory's atime */
453 fsstack_copy_attr_atime(parent->d_inode,
454 sdcardfs_lower_inode(parent->d_inode));
455
456out:
457 sdcardfs_put_lower_path(parent, &lower_parent_path);
458 REVERT_CRED(saved_cred);
459out_err:
460 dput(parent);
461 return ret;
462}