1 /*
2 * fs/sdcardfs/main.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/fs_context.h>
23 #include <linux/fs_parser.h>
24 #include <linux/fscrypt.h>
25 #include <linux/module.h>
26 #include <linux/types.h>
27 #include <linux/parser.h>
28
29 enum sdcardfs_param {
30 Opt_fsuid,
31 Opt_fsgid,
32 Opt_gid,
33 Opt_debug,
34 Opt_mask,
35 Opt_multiuser,
36 Opt_userid,
37 Opt_reserved_mb,
38 Opt_gid_derivation,
39 Opt_default_normal,
40 Opt_nocache,
41 Opt_unshared_obb,
42 Opt_err,
43 };
44
45 static const struct fs_parameter_spec sdcardfs_param_specs[] = {
46 fsparam_u32("fsuid", Opt_fsuid),
47 fsparam_u32("fsgid", Opt_fsgid),
48 fsparam_u32("gid", Opt_gid),
49 fsparam_bool("debug", Opt_debug),
50 fsparam_u32("mask", Opt_mask),
51 fsparam_u32("userid", Opt_userid),
52 fsparam_bool("multiuser", Opt_multiuser),
53 fsparam_bool("derive_gid", Opt_gid_derivation),
54 fsparam_bool("default_normal", Opt_default_normal),
55 fsparam_bool("unshared_obb", Opt_unshared_obb),
56 fsparam_u32("reserved_mb", Opt_reserved_mb),
57 fsparam_bool("nocache", Opt_nocache),
58 {}
59 };
60
61 static const struct fs_parameter_description sdcardfs_parameters = {
62 .name = "sdcardfs",
63 .specs = sdcardfs_param_specs,
64 };
65
sdcardfs_parse_param(struct fs_context * fc,struct fs_parameter * param)66 static int sdcardfs_parse_param(struct fs_context *fc, struct fs_parameter *param)
67 {
68 struct sdcardfs_context_options *fc_opts = fc->fs_private;
69 struct sdcardfs_mount_options *opts = &fc_opts->opts;
70 struct sdcardfs_vfsmount_options *vfsopts = &fc_opts->vfsopts;
71 struct fs_parse_result result;
72 int opt;
73
74 opt = fs_parse(fc, &sdcardfs_parameters, param, &result);
75 if (opt < 0)
76 return opt;
77
78 switch (opt) {
79 case Opt_debug:
80 opts->debug = true;
81 break;
82 case Opt_fsuid:
83 opts->fs_low_uid = result.uint_32;
84 break;
85 case Opt_fsgid:
86 opts->fs_low_gid = result.uint_32;
87 break;
88 case Opt_gid:
89 vfsopts->gid = result.uint_32;
90 break;
91 case Opt_userid:
92 opts->fs_user_id = result.uint_32;
93 break;
94 case Opt_mask:
95 vfsopts->mask = result.uint_32;
96 break;
97 case Opt_multiuser:
98 opts->multiuser = true;
99 break;
100 case Opt_reserved_mb:
101 opts->reserved_mb = result.uint_32;
102 break;
103 case Opt_gid_derivation:
104 opts->gid_derivation = true;
105 break;
106 case Opt_default_normal:
107 opts->default_normal = true;
108 break;
109 case Opt_nocache:
110 opts->nocache = true;
111 break;
112 case Opt_unshared_obb:
113 opts->unshared_obb = true;
114 break;
115 default:
116 return -EINVAL;
117 }
118
119 return 0;
120 }
121
copy_sb_opts(struct sdcardfs_mount_options * opts,struct fs_context * fc)122 static void copy_sb_opts(struct sdcardfs_mount_options *opts,
123 struct fs_context *fc)
124 {
125 struct sdcardfs_context_options *fcopts = fc->fs_private;
126
127 opts->debug = fcopts->opts.debug;
128 opts->default_normal = fcopts->opts.default_normal;
129 opts->fs_low_gid = fcopts->opts.fs_low_gid;
130 opts->fs_low_uid = fcopts->opts.fs_low_uid;
131 opts->fs_user_id = fcopts->opts.fs_user_id;
132 opts->gid_derivation = fcopts->opts.gid_derivation;
133 opts->multiuser = fcopts->opts.multiuser;
134 opts->nocache = fcopts->opts.nocache;
135 opts->reserved_mb = fcopts->opts.reserved_mb;
136 opts->unshared_obb = fcopts->opts.unshared_obb;
137 }
138
139 #if 0
140 /*
141 * our custom d_alloc_root work-alike
142 *
143 * we can't use d_alloc_root if we want to use our own interpose function
144 * unchanged, so we simply call our own "fake" d_alloc_root
145 */
146 static struct dentry *sdcardfs_d_alloc_root(struct super_block *sb)
147 {
148 struct dentry *ret = NULL;
149
150 if (sb) {
151 static const struct qstr name = {
152 .name = "/",
153 .len = 1
154 };
155
156 ret = d_alloc(NULL, &name);
157 if (ret) {
158 d_set_d_op(ret, &sdcardfs_ci_dops);
159 ret->d_sb = sb;
160 ret->d_parent = ret;
161 }
162 }
163 return ret;
164 }
165 #endif
166
167 DEFINE_MUTEX(sdcardfs_super_list_lock);
168 EXPORT_SYMBOL_GPL(sdcardfs_super_list_lock);
169 LIST_HEAD(sdcardfs_super_list);
170 EXPORT_SYMBOL_GPL(sdcardfs_super_list);
171
172 struct sdcardfs_mount_private {
173 struct vfsmount *mnt;
174 const char *dev_name;
175 void *raw_data;
176 };
177
__sdcardfs_fill_super(struct super_block * sb,struct fs_context * fc)178 static int __sdcardfs_fill_super(
179 struct super_block *sb,
180 struct fs_context *fc)
181 {
182 int err = 0;
183 struct super_block *lower_sb;
184 struct path lower_path;
185 struct sdcardfs_sb_info *sb_info;
186 struct inode *inode;
187 const char *dev_name = fc->source;
188 struct sdcardfs_context_options *fcopts = fc->fs_private;
189 struct sdcardfs_mount_options *opts = &fcopts->opts;
190 struct sdcardfs_vfsmount_options *mntopts = &fcopts->vfsopts;
191
192 pr_info("sdcardfs version 2.0\n");
193
194 if (!dev_name) {
195 pr_err("sdcardfs: read_super: missing dev_name argument\n");
196 err = -EINVAL;
197 goto out;
198 }
199
200 pr_info("sdcardfs: dev_name -> %s\n", dev_name);
201 pr_info("sdcardfs: gid=%d,mask=%x\n", mntopts->gid, mntopts->mask);
202
203 /* parse lower path */
204 err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
205 &lower_path);
206 if (err) {
207 pr_err("sdcardfs: error accessing lower directory '%s'\n", dev_name);
208 goto out;
209 }
210
211 /* allocate superblock private data */
212 sb->s_fs_info = kzalloc(sizeof(struct sdcardfs_sb_info), GFP_KERNEL);
213 if (!SDCARDFS_SB(sb)) {
214 pr_crit("sdcardfs: read_super: out of memory\n");
215 err = -ENOMEM;
216 goto out_free;
217 }
218
219 sb_info = sb->s_fs_info;
220 copy_sb_opts(&sb_info->options, fc);
221 if (opts->debug) {
222 pr_info("sdcardfs : options - debug:%d\n", opts->debug);
223 pr_info("sdcardfs : options - gid:%d\n", mntopts->gid);
224 pr_info("sdcardfs : options - mask:%d\n", mntopts->mask);
225 }
226
227 /* set the lower superblock field of upper superblock */
228 lower_sb = lower_path.dentry->d_sb;
229 atomic_inc(&lower_sb->s_active);
230 sdcardfs_set_lower_super(sb, lower_sb);
231
232 sb->s_stack_depth = lower_sb->s_stack_depth + 1;
233 if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
234 pr_err("sdcardfs: maximum fs stacking depth exceeded\n");
235 err = -EINVAL;
236 goto out_sput;
237 }
238
239 /* inherit maxbytes from lower file system */
240 sb->s_maxbytes = lower_sb->s_maxbytes;
241
242 /*
243 * Our c/m/atime granularity is 1 ns because we may stack on file
244 * systems whose granularity is as good.
245 */
246 sb->s_time_gran = 1;
247
248 sb->s_magic = SDCARDFS_SUPER_MAGIC;
249 sb->s_op = &sdcardfs_sops;
250
251 /* get a new inode and allocate our root dentry */
252 inode = sdcardfs_iget(sb, d_inode(lower_path.dentry), 0);
253 if (IS_ERR(inode)) {
254 err = PTR_ERR(inode);
255 goto out_sput;
256 }
257 sb->s_root = d_make_root(inode);
258 if (!sb->s_root) {
259 err = -ENOMEM;
260 goto out_sput;
261 }
262 d_set_d_op(sb->s_root, &sdcardfs_ci_dops);
263
264 /* link the upper and lower dentries */
265 sb->s_root->d_fsdata = NULL;
266 err = new_dentry_private_data(sb->s_root);
267 if (err)
268 goto out_freeroot;
269
270 /* set the lower dentries for s_root */
271 sdcardfs_set_lower_path(sb->s_root, &lower_path);
272
273 /*
274 * No need to call interpose because we already have a positive
275 * dentry, which was instantiated by d_make_root. Just need to
276 * d_rehash it.
277 */
278 d_rehash(sb->s_root);
279
280 /* setup permission policy */
281 sb_info->obbpath_s = kzalloc(PATH_MAX, GFP_KERNEL);
282 mutex_lock(&sdcardfs_super_list_lock);
283 if (sb_info->options.multiuser) {
284 setup_derived_state(d_inode(sb->s_root), PERM_PRE_ROOT,
285 sb_info->options.fs_user_id, AID_ROOT);
286 snprintf(sb_info->obbpath_s, PATH_MAX, "%s/obb", dev_name);
287 } else {
288 setup_derived_state(d_inode(sb->s_root), PERM_ROOT,
289 sb_info->options.fs_user_id, AID_ROOT);
290 snprintf(sb_info->obbpath_s, PATH_MAX, "%s/Android/obb", dev_name);
291 }
292 fixup_tmp_permissions(d_inode(sb->s_root));
293 sb_info->sb = sb;
294 list_add(&sb_info->list, &sdcardfs_super_list);
295 mutex_unlock(&sdcardfs_super_list_lock);
296
297 sb_info->fscrypt_nb.notifier_call = sdcardfs_on_fscrypt_key_removed;
298 fscrypt_register_key_removal_notifier(&sb_info->fscrypt_nb);
299
300 if (!(fc->sb_flags & SB_SILENT))
301 pr_info("sdcardfs: mounted on top of %s type %s\n",
302 dev_name, lower_sb->s_type->name);
303 goto out; /* all is well */
304
305 /* no longer needed: free_dentry_private_data(sb->s_root); */
306 out_freeroot:
307 dput(sb->s_root);
308 sb->s_root = NULL;
309 out_sput:
310 /* drop refs we took earlier */
311 atomic_dec(&lower_sb->s_active);
312 kfree(SDCARDFS_SB(sb));
313 sb->s_fs_info = NULL;
314 out_free:
315 path_put(&lower_path);
316
317 out:
318 return err;
319 }
320
sdcardfs_get_tree(struct fs_context * fc)321 static int sdcardfs_get_tree(struct fs_context *fc)
322 {
323 return vfs_get_super(fc, vfs_get_independent_super,
324 __sdcardfs_fill_super);
325 }
326
sdcardfs_alloc_mnt_data(void)327 void *sdcardfs_alloc_mnt_data(void)
328 {
329 return kmalloc(sizeof(struct sdcardfs_vfsmount_options), GFP_KERNEL);
330 }
331
sdcardfs_kill_sb(struct super_block * sb)332 void sdcardfs_kill_sb(struct super_block *sb)
333 {
334 struct sdcardfs_sb_info *sbi;
335
336 if (sb->s_magic == SDCARDFS_SUPER_MAGIC && sb->s_fs_info) {
337 sbi = SDCARDFS_SB(sb);
338
339 fscrypt_unregister_key_removal_notifier(&sbi->fscrypt_nb);
340
341 mutex_lock(&sdcardfs_super_list_lock);
342 list_del(&sbi->list);
343 mutex_unlock(&sdcardfs_super_list_lock);
344 }
345 kill_anon_super(sb);
346 }
347
sdcardfs_free_fs_context(struct fs_context * fc)348 static void sdcardfs_free_fs_context(struct fs_context *fc)
349 {
350 struct sdcardfs_context_options *fc_opts = fc->fs_private;
351
352 kfree(fc_opts);
353 }
354
355 /* Most of the remount happens in sdcardfs_update_mnt_data */
sdcardfs_reconfigure_context(struct fs_context * fc)356 static int sdcardfs_reconfigure_context(struct fs_context *fc)
357 {
358 struct sdcardfs_context_options *fc_opts = fc->fs_private;
359 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(fc->root->d_sb);
360
361 sbi->options.debug = fc_opts->opts.debug;
362 if (sbi->options.debug) {
363 pr_info("sdcardfs : options - debug:%d\n", sbi->options.debug);
364 pr_info("sdcardfs : options - gid:%d\n", fc_opts->vfsopts.gid);
365 pr_info("sdcardfs : options - mask:%d\n",
366 fc_opts->vfsopts.mask);
367 }
368 return 0;
369 }
370
371 /* reconfigure is handled by sdcardfs_update_mnt_data */
372 static const struct fs_context_operations sdcardfs_context_options_ops = {
373
374 .parse_param = sdcardfs_parse_param,
375 .get_tree = sdcardfs_get_tree,
376 .free = sdcardfs_free_fs_context,
377 .reconfigure = sdcardfs_reconfigure_context,
378 };
379
sdcardfs_init_fs_context(struct fs_context * fc)380 static int sdcardfs_init_fs_context(struct fs_context *fc)
381 {
382 struct sdcardfs_context_options *fc_opts =
383 kmalloc(sizeof(struct sdcardfs_context_options), GFP_KERNEL);
384
385 /* by default, we use AID_MEDIA_RW as uid, gid */
386 fc_opts->opts.fs_low_uid = AID_MEDIA_RW;
387 fc_opts->opts.fs_low_gid = AID_MEDIA_RW;
388 fc_opts->opts.fs_user_id = 0;
389 fc_opts->vfsopts.gid = 0;
390 fc_opts->vfsopts.mask = 0;
391
392 /* by default, 0MB is reserved */
393 fc_opts->opts.reserved_mb = 0;
394 /* by default, gid derivation is off */
395 fc_opts->opts.gid_derivation = false;
396 fc_opts->opts.default_normal = false;
397 fc_opts->opts.nocache = false;
398 fc_opts->opts.multiuser = false;
399 fc_opts->opts.debug = false;
400
401 fc->fs_private = fc_opts;
402 fc->ops = &sdcardfs_context_options_ops;
403 return 0;
404 }
405
406 static struct file_system_type sdcardfs_fs_type = {
407 .owner = THIS_MODULE,
408 .name = SDCARDFS_NAME,
409 .alloc_mnt_data = sdcardfs_alloc_mnt_data,
410 .kill_sb = sdcardfs_kill_sb,
411 .init_fs_context = sdcardfs_init_fs_context,
412 .fs_flags = 0,
413 };
414 MODULE_ALIAS_FS(SDCARDFS_NAME);
415
init_sdcardfs_fs(void)416 static int __init init_sdcardfs_fs(void)
417 {
418 int err;
419
420 pr_info("Registering sdcardfs " SDCARDFS_VERSION "\n");
421
422 err = sdcardfs_init_inode_cache();
423 if (err)
424 goto out;
425 err = sdcardfs_init_dentry_cache();
426 if (err)
427 goto out;
428 err = packagelist_init();
429 if (err)
430 goto out;
431 err = register_filesystem(&sdcardfs_fs_type);
432 out:
433 if (err) {
434 sdcardfs_destroy_inode_cache();
435 sdcardfs_destroy_dentry_cache();
436 packagelist_exit();
437 }
438 return err;
439 }
440
exit_sdcardfs_fs(void)441 static void __exit exit_sdcardfs_fs(void)
442 {
443 sdcardfs_destroy_inode_cache();
444 sdcardfs_destroy_dentry_cache();
445 packagelist_exit();
446 unregister_filesystem(&sdcardfs_fs_type);
447 pr_info("Completed sdcardfs module unload\n");
448 }
449
450 /* Original wrapfs authors */
451 MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University (http://www.fsl.cs.sunysb.edu/)");
452
453 /* Original sdcardfs authors */
454 MODULE_AUTHOR("Woojoong Lee, Daeho Jeong, Kitae Lee, Yeongjin Gil System Memory Lab., Samsung Electronics");
455
456 /* Current maintainer */
457 MODULE_AUTHOR("Daniel Rosenberg, Google");
458 MODULE_DESCRIPTION("Sdcardfs " SDCARDFS_VERSION);
459 MODULE_LICENSE("GPL");
460
461 module_init(init_sdcardfs_fs);
462 module_exit(exit_sdcardfs_fs);
463