• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * fs/sdcardfs/packagelist.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/hashtable.h>
23 #include <linux/ctype.h>
24 #include <linux/delay.h>
25 #include <linux/radix-tree.h>
26 #include <linux/dcache.h>
27 
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/slab.h>
31 
32 #include <linux/configfs.h>
33 
34 struct hashtable_entry {
35 	struct hlist_node hlist;
36 	struct hlist_node dlist; /* for deletion cleanup */
37 	struct qstr key;
38 	atomic_t value;
39 };
40 
41 static DEFINE_HASHTABLE(package_to_appid, 8);
42 static DEFINE_HASHTABLE(package_to_userid, 8);
43 static DEFINE_HASHTABLE(ext_to_groupid, 8);
44 
45 
46 static struct kmem_cache *hashtable_entry_cachep;
47 
full_name_case_hash(const unsigned char * name,unsigned int len)48 static unsigned int full_name_case_hash(const unsigned char *name, unsigned int len)
49 {
50 	unsigned long hash = init_name_hash();
51 
52 	while (len--)
53 		hash = partial_name_hash(tolower(*name++), hash);
54 	return end_name_hash(hash);
55 }
56 
qstr_init(struct qstr * q,const char * name)57 static inline void qstr_init(struct qstr *q, const char *name)
58 {
59 	q->name = name;
60 	q->len = strlen(q->name);
61 	q->hash = full_name_case_hash(q->name, q->len);
62 }
63 
qstr_copy(const struct qstr * src,struct qstr * dest)64 static inline int qstr_copy(const struct qstr *src, struct qstr *dest)
65 {
66 	dest->name = kstrdup(src->name, GFP_KERNEL);
67 	dest->hash_len = src->hash_len;
68 	return !!dest->name;
69 }
70 
71 
__get_appid(const struct qstr * key)72 static appid_t __get_appid(const struct qstr *key)
73 {
74 	struct hashtable_entry *hash_cur;
75 	unsigned int hash = key->hash;
76 	appid_t ret_id;
77 
78 	rcu_read_lock();
79 	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
80 		if (qstr_case_eq(key, &hash_cur->key)) {
81 			ret_id = atomic_read(&hash_cur->value);
82 			rcu_read_unlock();
83 			return ret_id;
84 		}
85 	}
86 	rcu_read_unlock();
87 	return 0;
88 }
89 
get_appid(const char * key)90 appid_t get_appid(const char *key)
91 {
92 	struct qstr q;
93 
94 	qstr_init(&q, key);
95 	return __get_appid(&q);
96 }
97 
__get_ext_gid(const struct qstr * key)98 static appid_t __get_ext_gid(const struct qstr *key)
99 {
100 	struct hashtable_entry *hash_cur;
101 	unsigned int hash = key->hash;
102 	appid_t ret_id;
103 
104 	rcu_read_lock();
105 	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
106 		if (qstr_case_eq(key, &hash_cur->key)) {
107 			ret_id = atomic_read(&hash_cur->value);
108 			rcu_read_unlock();
109 			return ret_id;
110 		}
111 	}
112 	rcu_read_unlock();
113 	return 0;
114 }
115 
get_ext_gid(const char * key)116 appid_t get_ext_gid(const char *key)
117 {
118 	struct qstr q;
119 
120 	qstr_init(&q, key);
121 	return __get_ext_gid(&q);
122 }
123 
__is_excluded(const struct qstr * app_name,userid_t user)124 static appid_t __is_excluded(const struct qstr *app_name, userid_t user)
125 {
126 	struct hashtable_entry *hash_cur;
127 	unsigned int hash = app_name->hash;
128 
129 	rcu_read_lock();
130 	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
131 		if (atomic_read(&hash_cur->value) == user &&
132 				qstr_case_eq(app_name, &hash_cur->key)) {
133 			rcu_read_unlock();
134 			return 1;
135 		}
136 	}
137 	rcu_read_unlock();
138 	return 0;
139 }
140 
is_excluded(const char * key,userid_t user)141 appid_t is_excluded(const char *key, userid_t user)
142 {
143 	struct qstr q;
144 
145 	qstr_init(&q, key);
146 	return __is_excluded(&q, user);
147 }
148 
149 /* Kernel has already enforced everything we returned through
150  * derive_permissions_locked(), so this is used to lock down access
151  * even further, such as enforcing that apps hold sdcard_rw.
152  */
check_caller_access_to_name(struct inode * parent_node,const struct qstr * name)153 int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
154 {
155 	struct qstr q_autorun = QSTR_LITERAL("autorun.inf");
156 	struct qstr q__android_secure = QSTR_LITERAL(".android_secure");
157 	struct qstr q_android_secure = QSTR_LITERAL("android_secure");
158 
159 	/* Always block security-sensitive files at root */
160 	if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) {
161 		if (qstr_case_eq(name, &q_autorun)
162 			|| qstr_case_eq(name, &q__android_secure)
163 			|| qstr_case_eq(name, &q_android_secure)) {
164 			return 0;
165 		}
166 	}
167 
168 	/* Root always has access; access for any other UIDs should always
169 	 * be controlled through packages.list.
170 	 */
171 	if (current_fsuid() == 0)
172 		return 1;
173 
174 	/* No extra permissions to enforce */
175 	return 1;
176 }
177 
alloc_hashtable_entry(const struct qstr * key,appid_t value)178 static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key,
179 		appid_t value)
180 {
181 	struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep,
182 			GFP_KERNEL);
183 	if (!ret)
184 		return NULL;
185 	INIT_HLIST_NODE(&ret->dlist);
186 	INIT_HLIST_NODE(&ret->hlist);
187 
188 	if (!qstr_copy(key, &ret->key)) {
189 		kmem_cache_free(hashtable_entry_cachep, ret);
190 		return NULL;
191 	}
192 
193 	atomic_set(&ret->value, value);
194 	return ret;
195 }
196 
insert_packagelist_appid_entry_locked(const struct qstr * key,appid_t value)197 static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value)
198 {
199 	struct hashtable_entry *hash_cur;
200 	struct hashtable_entry *new_entry;
201 	unsigned int hash = key->hash;
202 
203 	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
204 		if (qstr_case_eq(key, &hash_cur->key)) {
205 			atomic_set(&hash_cur->value, value);
206 			return 0;
207 		}
208 	}
209 	new_entry = alloc_hashtable_entry(key, value);
210 	if (!new_entry)
211 		return -ENOMEM;
212 	hash_add_rcu(package_to_appid, &new_entry->hlist, hash);
213 	return 0;
214 }
215 
insert_ext_gid_entry_locked(const struct qstr * key,appid_t value)216 static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value)
217 {
218 	struct hashtable_entry *hash_cur;
219 	struct hashtable_entry *new_entry;
220 	unsigned int hash = key->hash;
221 
222 	/* An extension can only belong to one gid */
223 	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
224 		if (qstr_case_eq(key, &hash_cur->key))
225 			return -EINVAL;
226 	}
227 	new_entry = alloc_hashtable_entry(key, value);
228 	if (!new_entry)
229 		return -ENOMEM;
230 	hash_add_rcu(ext_to_groupid, &new_entry->hlist, hash);
231 	return 0;
232 }
233 
insert_userid_exclude_entry_locked(const struct qstr * key,userid_t value)234 static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value)
235 {
236 	struct hashtable_entry *hash_cur;
237 	struct hashtable_entry *new_entry;
238 	unsigned int hash = key->hash;
239 
240 	/* Only insert if not already present */
241 	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
242 		if (atomic_read(&hash_cur->value) == value &&
243 				qstr_case_eq(key, &hash_cur->key))
244 			return 0;
245 	}
246 	new_entry = alloc_hashtable_entry(key, value);
247 	if (!new_entry)
248 		return -ENOMEM;
249 	hash_add_rcu(package_to_userid, &new_entry->hlist, hash);
250 	return 0;
251 }
252 
fixup_all_perms_name(const struct qstr * key)253 static void fixup_all_perms_name(const struct qstr *key)
254 {
255 	struct sdcardfs_sb_info *sbinfo;
256 	struct limit_search limit = {
257 		.flags = BY_NAME,
258 		.name = QSTR_INIT(key->name, key->len),
259 	};
260 	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
261 		if (sbinfo_has_sdcard_magic(sbinfo))
262 			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
263 	}
264 }
265 
fixup_all_perms_name_userid(const struct qstr * key,userid_t userid)266 static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
267 {
268 	struct sdcardfs_sb_info *sbinfo;
269 	struct limit_search limit = {
270 		.flags = BY_NAME | BY_USERID,
271 		.name = QSTR_INIT(key->name, key->len),
272 		.userid = userid,
273 	};
274 	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
275 		if (sbinfo_has_sdcard_magic(sbinfo))
276 			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
277 	}
278 }
279 
fixup_all_perms_userid(userid_t userid)280 static void fixup_all_perms_userid(userid_t userid)
281 {
282 	struct sdcardfs_sb_info *sbinfo;
283 	struct limit_search limit = {
284 		.flags = BY_USERID,
285 		.userid = userid,
286 	};
287 	list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
288 		if (sbinfo_has_sdcard_magic(sbinfo))
289 			fixup_perms_recursive(sbinfo->sb->s_root, &limit);
290 	}
291 }
292 
insert_packagelist_entry(const struct qstr * key,appid_t value)293 static int insert_packagelist_entry(const struct qstr *key, appid_t value)
294 {
295 	int err;
296 
297 	mutex_lock(&sdcardfs_super_list_lock);
298 	err = insert_packagelist_appid_entry_locked(key, value);
299 	if (!err)
300 		fixup_all_perms_name(key);
301 	mutex_unlock(&sdcardfs_super_list_lock);
302 
303 	return err;
304 }
305 
insert_ext_gid_entry(const struct qstr * key,appid_t value)306 static int insert_ext_gid_entry(const struct qstr *key, appid_t value)
307 {
308 	int err;
309 
310 	mutex_lock(&sdcardfs_super_list_lock);
311 	err = insert_ext_gid_entry_locked(key, value);
312 	mutex_unlock(&sdcardfs_super_list_lock);
313 
314 	return err;
315 }
316 
insert_userid_exclude_entry(const struct qstr * key,userid_t value)317 static int insert_userid_exclude_entry(const struct qstr *key, userid_t value)
318 {
319 	int err;
320 
321 	mutex_lock(&sdcardfs_super_list_lock);
322 	err = insert_userid_exclude_entry_locked(key, value);
323 	if (!err)
324 		fixup_all_perms_name_userid(key, value);
325 	mutex_unlock(&sdcardfs_super_list_lock);
326 
327 	return err;
328 }
329 
free_hashtable_entry(struct hashtable_entry * entry)330 static void free_hashtable_entry(struct hashtable_entry *entry)
331 {
332 	kfree(entry->key.name);
333 	kmem_cache_free(hashtable_entry_cachep, entry);
334 }
335 
remove_packagelist_entry_locked(const struct qstr * key)336 static void remove_packagelist_entry_locked(const struct qstr *key)
337 {
338 	struct hashtable_entry *hash_cur;
339 	unsigned int hash = key->hash;
340 	struct hlist_node *h_t;
341 	HLIST_HEAD(free_list);
342 
343 	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
344 		if (qstr_case_eq(key, &hash_cur->key)) {
345 			hash_del_rcu(&hash_cur->hlist);
346 			hlist_add_head(&hash_cur->dlist, &free_list);
347 		}
348 	}
349 	hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
350 		if (qstr_case_eq(key, &hash_cur->key)) {
351 			hash_del_rcu(&hash_cur->hlist);
352 			hlist_add_head(&hash_cur->dlist, &free_list);
353 			break;
354 		}
355 	}
356 	synchronize_rcu();
357 	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
358 		free_hashtable_entry(hash_cur);
359 }
360 
remove_packagelist_entry(const struct qstr * key)361 static void remove_packagelist_entry(const struct qstr *key)
362 {
363 	mutex_lock(&sdcardfs_super_list_lock);
364 	remove_packagelist_entry_locked(key);
365 	fixup_all_perms_name(key);
366 	mutex_unlock(&sdcardfs_super_list_lock);
367 }
368 
remove_ext_gid_entry_locked(const struct qstr * key,gid_t group)369 static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group)
370 {
371 	struct hashtable_entry *hash_cur;
372 	unsigned int hash = key->hash;
373 
374 	hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
375 		if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
376 			hash_del_rcu(&hash_cur->hlist);
377 			synchronize_rcu();
378 			free_hashtable_entry(hash_cur);
379 			break;
380 		}
381 	}
382 }
383 
remove_ext_gid_entry(const struct qstr * key,gid_t group)384 static void remove_ext_gid_entry(const struct qstr *key, gid_t group)
385 {
386 	mutex_lock(&sdcardfs_super_list_lock);
387 	remove_ext_gid_entry_locked(key, group);
388 	mutex_unlock(&sdcardfs_super_list_lock);
389 }
390 
remove_userid_all_entry_locked(userid_t userid)391 static void remove_userid_all_entry_locked(userid_t userid)
392 {
393 	struct hashtable_entry *hash_cur;
394 	struct hlist_node *h_t;
395 	HLIST_HEAD(free_list);
396 	int i;
397 
398 	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
399 		if (atomic_read(&hash_cur->value) == userid) {
400 			hash_del_rcu(&hash_cur->hlist);
401 			hlist_add_head(&hash_cur->dlist, &free_list);
402 		}
403 	}
404 	synchronize_rcu();
405 	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) {
406 		free_hashtable_entry(hash_cur);
407 	}
408 }
409 
remove_userid_all_entry(userid_t userid)410 static void remove_userid_all_entry(userid_t userid)
411 {
412 	mutex_lock(&sdcardfs_super_list_lock);
413 	remove_userid_all_entry_locked(userid);
414 	fixup_all_perms_userid(userid);
415 	mutex_unlock(&sdcardfs_super_list_lock);
416 }
417 
remove_userid_exclude_entry_locked(const struct qstr * key,userid_t userid)418 static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid)
419 {
420 	struct hashtable_entry *hash_cur;
421 	unsigned int hash = key->hash;
422 
423 	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
424 		if (qstr_case_eq(key, &hash_cur->key) &&
425 				atomic_read(&hash_cur->value) == userid) {
426 			hash_del_rcu(&hash_cur->hlist);
427 			synchronize_rcu();
428 			free_hashtable_entry(hash_cur);
429 			break;
430 		}
431 	}
432 }
433 
remove_userid_exclude_entry(const struct qstr * key,userid_t userid)434 static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid)
435 {
436 	mutex_lock(&sdcardfs_super_list_lock);
437 	remove_userid_exclude_entry_locked(key, userid);
438 	fixup_all_perms_name_userid(key, userid);
439 	mutex_unlock(&sdcardfs_super_list_lock);
440 }
441 
packagelist_destroy(void)442 static void packagelist_destroy(void)
443 {
444 	struct hashtable_entry *hash_cur;
445 	struct hlist_node *h_t;
446 	HLIST_HEAD(free_list);
447 	int i;
448 
449 	mutex_lock(&sdcardfs_super_list_lock);
450 	hash_for_each_rcu(package_to_appid, i, hash_cur, hlist) {
451 		hash_del_rcu(&hash_cur->hlist);
452 		hlist_add_head(&hash_cur->dlist, &free_list);
453 	}
454 	hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
455 		hash_del_rcu(&hash_cur->hlist);
456 		hlist_add_head(&hash_cur->dlist, &free_list);
457 	}
458 	synchronize_rcu();
459 	hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
460 		free_hashtable_entry(hash_cur);
461 	mutex_unlock(&sdcardfs_super_list_lock);
462 	pr_info("sdcardfs: destroyed packagelist pkgld\n");
463 }
464 
465 struct package_details {
466 	struct config_item item;
467 	struct qstr name;
468 };
469 
to_package_details(struct config_item * item)470 static inline struct package_details *to_package_details(struct config_item *item)
471 {
472 	return item ? container_of(item, struct package_details, item) : NULL;
473 }
474 
475 CONFIGFS_ATTR_STRUCT(package_details);
476 #define PACKAGE_DETAILS_ATTR(_name, _mode, _show, _store)	\
477 struct package_details_attribute package_details_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
478 #define PACKAGE_DETAILS_ATTRIBUTE(name) (&package_details_attr_##name.attr)
479 
package_details_appid_show(struct package_details * package_details,char * page)480 static ssize_t package_details_appid_show(struct package_details *package_details,
481 				      char *page)
482 {
483 	return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&package_details->name));
484 }
485 
package_details_appid_store(struct package_details * package_details,const char * page,size_t count)486 static ssize_t package_details_appid_store(struct package_details *package_details,
487 				       const char *page, size_t count)
488 {
489 	unsigned int tmp;
490 	int ret;
491 
492 	ret = kstrtouint(page, 10, &tmp);
493 	if (ret)
494 		return ret;
495 
496 	ret = insert_packagelist_entry(&package_details->name, tmp);
497 
498 	if (ret)
499 		return ret;
500 
501 	return count;
502 }
503 
package_details_excluded_userids_show(struct package_details * package_details,char * page)504 static ssize_t package_details_excluded_userids_show(struct package_details *package_details,
505 				      char *page)
506 {
507 	struct hashtable_entry *hash_cur;
508 	unsigned int hash = package_details->name.hash;
509 	int count = 0;
510 
511 	rcu_read_lock();
512 	hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
513 		if (qstr_case_eq(&package_details->name, &hash_cur->key))
514 			count += scnprintf(page + count, PAGE_SIZE - count,
515 					"%d ", atomic_read(&hash_cur->value));
516 	}
517 	rcu_read_unlock();
518 	if (count)
519 		count--;
520 	count += scnprintf(page + count, PAGE_SIZE - count, "\n");
521 	return count;
522 }
523 
package_details_excluded_userids_store(struct package_details * package_details,const char * page,size_t count)524 static ssize_t package_details_excluded_userids_store(struct package_details *package_details,
525 				       const char *page, size_t count)
526 {
527 	unsigned int tmp;
528 	int ret;
529 
530 	ret = kstrtouint(page, 10, &tmp);
531 	if (ret)
532 		return ret;
533 
534 	ret = insert_userid_exclude_entry(&package_details->name, tmp);
535 
536 	if (ret)
537 		return ret;
538 
539 	return count;
540 }
541 
package_details_clear_userid_store(struct package_details * package_details,const char * page,size_t count)542 static ssize_t package_details_clear_userid_store(struct package_details *package_details,
543 				       const char *page, size_t count)
544 {
545 	unsigned int tmp;
546 	int ret;
547 
548 	ret = kstrtouint(page, 10, &tmp);
549 	if (ret)
550 		return ret;
551 	remove_userid_exclude_entry(&package_details->name, tmp);
552 	return count;
553 }
554 
package_details_release(struct config_item * item)555 static void package_details_release(struct config_item *item)
556 {
557 	struct package_details *package_details = to_package_details(item);
558 
559 	pr_info("sdcardfs: removing %s\n", package_details->name.name);
560 	remove_packagelist_entry(&package_details->name);
561 	kfree(package_details->name.name);
562 	kfree(package_details);
563 }
564 
565 PACKAGE_DETAILS_ATTR(appid, S_IRUGO | S_IWUGO, package_details_appid_show, package_details_appid_store);
566 PACKAGE_DETAILS_ATTR(excluded_userids, S_IRUGO | S_IWUGO,
567 		package_details_excluded_userids_show, package_details_excluded_userids_store);
568 PACKAGE_DETAILS_ATTR(clear_userid, S_IWUGO, NULL, package_details_clear_userid_store);
569 
570 static struct configfs_attribute *package_details_attrs[] = {
571 	PACKAGE_DETAILS_ATTRIBUTE(appid),
572 	PACKAGE_DETAILS_ATTRIBUTE(excluded_userids),
573 	PACKAGE_DETAILS_ATTRIBUTE(clear_userid),
574 	NULL,
575 };
576 
577 CONFIGFS_ATTR_OPS(package_details);
578 
579 static struct configfs_item_operations package_details_item_ops = {
580 	.release = package_details_release,
581 	.show_attribute = package_details_attr_show,
582 	.store_attribute = package_details_attr_store,
583 };
584 
585 static struct config_item_type package_appid_type = {
586 	.ct_item_ops	= &package_details_item_ops,
587 	.ct_attrs	= package_details_attrs,
588 	.ct_owner	= THIS_MODULE,
589 };
590 
591 struct extensions_value {
592 	struct config_group group;
593 	unsigned int num;
594 };
595 
596 struct extension_details {
597 	struct config_item item;
598 	struct qstr name;
599 	unsigned int num;
600 };
601 
to_extensions_value(struct config_item * item)602 static inline struct extensions_value *to_extensions_value(struct config_item *item)
603 {
604 	return item ? container_of(to_config_group(item), struct extensions_value, group) : NULL;
605 }
606 
to_extension_details(struct config_item * item)607 static inline struct extension_details *to_extension_details(struct config_item *item)
608 {
609 	return item ? container_of(item, struct extension_details, item) : NULL;
610 }
611 
extension_details_release(struct config_item * item)612 static void extension_details_release(struct config_item *item)
613 {
614 	struct extension_details *extension_details = to_extension_details(item);
615 
616 	pr_info("sdcardfs: No longer mapping %s files to gid %d\n",
617 			extension_details->name.name, extension_details->num);
618 	remove_ext_gid_entry(&extension_details->name, extension_details->num);
619 	kfree(extension_details->name.name);
620 	kfree(extension_details);
621 }
622 
623 static struct configfs_item_operations extension_details_item_ops = {
624 	.release = extension_details_release,
625 };
626 
627 static struct config_item_type extension_details_type = {
628 	.ct_item_ops = &extension_details_item_ops,
629 	.ct_owner = THIS_MODULE,
630 };
631 
extension_details_make_item(struct config_group * group,const char * name)632 static struct config_item *extension_details_make_item(struct config_group *group, const char *name)
633 {
634 	struct extensions_value *extensions_value = to_extensions_value(&group->cg_item);
635 	struct extension_details *extension_details = kzalloc(sizeof(struct extension_details), GFP_KERNEL);
636 	const char *tmp;
637 	int ret;
638 
639 	if (!extension_details)
640 		return ERR_PTR(-ENOMEM);
641 
642 	tmp = kstrdup(name, GFP_KERNEL);
643 	if (!tmp) {
644 		kfree(extension_details);
645 		return ERR_PTR(-ENOMEM);
646 	}
647 	qstr_init(&extension_details->name, tmp);
648 	ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num);
649 
650 	if (ret) {
651 		kfree(extension_details->name.name);
652 		kfree(extension_details);
653 		return ERR_PTR(ret);
654 	}
655 	config_item_init_type_name(&extension_details->item, name, &extension_details_type);
656 
657 	return &extension_details->item;
658 }
659 
660 static struct configfs_group_operations extensions_value_group_ops = {
661 	.make_item = extension_details_make_item,
662 };
663 
664 static struct config_item_type extensions_name_type = {
665 	.ct_group_ops	= &extensions_value_group_ops,
666 	.ct_owner	= THIS_MODULE,
667 };
668 
extensions_make_group(struct config_group * group,const char * name)669 static struct config_group *extensions_make_group(struct config_group *group, const char *name)
670 {
671 	struct extensions_value *extensions_value;
672 	unsigned int tmp;
673 	int ret;
674 
675 	extensions_value = kzalloc(sizeof(struct extensions_value), GFP_KERNEL);
676 	if (!extensions_value)
677 		return ERR_PTR(-ENOMEM);
678 	ret = kstrtouint(name, 10, &tmp);
679 	if (ret) {
680 		kfree(extensions_value);
681 		return ERR_PTR(ret);
682 	}
683 
684 	extensions_value->num = tmp;
685 	config_group_init_type_name(&extensions_value->group, name,
686 						&extensions_name_type);
687 	return &extensions_value->group;
688 }
689 
extensions_drop_group(struct config_group * group,struct config_item * item)690 static void extensions_drop_group(struct config_group *group, struct config_item *item)
691 {
692 	struct extensions_value *value = to_extensions_value(item);
693 
694 	pr_info("sdcardfs: No longer mapping any files to gid %d\n", value->num);
695 	kfree(value);
696 }
697 
698 static struct configfs_group_operations extensions_group_ops = {
699 	.make_group	= extensions_make_group,
700 	.drop_item	= extensions_drop_group,
701 };
702 
703 static struct config_item_type extensions_type = {
704 	.ct_group_ops	= &extensions_group_ops,
705 	.ct_owner	= THIS_MODULE,
706 };
707 
708 struct config_group extension_group = {
709 	.cg_item = {
710 		.ci_namebuf = "extensions",
711 		.ci_type = &extensions_type,
712 	},
713 };
714 
715 struct packages {
716 	struct configfs_subsystem subsystem;
717 };
718 
to_packages(struct config_item * item)719 static inline struct packages *to_packages(struct config_item *item)
720 {
721 	return item ? container_of(to_configfs_subsystem(to_config_group(item)), struct packages, subsystem) : NULL;
722 }
723 
724 CONFIGFS_ATTR_STRUCT(packages);
725 #define PACKAGES_ATTR(_name, _mode, _show, _store)	\
726 struct packages_attribute packages_attr_##_name = __CONFIGFS_ATTR(_name, _mode, _show, _store)
727 #define PACKAGES_ATTR_RO(_name, _show)	\
728 struct packages_attribute packages_attr_##_name = __CONFIGFS_ATTR_RO(_name, _show)
729 
packages_make_item(struct config_group * group,const char * name)730 static struct config_item *packages_make_item(struct config_group *group, const char *name)
731 {
732 	struct package_details *package_details;
733 	const char *tmp;
734 
735 	package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL);
736 	if (!package_details)
737 		return ERR_PTR(-ENOMEM);
738 	tmp = kstrdup(name, GFP_KERNEL);
739 	if (!tmp) {
740 		kfree(package_details);
741 		return ERR_PTR(-ENOMEM);
742 	}
743 	qstr_init(&package_details->name, tmp);
744 	config_item_init_type_name(&package_details->item, name,
745 						&package_appid_type);
746 
747 	return &package_details->item;
748 }
749 
packages_list_show(struct packages * packages,char * page)750 static ssize_t packages_list_show(struct packages *packages,
751 					 char *page)
752 {
753 	struct hashtable_entry *hash_cur_app;
754 	struct hashtable_entry *hash_cur_user;
755 	int i;
756 	int count = 0, written = 0;
757 	const char errormsg[] = "<truncated>\n";
758 	unsigned int hash;
759 
760 	rcu_read_lock();
761 	hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) {
762 		written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n",
763 					hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
764 		hash = hash_cur_app->key.hash;
765 		hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
766 			if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
767 				written += scnprintf(page + count + written - 1,
768 					PAGE_SIZE - sizeof(errormsg) - count - written + 1,
769 					" %d\n", atomic_read(&hash_cur_user->value)) - 1;
770 			}
771 		}
772 		if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) {
773 			count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
774 			break;
775 		}
776 		count += written;
777 	}
778 	rcu_read_unlock();
779 
780 	return count;
781 }
782 
packages_remove_userid_store(struct packages * packages,const char * page,size_t count)783 static ssize_t packages_remove_userid_store(struct packages *packages,
784 				       const char *page, size_t count)
785 {
786 	unsigned int tmp;
787 	int ret;
788 
789 	ret = kstrtouint(page, 10, &tmp);
790 	if (ret)
791 		return ret;
792 	remove_userid_all_entry(tmp);
793 	return count;
794 }
795 
796 struct packages_attribute packages_attr_packages_gid_list = __CONFIGFS_ATTR_RO(packages_gid.list, packages_list_show);
797 PACKAGES_ATTR(remove_userid, S_IWUGO, NULL, packages_remove_userid_store);
798 
799 static struct configfs_attribute *packages_attrs[] = {
800 	&packages_attr_packages_gid_list.attr,
801 	&packages_attr_remove_userid.attr,
802 	NULL,
803 };
804 
805 CONFIGFS_ATTR_OPS(packages)
806 static struct configfs_item_operations packages_item_ops = {
807 	.show_attribute = packages_attr_show,
808 	.store_attribute = packages_attr_store,
809 };
810 
811 /*
812  * Note that, since no extra work is required on ->drop_item(),
813  * no ->drop_item() is provided.
814  */
815 static struct configfs_group_operations packages_group_ops = {
816 	.make_item	= packages_make_item,
817 };
818 
819 static struct config_item_type packages_type = {
820 	.ct_item_ops	= &packages_item_ops,
821 	.ct_group_ops	= &packages_group_ops,
822 	.ct_attrs	= packages_attrs,
823 	.ct_owner	= THIS_MODULE,
824 };
825 
826 struct config_group *sd_default_groups[] = {
827 	&extension_group,
828 	NULL,
829 };
830 
831 static struct packages sdcardfs_packages = {
832 	.subsystem = {
833 		.su_group = {
834 			.cg_item = {
835 				.ci_namebuf = "sdcardfs",
836 				.ci_type = &packages_type,
837 			},
838 			.default_groups = sd_default_groups,
839 		},
840 	},
841 };
842 
configfs_sdcardfs_init(void)843 static int configfs_sdcardfs_init(void)
844 {
845 	int ret, i;
846 	struct configfs_subsystem *subsys = &sdcardfs_packages.subsystem;
847 
848 	for (i = 0; sd_default_groups[i]; i++)
849 		config_group_init(sd_default_groups[i]);
850 	config_group_init(&subsys->su_group);
851 	mutex_init(&subsys->su_mutex);
852 	ret = configfs_register_subsystem(subsys);
853 	if (ret) {
854 		pr_err("Error %d while registering subsystem %s\n",
855 		       ret,
856 		       subsys->su_group.cg_item.ci_namebuf);
857 	}
858 	return ret;
859 }
860 
configfs_sdcardfs_exit(void)861 static void configfs_sdcardfs_exit(void)
862 {
863 	configfs_unregister_subsystem(&sdcardfs_packages.subsystem);
864 }
865 
packagelist_init(void)866 int packagelist_init(void)
867 {
868 	hashtable_entry_cachep =
869 		kmem_cache_create("packagelist_hashtable_entry",
870 					sizeof(struct hashtable_entry), 0, 0, NULL);
871 	if (!hashtable_entry_cachep) {
872 		pr_err("sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
873 		return -ENOMEM;
874 	}
875 
876 	configfs_sdcardfs_init();
877 	return 0;
878 }
879 
packagelist_exit(void)880 void packagelist_exit(void)
881 {
882 	configfs_sdcardfs_exit();
883 	packagelist_destroy();
884 	kmem_cache_destroy(hashtable_entry_cachep);
885 }
886