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