blob: 2cc076ca85de0e4745d6eb5af333bee100cc5fe1 [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);
51 while (len--)
52 hash = partial_name_hash(tolower(*name++), hash);
53 return end_name_hash(hash);
54}
55
Daniel Rosenberg52b77682017-01-27 19:35:08 -080056static inline void qstr_init(struct qstr *q, const char *name)
57{
58 q->name = name;
59 q->len = strlen(q->name);
Daniel Rosenberga8c20782017-03-10 12:39:42 -080060 q->hash = full_name_case_hash(0, q->name, q->len);
Daniel Campello35c9e242015-07-20 16:23:50 -070061}
62
Daniel Rosenberg52b77682017-01-27 19:35:08 -080063static inline int qstr_copy(const struct qstr *src, struct qstr *dest)
64{
65 dest->name = kstrdup(src->name, GFP_KERNEL);
66 dest->hash_len = src->hash_len;
67 return !!dest->name;
68}
69
70
71static appid_t __get_appid(const struct qstr *key)
Daniel Campello35c9e242015-07-20 16:23:50 -070072{
Daniel Campello35c9e242015-07-20 16:23:50 -070073 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -080074 unsigned int hash = key->hash;
Daniel Campello35c9e242015-07-20 16:23:50 -070075 appid_t ret_id;
76
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -070077 rcu_read_lock();
78 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -080079 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -080080 ret_id = atomic_read(&hash_cur->value);
81 rcu_read_unlock();
82 return ret_id;
83 }
84 }
85 rcu_read_unlock();
86 return 0;
87}
88
89appid_t get_appid(const char *key)
90{
91 struct qstr q;
92 qstr_init(&q, key);
93 return __get_appid(&q);
94}
95
96static appid_t __get_ext_gid(const struct qstr *key)
97{
98 struct hashtable_entry *hash_cur;
99 unsigned int hash = key->hash;
100 appid_t ret_id;
101
102 rcu_read_lock();
103 hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800104 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800105 ret_id = atomic_read(&hash_cur->value);
106 rcu_read_unlock();
107 return ret_id;
108 }
109 }
110 rcu_read_unlock();
111 return 0;
112}
113
114appid_t get_ext_gid(const char *key)
115{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800116 struct qstr q;
117 qstr_init(&q, key);
118 return __get_ext_gid(&q);
119}
120
121static appid_t __is_excluded(const struct qstr *app_name, userid_t user)
122{
Daniel Rosenbergad905252017-01-25 13:48:45 -0800123 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800124 unsigned int hash = app_name->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800125
126 rcu_read_lock();
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800127 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
128 if (atomic_read(&hash_cur->value) == user &&
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800129 qstr_case_eq(app_name, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700130 rcu_read_unlock();
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800131 return 1;
Daniel Campello35c9e242015-07-20 16:23:50 -0700132 }
133 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700134 rcu_read_unlock();
Daniel Campello35c9e242015-07-20 16:23:50 -0700135 return 0;
136}
137
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800138appid_t is_excluded(const char *key, userid_t user)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800139{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800140 struct qstr q;
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800141 qstr_init(&q, key);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800142 return __is_excluded(&q, user);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800143}
144
Daniel Campello35c9e242015-07-20 16:23:50 -0700145/* Kernel has already enforced everything we returned through
146 * derive_permissions_locked(), so this is used to lock down access
147 * even further, such as enforcing that apps hold sdcard_rw. */
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800148int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800149{
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800150 struct qstr q_autorun = QSTR_LITERAL("autorun.inf");
151 struct qstr q__android_secure = QSTR_LITERAL(".android_secure");
152 struct qstr q_android_secure = QSTR_LITERAL("android_secure");
153
Daniel Campello35c9e242015-07-20 16:23:50 -0700154 /* Always block security-sensitive files at root */
155 if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800156 if (qstr_case_eq(name, &q_autorun)
157 || qstr_case_eq(name, &q__android_secure)
158 || qstr_case_eq(name, &q_android_secure)) {
Daniel Campello35c9e242015-07-20 16:23:50 -0700159 return 0;
160 }
161 }
162
Daniel Campello35c9e242015-07-20 16:23:50 -0700163 /* Root always has access; access for any other UIDs should always
164 * be controlled through packages.list. */
Daniel Campellod1d080c2015-07-20 16:27:37 -0700165 if (from_kuid(&init_user_ns, current_fsuid()) == 0) {
Daniel Campello35c9e242015-07-20 16:23:50 -0700166 return 1;
167 }
168
Daniel Campello35c9e242015-07-20 16:23:50 -0700169 /* No extra permissions to enforce */
170 return 1;
171}
172
173/* This function is used when file opening. The open flags must be
174 * checked before calling check_caller_access_to_name() */
175int open_flags_to_access_mode(int open_flags) {
176 if((open_flags & O_ACCMODE) == O_RDONLY) {
177 return 0; /* R_OK */
178 } else if ((open_flags & O_ACCMODE) == O_WRONLY) {
179 return 1; /* W_OK */
180 } else {
181 /* Probably O_RDRW, but treat as default to be safe */
182 return 1; /* R_OK | W_OK */
183 }
184}
185
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800186static struct hashtable_entry *alloc_hashtable_entry(const struct qstr *key,
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700187 appid_t value)
188{
189 struct hashtable_entry *ret = kmem_cache_alloc(hashtable_entry_cachep,
190 GFP_KERNEL);
191 if (!ret)
192 return NULL;
Daniel Rosenberg1df48422017-02-22 14:41:58 -0800193 INIT_HLIST_NODE(&ret->dlist);
194 INIT_HLIST_NODE(&ret->hlist);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700195
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800196 if (!qstr_copy(key, &ret->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700197 kmem_cache_free(hashtable_entry_cachep, ret);
198 return NULL;
199 }
200
201 atomic_set(&ret->value, value);
202 return ret;
203}
204
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800205static int insert_packagelist_appid_entry_locked(const struct qstr *key, appid_t value)
Daniel Campello5d3b4162015-07-20 16:33:46 -0700206{
Daniel Campello35c9e242015-07-20 16:23:50 -0700207 struct hashtable_entry *hash_cur;
208 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800209 unsigned int hash = key->hash;
Daniel Campello35c9e242015-07-20 16:23:50 -0700210
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700211 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800212 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700213 atomic_set(&hash_cur->value, value);
Daniel Campello35c9e242015-07-20 16:23:50 -0700214 return 0;
215 }
216 }
Daniel Rosenbergad905252017-01-25 13:48:45 -0800217 new_entry = alloc_hashtable_entry(key, value);
Daniel Campello35c9e242015-07-20 16:23:50 -0700218 if (!new_entry)
219 return -ENOMEM;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700220 hash_add_rcu(package_to_appid, &new_entry->hlist, hash);
Daniel Campello35c9e242015-07-20 16:23:50 -0700221 return 0;
222}
223
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800224static int insert_ext_gid_entry_locked(const struct qstr *key, appid_t value)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800225{
226 struct hashtable_entry *hash_cur;
227 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800228 unsigned int hash = key->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800229
230 /* An extension can only belong to one gid */
231 hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800232 if (qstr_case_eq(key, &hash_cur->key))
Daniel Rosenbergad905252017-01-25 13:48:45 -0800233 return -EINVAL;
234 }
235 new_entry = alloc_hashtable_entry(key, value);
236 if (!new_entry)
237 return -ENOMEM;
238 hash_add_rcu(ext_to_groupid, &new_entry->hlist, hash);
239 return 0;
240}
241
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800242static int insert_userid_exclude_entry_locked(const struct qstr *key, userid_t value)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800243{
244 struct hashtable_entry *hash_cur;
245 struct hashtable_entry *new_entry;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800246 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800247
248 /* Only insert if not already present */
249 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800250 if (atomic_read(&hash_cur->value) == value &&
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800251 qstr_case_eq(key, &hash_cur->key))
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800252 return 0;
253 }
Daniel Rosenbergad905252017-01-25 13:48:45 -0800254 new_entry = alloc_hashtable_entry(key, value);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800255 if (!new_entry)
256 return -ENOMEM;
257 hash_add_rcu(package_to_userid, &new_entry->hlist, hash);
258 return 0;
259}
260
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800261static void fixup_all_perms_name(const struct qstr *key)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800262{
263 struct sdcardfs_sb_info *sbinfo;
264 struct limit_search limit = {
265 .flags = BY_NAME,
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800266 .name = QSTR_INIT(key->name, key->len),
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800267 };
268 list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
269 if (sbinfo_has_sdcard_magic(sbinfo))
270 fixup_perms_recursive(sbinfo->sb->s_root, &limit);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800271 }
Daniel Campello35c9e242015-07-20 16:23:50 -0700272}
273
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800274static void fixup_all_perms_name_userid(const struct qstr *key, userid_t userid)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800275{
276 struct sdcardfs_sb_info *sbinfo;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800277 struct limit_search limit = {
278 .flags = BY_NAME | BY_USERID,
Daniel Rosenberg721274a2017-03-08 17:20:02 -0800279 .name = QSTR_INIT(key->name, key->len),
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800280 .userid = userid,
281 };
282 list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
283 if (sbinfo_has_sdcard_magic(sbinfo))
284 fixup_perms_recursive(sbinfo->sb->s_root, &limit);
285 }
286}
287
288static void fixup_all_perms_userid(userid_t userid)
289{
290 struct sdcardfs_sb_info *sbinfo;
291 struct limit_search limit = {
292 .flags = BY_USERID,
293 .userid = userid,
294 };
295 list_for_each_entry(sbinfo, &sdcardfs_super_list, list) {
296 if (sbinfo_has_sdcard_magic(sbinfo))
297 fixup_perms_recursive(sbinfo->sb->s_root, &limit);
298 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700299}
300
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800301static int insert_packagelist_entry(const struct qstr *key, appid_t value)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700302{
303 int err;
304
305 mutex_lock(&sdcardfs_super_list_lock);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800306 err = insert_packagelist_appid_entry_locked(key, value);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700307 if (!err)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800308 fixup_all_perms_name(key);
309 mutex_unlock(&sdcardfs_super_list_lock);
310
311 return err;
312}
313
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800314static int insert_ext_gid_entry(const struct qstr *key, appid_t value)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800315{
316 int err;
317
318 mutex_lock(&sdcardfs_super_list_lock);
319 err = insert_ext_gid_entry_locked(key, value);
320 mutex_unlock(&sdcardfs_super_list_lock);
321
322 return err;
323}
324
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800325static int insert_userid_exclude_entry(const struct qstr *key, userid_t value)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800326{
327 int err;
328
329 mutex_lock(&sdcardfs_super_list_lock);
330 err = insert_userid_exclude_entry_locked(key, value);
331 if (!err)
332 fixup_all_perms_name_userid(key, value);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700333 mutex_unlock(&sdcardfs_super_list_lock);
334
335 return err;
336}
337
Daniel Rosenbergad905252017-01-25 13:48:45 -0800338static void free_hashtable_entry(struct hashtable_entry *entry)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700339{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800340 kfree(entry->key.name);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700341 kmem_cache_free(hashtable_entry_cachep, entry);
342}
343
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800344static void remove_packagelist_entry_locked(const struct qstr *key)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700345{
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800346 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800347 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800348 struct hlist_node *h_t;
349 HLIST_HEAD(free_list);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700350
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800351 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800352 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800353 hash_del_rcu(&hash_cur->hlist);
354 hlist_add_head(&hash_cur->dlist, &free_list);
355 }
356 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700357 hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800358 if (qstr_case_eq(key, &hash_cur->key)) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700359 hash_del_rcu(&hash_cur->hlist);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800360 hlist_add_head(&hash_cur->dlist, &free_list);
361 break;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800362 }
363 }
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800364 synchronize_rcu();
365 hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800366 free_hashtable_entry(hash_cur);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700367}
368
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800369static void remove_packagelist_entry(const struct qstr *key)
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700370{
371 mutex_lock(&sdcardfs_super_list_lock);
372 remove_packagelist_entry_locked(key);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800373 fixup_all_perms_name(key);
374 mutex_unlock(&sdcardfs_super_list_lock);
375 return;
376}
377
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800378static void remove_ext_gid_entry_locked(const struct qstr *key, gid_t group)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800379{
380 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800381 unsigned int hash = key->hash;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800382
383 hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800384 if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800385 hash_del_rcu(&hash_cur->hlist);
386 synchronize_rcu();
387 free_hashtable_entry(hash_cur);
388 break;
389 }
390 }
391}
392
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800393static void remove_ext_gid_entry(const struct qstr *key, gid_t group)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800394{
395 mutex_lock(&sdcardfs_super_list_lock);
396 remove_ext_gid_entry_locked(key, group);
397 mutex_unlock(&sdcardfs_super_list_lock);
398 return;
399}
400
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800401static void remove_userid_all_entry_locked(userid_t userid)
402{
403 struct hashtable_entry *hash_cur;
404 struct hlist_node *h_t;
405 HLIST_HEAD(free_list);
406 int i;
407
408 hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
409 if (atomic_read(&hash_cur->value) == userid) {
410 hash_del_rcu(&hash_cur->hlist);
411 hlist_add_head(&hash_cur->dlist, &free_list);
412 }
413 }
414 synchronize_rcu();
415 hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800416 free_hashtable_entry(hash_cur);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800417 }
418}
419
420static void remove_userid_all_entry(userid_t userid)
421{
422 mutex_lock(&sdcardfs_super_list_lock);
423 remove_userid_all_entry_locked(userid);
424 fixup_all_perms_userid(userid);
425 mutex_unlock(&sdcardfs_super_list_lock);
426 return;
427}
428
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800429static void remove_userid_exclude_entry_locked(const struct qstr *key, userid_t userid)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800430{
431 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800432 unsigned int hash = key->hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800433
434 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800435 if (qstr_case_eq(key, &hash_cur->key) &&
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800436 atomic_read(&hash_cur->value) == userid) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800437 hash_del_rcu(&hash_cur->hlist);
438 synchronize_rcu();
Daniel Rosenbergad905252017-01-25 13:48:45 -0800439 free_hashtable_entry(hash_cur);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800440 break;
441 }
442 }
443}
444
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800445static void remove_userid_exclude_entry(const struct qstr *key, userid_t userid)
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800446{
447 mutex_lock(&sdcardfs_super_list_lock);
448 remove_userid_exclude_entry_locked(key, userid);
449 fixup_all_perms_name_userid(key, userid);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800450 mutex_unlock(&sdcardfs_super_list_lock);
451 return;
452}
453
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700454static void packagelist_destroy(void)
Daniel Campello35c9e242015-07-20 16:23:50 -0700455{
456 struct hashtable_entry *hash_cur;
Daniel Campello35c9e242015-07-20 16:23:50 -0700457 struct hlist_node *h_t;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700458 HLIST_HEAD(free_list);
Daniel Campello35c9e242015-07-20 16:23:50 -0700459 int i;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700460 mutex_lock(&sdcardfs_super_list_lock);
461 hash_for_each_rcu(package_to_appid, i, hash_cur, hlist) {
462 hash_del_rcu(&hash_cur->hlist);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800463 hlist_add_head(&hash_cur->dlist, &free_list);
464 }
465 hash_for_each_rcu(package_to_userid, i, hash_cur, hlist) {
466 hash_del_rcu(&hash_cur->hlist);
467 hlist_add_head(&hash_cur->dlist, &free_list);
Daniel Campello35c9e242015-07-20 16:23:50 -0700468 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700469 synchronize_rcu();
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800470 hlist_for_each_entry_safe(hash_cur, h_t, &free_list, dlist)
Daniel Rosenbergad905252017-01-25 13:48:45 -0800471 free_hashtable_entry(hash_cur);
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700472 mutex_unlock(&sdcardfs_super_list_lock);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800473 printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld\n");
Daniel Campello35c9e242015-07-20 16:23:50 -0700474}
475
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800476#define SDCARDFS_CONFIGFS_ATTR(_pfx, _name) \
477static struct configfs_attribute _pfx##attr_##_name = { \
478 .ca_name = __stringify(_name), \
479 .ca_mode = S_IRUGO | S_IWUGO, \
480 .ca_owner = THIS_MODULE, \
481 .show = _pfx##_name##_show, \
482 .store = _pfx##_name##_store, \
483}
484
485#define SDCARDFS_CONFIGFS_ATTR_RO(_pfx, _name) \
486static struct configfs_attribute _pfx##attr_##_name = { \
487 .ca_name = __stringify(_name), \
488 .ca_mode = S_IRUGO, \
489 .ca_owner = THIS_MODULE, \
490 .show = _pfx##_name##_show, \
491}
492
493#define SDCARDFS_CONFIGFS_ATTR_WO(_pfx, _name) \
494static struct configfs_attribute _pfx##attr_##_name = { \
495 .ca_name = __stringify(_name), \
496 .ca_mode = S_IWUGO, \
497 .ca_owner = THIS_MODULE, \
498 .store = _pfx##_name##_store, \
499}
500
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800501struct package_details {
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800502 struct config_item item;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800503 struct qstr name;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800504};
505
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800506static inline struct package_details *to_package_details(struct config_item *item)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800507{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800508 return item ? container_of(item, struct package_details, item) : NULL;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800509}
510
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800511static ssize_t package_details_appid_show(struct config_item *item, char *page)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800512{
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800513 return scnprintf(page, PAGE_SIZE, "%u\n", __get_appid(&to_package_details(item)->name));
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800514}
515
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800516static ssize_t package_details_appid_store(struct config_item *item,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800517 const char *page, size_t count)
518{
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700519 unsigned int tmp;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800520 int ret;
521
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700522 ret = kstrtouint(page, 10, &tmp);
523 if (ret)
524 return ret;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800525
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800526 ret = insert_packagelist_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800527
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800528 if (ret)
529 return ret;
530
531 return count;
532}
533
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800534static ssize_t package_details_excluded_userids_show(struct config_item *item,
535 char *page)
536{
537 struct package_details *package_details = to_package_details(item);
538 struct hashtable_entry *hash_cur;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800539 unsigned int hash = package_details->name.hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800540 int count = 0;
541
542 rcu_read_lock();
543 hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800544 if (qstr_case_eq(&package_details->name, &hash_cur->key))
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800545 count += scnprintf(page + count, PAGE_SIZE - count,
546 "%d ", atomic_read(&hash_cur->value));
547 }
548 rcu_read_unlock();
549 if (count)
550 count--;
551 count += scnprintf(page + count, PAGE_SIZE - count, "\n");
552 return count;
553}
554
555static ssize_t package_details_excluded_userids_store(struct config_item *item,
556 const char *page, size_t count)
557{
558 unsigned int tmp;
559 int ret;
560
561 ret = kstrtouint(page, 10, &tmp);
562 if (ret)
563 return ret;
564
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800565 ret = insert_userid_exclude_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800566
567 if (ret)
568 return ret;
569
570 return count;
571}
572
573static ssize_t package_details_clear_userid_store(struct config_item *item,
574 const char *page, size_t count)
575{
576 unsigned int tmp;
577 int ret;
578
579 ret = kstrtouint(page, 10, &tmp);
580 if (ret)
581 return ret;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800582 remove_userid_exclude_entry(&to_package_details(item)->name, tmp);
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800583 return count;
584}
585
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800586static void package_details_release(struct config_item *item)
587{
588 struct package_details *package_details = to_package_details(item);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800589 printk(KERN_INFO "sdcardfs: removing %s\n", package_details->name.name);
590 remove_packagelist_entry(&package_details->name);
591 kfree(package_details->name.name);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800592 kfree(package_details);
593}
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800594
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800595SDCARDFS_CONFIGFS_ATTR(package_details_, appid);
596SDCARDFS_CONFIGFS_ATTR(package_details_, excluded_userids);
597SDCARDFS_CONFIGFS_ATTR_WO(package_details_, clear_userid);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800598
599static struct configfs_attribute *package_details_attrs[] = {
600 &package_details_attr_appid,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800601 &package_details_attr_excluded_userids,
602 &package_details_attr_clear_userid,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800603 NULL,
604};
605
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800606static struct configfs_item_operations package_details_item_ops = {
607 .release = package_details_release,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800608};
609
610static struct config_item_type package_appid_type = {
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800611 .ct_item_ops = &package_details_item_ops,
612 .ct_attrs = package_details_attrs,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800613 .ct_owner = THIS_MODULE,
614};
615
Daniel Rosenbergad905252017-01-25 13:48:45 -0800616struct extensions_value {
617 struct config_group group;
618 unsigned int num;
619};
620
621struct extension_details {
622 struct config_item item;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800623 struct qstr name;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800624 unsigned int num;
625};
626
627static inline struct extensions_value *to_extensions_value(struct config_item *item)
628{
629 return item ? container_of(to_config_group(item), struct extensions_value, group) : NULL;
630}
631
632static inline struct extension_details *to_extension_details(struct config_item *item)
633{
634 return item ? container_of(item, struct extension_details, item) : NULL;
635}
636
637static void extension_details_release(struct config_item *item)
638{
639 struct extension_details *extension_details = to_extension_details(item);
640
641 printk(KERN_INFO "sdcardfs: No longer mapping %s files to gid %d\n",
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800642 extension_details->name.name, extension_details->num);
643 remove_ext_gid_entry(&extension_details->name, extension_details->num);
644 kfree(extension_details->name.name);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800645 kfree(extension_details);
646}
647
648static struct configfs_item_operations extension_details_item_ops = {
649 .release = extension_details_release,
650};
651
652static struct config_item_type extension_details_type = {
653 .ct_item_ops = &extension_details_item_ops,
654 .ct_owner = THIS_MODULE,
655};
656
657static struct config_item *extension_details_make_item(struct config_group *group, const char *name)
658{
659 struct extensions_value *extensions_value = to_extensions_value(&group->cg_item);
660 struct extension_details *extension_details = kzalloc(sizeof(struct extension_details), GFP_KERNEL);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800661 const char *tmp;
Daniel Rosenbergad905252017-01-25 13:48:45 -0800662 int ret;
663 if (!extension_details)
664 return ERR_PTR(-ENOMEM);
665
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800666 tmp = kstrdup(name, GFP_KERNEL);
667 if (!tmp) {
Daniel Rosenbergad905252017-01-25 13:48:45 -0800668 kfree(extension_details);
669 return ERR_PTR(-ENOMEM);
670 }
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800671 qstr_init(&extension_details->name, tmp);
672 ret = insert_ext_gid_entry(&extension_details->name, extensions_value->num);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800673
674 if (ret) {
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800675 kfree(extension_details->name.name);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800676 kfree(extension_details);
677 return ERR_PTR(ret);
678 }
679 config_item_init_type_name(&extension_details->item, name, &extension_details_type);
680
681 return &extension_details->item;
682}
683
684static struct configfs_group_operations extensions_value_group_ops = {
685 .make_item = extension_details_make_item,
686};
687
688static struct config_item_type extensions_name_type = {
689 .ct_group_ops = &extensions_value_group_ops,
690 .ct_owner = THIS_MODULE,
691};
692
693static struct config_group *extensions_make_group(struct config_group *group, const char *name)
694{
695 struct extensions_value *extensions_value;
696 unsigned int tmp;
697 int ret;
698
699 extensions_value = kzalloc(sizeof(struct extensions_value), GFP_KERNEL);
700 if (!extensions_value)
701 return ERR_PTR(-ENOMEM);
702 ret = kstrtouint(name, 10, &tmp);
703 if (ret) {
704 kfree(extensions_value);
705 return ERR_PTR(ret);
706 }
707
708 extensions_value->num = tmp;
709 config_group_init_type_name(&extensions_value->group, name,
710 &extensions_name_type);
711 return &extensions_value->group;
712}
713
714static void extensions_drop_group(struct config_group *group, struct config_item *item)
715{
716 struct extensions_value *value = to_extensions_value(item);
717 printk(KERN_INFO "sdcardfs: No longer mapping any files to gid %d\n", value->num);
718 kfree(value);
719}
720
721static struct configfs_group_operations extensions_group_ops = {
722 .make_group = extensions_make_group,
723 .drop_item = extensions_drop_group,
724};
725
726static struct config_item_type extensions_type = {
727 .ct_group_ops = &extensions_group_ops,
728 .ct_owner = THIS_MODULE,
729};
730
731struct config_group extension_group = {
732 .cg_item = {
733 .ci_namebuf = "extensions",
734 .ci_type = &extensions_type,
735 },
736};
737
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800738static struct config_item *packages_make_item(struct config_group *group, const char *name)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800739{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800740 struct package_details *package_details;
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800741 const char *tmp;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800742
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800743 package_details = kzalloc(sizeof(struct package_details), GFP_KERNEL);
744 if (!package_details)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800745 return ERR_PTR(-ENOMEM);
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800746 tmp = kstrdup(name, GFP_KERNEL);
747 if (!tmp) {
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800748 kfree(package_details);
749 return ERR_PTR(-ENOMEM);
750 }
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800751 qstr_init(&package_details->name, tmp);
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800752 config_item_init_type_name(&package_details->item, name,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800753 &package_appid_type);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800754
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800755 return &package_details->item;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800756}
757
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800758static ssize_t packages_list_show(struct config_item *item, char *page)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800759{
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800760 struct hashtable_entry *hash_cur_app;
761 struct hashtable_entry *hash_cur_user;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800762 int i;
Daniel Rosenberg0de3b4c2016-07-08 14:15:14 -0700763 int count = 0, written = 0;
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700764 const char errormsg[] = "<truncated>\n";
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800765 unsigned int hash;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800766
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700767 rcu_read_lock();
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800768 hash_for_each_rcu(package_to_appid, i, hash_cur_app, hlist) {
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700769 written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n",
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800770 hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
771 hash = hash_cur_app->key.hash;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800772 hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
Daniel Rosenberg5004c5f2017-01-31 20:07:51 -0800773 if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800774 written += scnprintf(page + count + written - 1,
775 PAGE_SIZE - sizeof(errormsg) - count - written + 1,
Daniel Rosenberg52b77682017-01-27 19:35:08 -0800776 " %d\n", atomic_read(&hash_cur_user->value)) - 1;
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800777 }
778 }
779 if (count + written == PAGE_SIZE - sizeof(errormsg) - 1) {
Daniel Rosenberg0de3b4c2016-07-08 14:15:14 -0700780 count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
781 break;
782 }
783 count += written;
784 }
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700785 rcu_read_unlock();
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800786
787 return count;
788}
789
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800790static ssize_t packages_remove_userid_store(struct config_item *item,
791 const char *page, size_t count)
792{
793 unsigned int tmp;
794 int ret;
795
796 ret = kstrtouint(page, 10, &tmp);
797 if (ret)
798 return ret;
799 remove_userid_all_entry(tmp);
800 return count;
801}
802
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800803static struct configfs_attribute packages_attr_packages_gid_list = {
804 .ca_name = "packages_gid.list",
805 .ca_mode = S_IRUGO,
806 .ca_owner = THIS_MODULE,
807 .show = packages_list_show,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800808};
809
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800810SDCARDFS_CONFIGFS_ATTR_WO(packages_, remove_userid);
811
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800812static struct configfs_attribute *packages_attrs[] = {
813 &packages_attr_packages_gid_list,
Daniel Rosenbergd8caaf92017-01-22 15:32:49 -0800814 &packages_attr_remove_userid,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800815 NULL,
816};
817
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800818/*
819 * Note that, since no extra work is required on ->drop_item(),
820 * no ->drop_item() is provided.
821 */
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800822static struct configfs_group_operations packages_group_ops = {
823 .make_item = packages_make_item,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800824};
825
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800826static struct config_item_type packages_type = {
827 .ct_group_ops = &packages_group_ops,
828 .ct_attrs = packages_attrs,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800829 .ct_owner = THIS_MODULE,
830};
831
Daniel Rosenbergad905252017-01-25 13:48:45 -0800832struct config_group *sd_default_groups[] = {
833 &extension_group,
834 NULL,
835};
836
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800837static struct configfs_subsystem sdcardfs_packages = {
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800838 .su_group = {
839 .cg_item = {
840 .ci_namebuf = "sdcardfs",
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800841 .ci_type = &packages_type,
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800842 },
843 },
844};
845
Daniel Rosenbergcfdb6652016-03-28 16:00:34 -0700846static int configfs_sdcardfs_init(void)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800847{
Daniel Rosenbergad905252017-01-25 13:48:45 -0800848 int ret, i;
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800849 struct configfs_subsystem *subsys = &sdcardfs_packages;
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800850
851 config_group_init(&subsys->su_group);
Daniel Rosenbergad905252017-01-25 13:48:45 -0800852 for (i = 0; sd_default_groups[i]; i++) {
853 config_group_init(sd_default_groups[i]);
854 configfs_add_default_group(sd_default_groups[i], &subsys->su_group);
855 }
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800856 mutex_init(&subsys->su_mutex);
857 ret = configfs_register_subsystem(subsys);
858 if (ret) {
859 printk(KERN_ERR "Error %d while registering subsystem %s\n",
860 ret,
861 subsys->su_group.cg_item.ci_namebuf);
862 }
863 return ret;
864}
865
Daniel Rosenbergcfdb6652016-03-28 16:00:34 -0700866static void configfs_sdcardfs_exit(void)
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800867{
Daniel Rosenbergf48ace12017-01-21 00:35:26 -0800868 configfs_unregister_subsystem(&sdcardfs_packages);
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800869}
870
Daniel Campello35c9e242015-07-20 16:23:50 -0700871int packagelist_init(void)
872{
873 hashtable_entry_cachep =
874 kmem_cache_create("packagelist_hashtable_entry",
875 sizeof(struct hashtable_entry), 0, 0, NULL);
876 if (!hashtable_entry_cachep) {
877 printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
878 return -ENOMEM;
879 }
880
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800881 configfs_sdcardfs_init();
Daniel Campello35c9e242015-07-20 16:23:50 -0700882 return 0;
883}
884
885void packagelist_exit(void)
886{
Daniel Rosenberg497ac902016-02-03 21:08:21 -0800887 configfs_sdcardfs_exit();
Daniel Rosenbergfbd34b62016-05-10 13:42:43 -0700888 packagelist_destroy();
Daniel Campello35c9e242015-07-20 16:23:50 -0700889 if (hashtable_entry_cachep)
890 kmem_cache_destroy(hashtable_entry_cachep);
891}