• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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