blob: 4b9a5635f1e0450693e6cbc1a4fee7c5df3023da [file] [log] [blame]
Daniel Campello35c9e242015-07-20 16:23:50 -07001/*
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"
Daniel Campellod1d080c2015-07-20 16:27:37 -070022#include <linux/hashtable.h>
Daniel Rosenberga8c20782017-03-10 12:39:42 -080023#include <linux/ctype.h>
Daniel Campello35c9e242015-07-20 16:23:50 -070024#include <linux/delay.h>
Daniel Rosenbergad905252017-01-25 13:48:45 -080025#include <linux/radix-tree.h>
Daniel Rosenberg52b77682017-01-27 19:35:08 -080026#include <linux/dcache.h>
Daniel Rosenberg497ac902016-02-03 21:08:21 -080027
28#include <linux/init.h>
29#include <linux/module.h>
30#include <linux/slab.h>
31
32#include <linux/configfs.h>
33
Daniel Campello35c9e242015-07-20 16:23:50 -070034struct hashtable_entry {
Daniel Campellod1d080c2015-07-20 16:27:37 -070035 struct hlist_node hlist;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -080036 struct hlist_node dlist; /* for deletion cleanup */
Daniel Rosenberg52b77682017-01-27 19:35:08 -080037 struct qstr key;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -070038 atomic_t value;
Daniel Campello35c9e242015-07-20 16:23:50 -070039};
40
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -070041static DEFINE_HASHTABLE(package_to_appid, 8);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -080042static DEFINE_HASHTABLE(package_to_userid, 8);
Daniel Rosenbergad905252017-01-25 13:48:45 -080043static DEFINE_HASHTABLE(ext_to_groupid, 8);
44
Daniel Rosenberg497ac902016-02-03 21:08:21 -080045
46static struct kmem_cache *hashtable_entry_cachep;
Daniel Campello35c9e242015-07-20 16:23:50 -070047
Daniel Rosenberga8c20782017-03-10 12:39:42 -080048static 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);
Daniel Rosenberg9608a4a2017-03-21 16:28:27 -070051
Daniel Rosenberga8c20782017-03-10 12:39:42 -080052 while (len--)
53 hash = partial_name_hash(tolower(*name++), hash);
54 return end_name_hash(hash);
55}
56
Daniel Rosenberg52b77682017-01-27 19:35:08 -080057static inline void qstr_init(struct qstr *q, const char *name)
58{
59 q->name = name;
60 q->len = strlen(q->name);
Daniel Rosenberga8c20782017-03-10 12:39:42 -080061 q->hash = full_name_case_hash(0, q->name, q->len);
Daniel Campello35c9e242015-07-20 16:23:50 -070062}
63
Daniel Rosenberg52b77682017-01-27 19:35:08 -080064static 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
72static appid_t __get_appid(const struct qstr *key)
Daniel Campello35c9e242015-07-20 16:23:50 -070073{
Daniel Campello35c9e242015-07-20 16:23:50 -070074 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -080075 unsigned int hash = key->hash;
Daniel Campello35c9e242015-07-20 16:23:50 -070076 appid_t ret_id;
77
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -070078 rcu_read_lock();
79 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -080080 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -080081 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
90appid_t get_appid(const char *key)
91{
92 struct qstr q;
Daniel Rosenberg5e024f62017-03-16 17:42:58 -070093
Daniel Rosenberg52b77682017-01-27 19:35:08 -080094 qstr_init(&q, key);
95 return __get_appid(&q);
96}
97
98static 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) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800106 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800107 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
116appid_t get_ext_gid(const char *key)
117{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800118 struct qstr q;
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700119
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800120 qstr_init(&q, key);
121 return __get_ext_gid(&q);
122}
123
124static appid_t __is_excluded(const struct qstr *app_name, userid_t user)
125{
Daniel Rosenbergad905252017-01-25 13:48:45 -0800126 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800127 unsigned int hash = app_name->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800128
129 rcu_read_lock();
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800130 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
131 if (atomic_read(&hash_cur->value) == user &&
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800132 qstr_case_eq(app_name, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700133 rcu_read_unlock();
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800134 return 1;
Daniel Campello35c9e242015-07-20 16:23:50 -0700135 }
136 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700137 rcu_read_unlock();
Daniel Campello35c9e242015-07-20 16:23:50 -0700138 return 0;
139}
140
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800141appid_t is_excluded(const char *key, userid_t user)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800142{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800143 struct qstr q;
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800144 qstr_init(&q, key);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800145 return __is_excluded(&q, user);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800146}
147
Daniel Campello35c9e242015-07-20 16:23:50 -0700148/* Kernel has already enforced everything we returned through
149 * derive_permissions_locked(), so this is used to lock down access
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700150 * even further, such as enforcing that apps hold sdcard_rw.
151 */
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800152int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800153{
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800154 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
Daniel Campello35c9e242015-07-20 16:23:50 -0700158 /* Always block security-sensitive files at root */
Daniel Rosenberga56a1052017-05-15 14:03:15 -0700159 if (parent_node && SDCARDFS_I(parent_node)->data->perm == PERM_ROOT) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800160 if (qstr_case_eq(name, &q_autorun)
161 || qstr_case_eq(name, &q__android_secure)
162 || qstr_case_eq(name, &q_android_secure)) {
Daniel Campello35c9e242015-07-20 16:23:50 -0700163 return 0;
164 }
165 }
166
Daniel Campello35c9e242015-07-20 16:23:50 -0700167 /* Root always has access; access for any other UIDs should always
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700168 * be controlled through packages.list.
169 */
170 if (from_kuid(&init_user_ns, current_fsuid()) == 0)
Daniel Campello35c9e242015-07-20 16:23:50 -0700171 return 1;
Daniel Campello35c9e242015-07-20 16:23:50 -0700172
Daniel Campello35c9e242015-07-20 16:23:50 -0700173 /* No extra permissions to enforce */
174 return 1;
175}
176
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800177static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key,
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700178 appid_t value)
179{
180 struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep,
181 GFP_KERNEL);
182 if (!ret)
183 return NULL;
Daniel Rosenberg1df48422017-02-22 14:41:58 -0800184 INIT_HLIST_NODE(&ret->dlist);
185 INIT_HLIST_NODE(&ret->hlist);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700186
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800187 if (!qstr_copy(key, &ret->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700188 kmem_cache_free(hashtable_entry_cachep, ret);
189 return NULL;
190 }
191
192 atomic_set(&ret->value, value);
193 return ret;
194}
195
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800196static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value)
Daniel Campello5d3b4162015-07-20 16:33:46 -0700197{
Daniel Campello35c9e242015-07-20 16:23:50 -0700198 struct hashtable_entry *hash_cur;
199 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800200 unsigned int hash = key->hash;
Daniel Campello35c9e242015-07-20 16:23:50 -0700201
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700202 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800203 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700204 atomic_set(&hash_cur->value, value);
Daniel Campello35c9e242015-07-20 16:23:50 -0700205 return 0;
206 }
207 }
Daniel Rosenbergad905252017-01-25 13:48:45 -0800208 new_entry = alloc_hashtable_entry(key, value);
Daniel Campello35c9e242015-07-20 16:23:50 -0700209 if (!new_entry)
210 return -ENOMEM;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700211 hash_add_rcu(package_to_appid, &new_entry->hlist, hash);
Daniel Campello35c9e242015-07-20 16:23:50 -0700212 return 0;
213}
214
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800215static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800216{
217 struct hashtable_entry *hash_cur;
218 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800219 unsigned int hash = key->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800220
221 /* An extension can only belong to one gid */
222 hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800223 if (qstr_case_eq(key, &hash_cur->key))
Daniel Rosenbergad905252017-01-25 13:48:45 -0800224 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
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800233static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800234{
235 struct hashtable_entry *hash_cur;
236 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800237 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800238
239 /* Only insert if not already present */
240 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800241 if (atomic_read(&hash_cur->value) == value &&
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800242 qstr_case_eq(key, &hash_cur->key))
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800243 return 0;
244 }
Daniel Rosenbergad905252017-01-25 13:48:45 -0800245 new_entry = alloc_hashtable_entry(key, value);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800246 if (!new_entry)
247 return -ENOMEM;
248 hash_add_rcu(package_to_userid, &new_entry->hlist, hash);
249 return 0;
250}
251
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800252static void fixup_all_perms_name(const struct qstr *key)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800253{
254 struct sdcardfs_sb_info *sbinfo;
255 struct limit_search limit = {
256 .flags = BY_NAME,
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800257 .name = QSTR_INIT(key->name, key->len),
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800258 };
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);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800262 }
Daniel Campello35c9e242015-07-20 16:23:50 -0700263}
264
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800265static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800266{
267 struct sdcardfs_sb_info *sbinfo;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800268 struct limit_search limit = {
269 .flags = BY_NAME | BY_USERID,
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800270 .name = QSTR_INIT(key->name, key->len),
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800271 .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
279static 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 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700290}
291
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800292static int insert_packagelist_entry(const struct qstr *key, appid_t value)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700293{
294 int err;
295
296 mutex_lock(&sdcardfs_super_list_lock);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800297 err = insert_packagelist_appid_entry_locked(key, value);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700298 if (!err)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800299 fixup_all_perms_name(key);
300 mutex_unlock(&sdcardfs_super_list_lock);
301
302 return err;
303}
304
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800305static int insert_ext_gid_entry(const struct qstr *key, appid_t value)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800306{
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
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800316static int insert_userid_exclude_entry(const struct qstr *key, userid_t value)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800317{
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);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700324 mutex_unlock(&sdcardfs_super_list_lock);
325
326 return err;
327}
328
Daniel Rosenbergad905252017-01-25 13:48:45 -0800329static void free_hashtable_entry(struct hashtable_entry *entry)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700330{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800331 kfree(entry->key.name);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700332 kmem_cache_free(hashtable_entry_cachep, entry);
333}
334
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800335static void remove_packagelist_entry_locked(const struct qstr *key)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700336{
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800337 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800338 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800339 struct hlist_node *h_t;
340 HLIST_HEAD(free_list);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700341
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800342 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800343 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800344 hash_del_rcu(&hash_cur->hlist);
345 hlist_add_head(&hash_cur->dlist, &free_list);
346 }
347 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700348 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800349 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700350 hash_del_rcu(&hash_cur->hlist);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800351 hlist_add_head(&hash_cur->dlist, &free_list);
352 break;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800353 }
354 }
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800355 synchronize_rcu();
356 hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800357 free_hashtable_entry(hash_cur);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700358}
359
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800360static void remove_packagelist_entry(const struct qstr *key)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700361{
362 mutex_lock(&sdcardfs_super_list_lock);
363 remove_packagelist_entry_locked(key);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800364 fixup_all_perms_name(key);
365 mutex_unlock(&sdcardfs_super_list_lock);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800366}
367
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800368static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800369{
370 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800371 unsigned int hash = key->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800372
373 hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800374 if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800375 hash_del_rcu(&hash_cur->hlist);
376 synchronize_rcu();
377 free_hashtable_entry(hash_cur);
378 break;
379 }
380 }
381}
382
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800383static void remove_ext_gid_entry(const struct qstr *key, gid_t group)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800384{
385 mutex_lock(&sdcardfs_super_list_lock);
386 remove_ext_gid_entry_locked(key, group);
387 mutex_unlock(&sdcardfs_super_list_lock);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800388}
389
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800390static 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) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800405 free_hashtable_entry(hash_cur);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800406 }
407}
408
409static 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);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800415}
416
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800417static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800418{
419 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800420 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800421
422 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800423 if (qstr_case_eq(key, &hash_cur->key) &&
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800424 atomic_read(&hash_cur->value) == userid) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800425 hash_del_rcu(&hash_cur->hlist);
426 synchronize_rcu();
Daniel Rosenbergad905252017-01-25 13:48:45 -0800427 free_hashtable_entry(hash_cur);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800428 break;
429 }
430 }
431}
432
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800433static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800434{
435 mutex_lock(&sdcardfs_super_list_lock);
436 remove_userid_exclude_entry_locked(key, userid);
437 fixup_all_perms_name_userid(key, userid);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800438 mutex_unlock(&sdcardfs_super_list_lock);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800439}
440
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700441static void packagelist_destroy(void)
Daniel Campello35c9e242015-07-20 16:23:50 -0700442{
443 struct hashtable_entry *hash_cur;
Daniel Campello35c9e242015-07-20 16:23:50 -0700444 struct hlist_node *h_t;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700445 HLIST_HEAD(free_list);
Daniel Campello35c9e242015-07-20 16:23:50 -0700446 int i;
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700447
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700448 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);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800451 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);
Daniel Campello35c9e242015-07-20 16:23:50 -0700456 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700457 synchronize_rcu();
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800458 hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800459 free_hashtable_entry(hash_cur);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700460 mutex_unlock(&sdcardfs_super_list_lock);
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700461 pr_info("sdcardfs: destroyed packagelist pkgld\n");
Daniel Campello35c9e242015-07-20 16:23:50 -0700462}
463
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800464#define SDCARDFS_CONFIGFS_ATTR(_pfx, _name) \
465static 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) \
474static 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) \
482static 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
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800489struct package_details {
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800490 struct config_item item;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800491 struct qstr name;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800492};
493
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800494static inline struct package_details *to_package_details(struct config_item *item)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800495{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800496 return item ? container_of(item, struct package_details, item) : NULL;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800497}
498
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800499static ssize_t package_details_appid_show(struct config_item *item, char *page)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800500{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800501 return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&to_package_details(item)->name));
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800502}
503
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800504static ssize_t package_details_appid_store(struct config_item *item,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800505 const char *page, size_t count)
506{
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700507 unsigned int tmp;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800508 int ret;
509
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700510 ret = kstrtouint(page, 10, &tmp);
511 if (ret)
512 return ret;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800513
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800514 ret = insert_packagelist_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800515
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800516 if (ret)
517 return ret;
518
519 return count;
520}
521
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800522static 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;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800527 unsigned int hash = package_details->name.hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800528 int count = 0;
529
530 rcu_read_lock();
531 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800532 if (qstr_case_eq(&package_details->name, &hash_cur->key))
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800533 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
543static 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
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800553 ret = insert_userid_exclude_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800554
555 if (ret)
556 return ret;
557
558 return count;
559}
560
561static 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;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800570 remove_userid_exclude_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800571 return count;
572}
573
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800574static void package_details_release(struct config_item *item)
575{
576 struct package_details *package_details = to_package_details(item);
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700577
578 pr_info("sdcardfs: removing %s\n", package_details->name.name);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800579 remove_packagelist_entry(&package_details->name);
580 kfree(package_details->name.name);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800581 kfree(package_details);
582}
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800583
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800584SDCARDFS_CONFIGFS_ATTR(package_details_, appid);
585SDCARDFS_CONFIGFS_ATTR(package_details_, excluded_userids);
586SDCARDFS_CONFIGFS_ATTR_WO(package_details_, clear_userid);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800587
588static struct configfs_attribute *package_details_attrs[] = {
589 &package_details_attr_appid,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800590 &package_details_attr_excluded_userids,
591 &package_details_attr_clear_userid,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800592 NULL,
593};
594
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800595static struct configfs_item_operations package_details_item_ops = {
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700596 .release = package_details_release,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800597};
598
599static struct config_item_type package_appid_type = {
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800600 .ct_item_ops = &package_details_item_ops,
601 .ct_attrs = package_details_attrs,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800602 .ct_owner = THIS_MODULE,
603};
604
Daniel Rosenbergad905252017-01-25 13:48:45 -0800605struct extensions_value {
606 struct config_group group;
607 unsigned int num;
608};
609
610struct extension_details {
611 struct config_item item;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800612 struct qstr name;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800613 unsigned int num;
614};
615
616static 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
621static 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
626static void extension_details_release(struct config_item *item)
627{
628 struct extension_details *extension_details = to_extension_details(item);
629
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700630 pr_info("sdcardfs: No longer mapping %s files to gid %d\n",
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800631 extension_details->name.name, extension_details->num);
632 remove_ext_gid_entry(&extension_details->name, extension_details->num);
633 kfree(extension_details->name.name);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800634 kfree(extension_details);
635}
636
637static struct configfs_item_operations extension_details_item_ops = {
638 .release = extension_details_release,
639};
640
641static struct config_item_type extension_details_type = {
642 .ct_item_ops = &extension_details_item_ops,
643 .ct_owner = THIS_MODULE,
644};
645
646static 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);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800650 const char *tmp;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800651 int ret;
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700652
Daniel Rosenbergad905252017-01-25 13:48:45 -0800653 if (!extension_details)
654 return ERR_PTR(-ENOMEM);
655
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800656 tmp = kstrdup(name, GFP_KERNEL);
657 if (!tmp) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800658 kfree(extension_details);
659 return ERR_PTR(-ENOMEM);
660 }
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800661 qstr_init(&extension_details->name, tmp);
Ritesh Harjanie7f51a52017-12-04 09:51:07 +0530662 extension_details->num = extensions_value->num;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800663 ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800664
665 if (ret) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800666 kfree(extension_details->name.name);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800667 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
675static struct configfs_group_operations extensions_value_group_ops = {
676 .make_item = extension_details_make_item,
677};
678
679static struct config_item_type extensions_name_type = {
680 .ct_group_ops = &extensions_value_group_ops,
681 .ct_owner = THIS_MODULE,
682};
683
684static 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
705static void extensions_drop_group(struct config_group *group, struct config_item *item)
706{
707 struct extensions_value *value = to_extensions_value(item);
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700708
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700709 pr_info("sdcardfs: No longer mapping any files to gid %d\n", value->num);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800710 kfree(value);
711}
712
713static struct configfs_group_operations extensions_group_ops = {
714 .make_group = extensions_make_group,
715 .drop_item = extensions_drop_group,
716};
717
718static struct config_item_type extensions_type = {
719 .ct_group_ops = &extensions_group_ops,
720 .ct_owner = THIS_MODULE,
721};
722
723struct config_group extension_group = {
724 .cg_item = {
725 .ci_namebuf = "extensions",
726 .ci_type = &extensions_type,
727 },
728};
729
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800730static struct config_item *packages_make_item(struct config_group *group, const char *name)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800731{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800732 struct package_details *package_details;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800733 const char *tmp;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800734
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800735 package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL);
736 if (!package_details)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800737 return ERR_PTR(-ENOMEM);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800738 tmp = kstrdup(name, GFP_KERNEL);
739 if (!tmp) {
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800740 kfree(package_details);
741 return ERR_PTR(-ENOMEM);
742 }
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800743 qstr_init(&package_details->name, tmp);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800744 config_item_init_type_name(&package_details->item, name,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800745 &package_appid_type);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800746
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800747 return &package_details->item;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800748}
749
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800750static ssize_t packages_list_show(struct config_item *item, char *page)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800751{
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800752 struct hashtable_entry *hash_cur_app;
753 struct hashtable_entry *hash_cur_user;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800754 int i;
Daniel Rosenberg0de3b4c2016-07-08 14:15:14 -0700755 int count = 0, written = 0;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700756 const char errormsg[] = "<truncated>\n";
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800757 unsigned int hash;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800758
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700759 rcu_read_lock();
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800760 hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700761 written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n",
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800762 hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
763 hash = hash_cur_app->key.hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800764 hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800765 if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800766 written += scnprintf(page + count + written - 1,
767 PAGE_SIZE - sizeof(errormsg) - count - written + 1,
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800768 " %d\n", atomic_read(&hash_cur_user->value)) - 1;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800769 }
770 }
771 if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) {
Daniel Rosenberg0de3b4c2016-07-08 14:15:14 -0700772 count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
773 break;
774 }
775 count += written;
776 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700777 rcu_read_unlock();
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800778
779 return count;
780}
781
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800782static 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
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800795static 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,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800800};
801
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800802SDCARDFS_CONFIGFS_ATTR_WO(packages_, remove_userid);
803
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800804static struct configfs_attribute *packages_attrs[] = {
805 &packages_attr_packages_gid_list,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800806 &packages_attr_remove_userid,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800807 NULL,
808};
809
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800810/*
811 * Note that, since no extra work is required on ->drop_item(),
812 * no ->drop_item() is provided.
813 */
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800814static struct configfs_group_operations packages_group_ops = {
815 .make_item = packages_make_item,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800816};
817
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800818static struct config_item_type packages_type = {
819 .ct_group_ops = &packages_group_ops,
820 .ct_attrs = packages_attrs,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800821 .ct_owner = THIS_MODULE,
822};
823
Daniel Rosenbergad905252017-01-25 13:48:45 -0800824struct config_group *sd_default_groups[] = {
825 &extension_group,
826 NULL,
827};
828
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800829static struct configfs_subsystem sdcardfs_packages = {
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800830 .su_group = {
831 .cg_item = {
832 .ci_namebuf = "sdcardfs",
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800833 .ci_type = &packages_type,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800834 },
835 },
836};
837
Daniel Rosenbergcfdb6652016-03-28 16:00:34 -0700838static int configfs_sdcardfs_init(void)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800839{
Daniel Rosenbergad905252017-01-25 13:48:45 -0800840 int ret, i;
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800841 struct configfs_subsystem *subsys = &sdcardfs_packages;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800842
843 config_group_init(&subsys->su_group);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800844 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 }
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800848 mutex_init(&subsys->su_mutex);
849 ret = configfs_register_subsystem(subsys);
850 if (ret) {
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700851 pr_err("Error %d while registering subsystem %s\n",
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800852 ret,
853 subsys->su_group.cg_item.ci_namebuf);
854 }
855 return ret;
856}
857
Daniel Rosenbergcfdb6652016-03-28 16:00:34 -0700858static void configfs_sdcardfs_exit(void)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800859{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800860 configfs_unregister_subsystem(&sdcardfs_packages);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800861}
862
Daniel Campello35c9e242015-07-20 16:23:50 -0700863int 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) {
Daniel Rosenberg77ecf212017-03-16 17:46:13 -0700869 pr_err("sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
Daniel Campello35c9e242015-07-20 16:23:50 -0700870 return -ENOMEM;
871 }
872
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800873 configfs_sdcardfs_init();
Daniel Rosenberg5e024f62017-03-16 17:42:58 -0700874 return 0;
Daniel Campello35c9e242015-07-20 16:23:50 -0700875}
876
877void packagelist_exit(void)
878{
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800879 configfs_sdcardfs_exit();
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700880 packagelist_destroy();
Daniel Rosenbergb6704a82017-03-21 16:29:13 -0700881 kmem_cache_destroy(hashtable_entry_cachep);
Daniel Campello35c9e242015-07-20 16:23:50 -0700882}