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