f11591da141df35c767d73ef9225575dbd9634b7
[firefly-linux-kernel-4.4.55.git] / fs / sdcardfs / packagelist.c
1 /*
2  * fs/sdcardfs/packagelist.c
3  *
4  * Copyright (c) 2013 Samsung Electronics Co. Ltd
5  *   Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun,
6  *               Sunghwan Yun, Sungjong Seo
7  *
8  * This program has been developed as a stackable file system based on
9  * the WrapFS which written by
10  *
11  * Copyright (c) 1998-2011 Erez Zadok
12  * Copyright (c) 2009     Shrikar Archak
13  * Copyright (c) 2003-2011 Stony Brook University
14  * Copyright (c) 2003-2011 The Research Foundation of SUNY
15  *
16  * This file is dual licensed.  It may be redistributed and/or modified
17  * under the terms of the Apache 2.0 License OR version 2 of the GNU
18  * General Public License.
19  */
20
21 #include "sdcardfs.h"
22 #include "strtok.h"
23 #include <linux/hashtable.h>
24 #include <linux/syscalls.h>
25 #include <linux/kthread.h>
26 #include <linux/inotify.h>
27 #include <linux/delay.h>
28
29 #define STRING_BUF_SIZE         (512)
30
31 struct hashtable_entry {
32         struct hlist_node hlist;
33         void *key;
34         unsigned int value;
35 };
36
37 struct packagelist_data {
38         DECLARE_HASHTABLE(package_to_appid,8);
39         DECLARE_HASHTABLE(appid_with_rw,7);
40         struct mutex hashtable_lock;
41         struct task_struct *thread_id;
42         gid_t write_gid;
43         char *strtok_last;
44         char read_buf[STRING_BUF_SIZE];
45         char event_buf[STRING_BUF_SIZE];
46         char app_name_buf[STRING_BUF_SIZE];
47         char gids_buf[STRING_BUF_SIZE];
48 };
49
50 static struct kmem_cache *hashtable_entry_cachep;
51
52 /* Path to system-provided mapping of package name to appIds */
53 static const char* const kpackageslist_file = "/data/system/packages.list";
54 /* Supplementary groups to execute with */
55 static const gid_t kgroups[1] = { AID_PACKAGE_INFO };
56
57 static unsigned int str_hash(const char *key) {
58         int i;
59         unsigned int h = strlen(key);
60         char *data = (char *)key;
61
62         for (i = 0; i < strlen(key); i++) {
63                 h = h * 31 + *data;
64                 data++;
65         }
66         return h;
67 }
68
69 static int contain_appid_key(struct packagelist_data *pkgl_dat, unsigned int appid) {
70         struct hashtable_entry *hash_cur;
71
72         hash_for_each_possible(pkgl_dat->appid_with_rw, hash_cur, hlist, appid)
73                 if ((void *)(uintptr_t)appid == hash_cur->key)
74                         return 1;
75
76         return 0;
77 }
78
79 /* Return if the calling UID holds sdcard_rw. */
80 int get_caller_has_rw_locked(void *pkgl_id, derive_t derive) {
81         struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id;
82         appid_t appid;
83         int ret;
84
85         /* No additional permissions enforcement */
86         if (derive == DERIVE_NONE) {
87                 return 1;
88         }
89
90         appid = multiuser_get_app_id(from_kuid(&init_user_ns, current_fsuid()));
91         mutex_lock(&pkgl_dat->hashtable_lock);
92         ret = contain_appid_key(pkgl_dat, appid);
93         mutex_unlock(&pkgl_dat->hashtable_lock);
94         return ret;
95 }
96
97 appid_t get_appid(void *pkgl_id, const char *app_name)
98 {
99         struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id;
100         struct hashtable_entry *hash_cur;
101         unsigned int hash = str_hash(app_name);
102         appid_t ret_id;
103
104         //printk(KERN_INFO "sdcardfs: %s: %s, %u\n", __func__, (char *)app_name, hash);
105         mutex_lock(&pkgl_dat->hashtable_lock);
106         hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
107                 //printk(KERN_INFO "sdcardfs: %s: %s\n", __func__, (char *)hash_cur->key);
108                 if (!strcasecmp(app_name, hash_cur->key)) {
109                         ret_id = (appid_t)hash_cur->value;
110                         mutex_unlock(&pkgl_dat->hashtable_lock);
111                         //printk(KERN_INFO "=> app_id: %d\n", (int)ret_id);
112                         return ret_id;
113                 }
114         }
115         mutex_unlock(&pkgl_dat->hashtable_lock);
116         //printk(KERN_INFO "=> app_id: %d\n", 0);
117         return 0;
118 }
119
120 /* Kernel has already enforced everything we returned through
121  * derive_permissions_locked(), so this is used to lock down access
122  * even further, such as enforcing that apps hold sdcard_rw. */
123 int check_caller_access_to_name(struct inode *parent_node, const char* name,
124                                         derive_t derive, int w_ok, int has_rw) {
125
126         /* Always block security-sensitive files at root */
127         if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
128                 if (!strcasecmp(name, "autorun.inf")
129                         || !strcasecmp(name, ".android_secure")
130                         || !strcasecmp(name, "android_secure")) {
131                         return 0;
132                 }
133         }
134
135         /* No additional permissions enforcement */
136         if (derive == DERIVE_NONE) {
137                 return 1;
138         }
139
140         /* Root always has access; access for any other UIDs should always
141          * be controlled through packages.list. */
142         if (from_kuid(&init_user_ns, current_fsuid()) == 0) {
143                 return 1;
144         }
145
146         /* If asking to write, verify that caller either owns the
147          * parent or holds sdcard_rw. */
148         if (w_ok) {
149                 if (parent_node &&
150                         (from_kuid(&init_user_ns, current_fsuid()) ==
151                          SDCARDFS_I(parent_node)->d_uid)) {
152                         return 1;
153                 }
154                 return has_rw;
155         }
156
157         /* No extra permissions to enforce */
158         return 1;
159 }
160
161 /* This function is used when file opening. The open flags must be
162  * checked before calling check_caller_access_to_name() */
163 int open_flags_to_access_mode(int open_flags) {
164         if((open_flags & O_ACCMODE) == O_RDONLY) {
165                 return 0; /* R_OK */
166         } else if ((open_flags & O_ACCMODE) == O_WRONLY) {
167                 return 1; /* W_OK */
168         } else {
169                 /* Probably O_RDRW, but treat as default to be safe */
170                 return 1; /* R_OK | W_OK */
171         }
172 }
173
174 static int insert_str_to_int(struct packagelist_data *pkgl_dat, char *key,
175                 unsigned int value)
176 {
177         struct hashtable_entry *hash_cur;
178         struct hashtable_entry *new_entry;
179         unsigned int hash = str_hash(key);
180
181         //printk(KERN_INFO "sdcardfs: %s: %s: %d, %u\n", __func__, (char *)key, value, hash);
182         hash_for_each_possible(pkgl_dat->package_to_appid, hash_cur, hlist, hash) {
183                 if (!strcasecmp(key, hash_cur->key)) {
184                         hash_cur->value = value;
185                         return 0;
186                 }
187         }
188         new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL);
189         if (!new_entry)
190                 return -ENOMEM;
191         new_entry->key = kstrdup(key, GFP_KERNEL);
192         new_entry->value = value;
193         hash_add(pkgl_dat->package_to_appid, &new_entry->hlist, hash);
194         return 0;
195 }
196
197 static void remove_str_to_int(struct hashtable_entry *h_entry) {
198         //printk(KERN_INFO "sdcardfs: %s: %s: %d\n", __func__, (char *)h_entry->key, h_entry->value);
199         kfree(h_entry->key);
200         kmem_cache_free(hashtable_entry_cachep, h_entry);
201 }
202
203 static int insert_int_to_null(struct packagelist_data *pkgl_dat, unsigned int key,
204                 unsigned int value)
205 {
206         struct hashtable_entry *hash_cur;
207         struct hashtable_entry *new_entry;
208
209         //printk(KERN_INFO "sdcardfs: %s: %d: %d\n", __func__, (int)key, value);
210         hash_for_each_possible(pkgl_dat->appid_with_rw, hash_cur, hlist, key) {
211                 if ((void *)(uintptr_t)key == hash_cur->key) {
212                         hash_cur->value = value;
213                         return 0;
214                 }
215         }
216         new_entry = kmem_cache_alloc(hashtable_entry_cachep, GFP_KERNEL);
217         if (!new_entry)
218                 return -ENOMEM;
219         new_entry->key = (void *)(uintptr_t)key;
220         new_entry->value = value;
221         hash_add(pkgl_dat->appid_with_rw, &new_entry->hlist, key);
222         return 0;
223 }
224
225 static void remove_int_to_null(struct hashtable_entry *h_entry) {
226         //printk(KERN_INFO "sdcardfs: %s: %d: %d\n", __func__, (int)h_entry->key, h_entry->value);
227         kmem_cache_free(hashtable_entry_cachep, h_entry);
228 }
229
230 static void remove_all_hashentrys(struct packagelist_data *pkgl_dat)
231 {
232         struct hashtable_entry *hash_cur;
233         struct hlist_node *h_t;
234         int i;
235
236         hash_for_each_safe(pkgl_dat->package_to_appid, i, h_t, hash_cur, hlist)
237                 remove_str_to_int(hash_cur);
238         hash_for_each_safe(pkgl_dat->appid_with_rw, i, h_t, hash_cur, hlist)
239                 remove_int_to_null(hash_cur);
240
241         hash_init(pkgl_dat->package_to_appid);
242         hash_init(pkgl_dat->appid_with_rw);
243 }
244
245 static int read_package_list(struct packagelist_data *pkgl_dat) {
246         int ret;
247         int fd;
248         int read_amount;
249
250         printk(KERN_INFO "sdcardfs: read_package_list\n");
251
252         mutex_lock(&pkgl_dat->hashtable_lock);
253
254         remove_all_hashentrys(pkgl_dat);
255
256         fd = sys_open(kpackageslist_file, O_RDONLY, 0);
257         if (fd < 0) {
258                 printk(KERN_ERR "sdcardfs: failed to open package list\n");
259                 mutex_unlock(&pkgl_dat->hashtable_lock);
260                 return fd;
261         }
262
263         while ((read_amount = sys_read(fd, pkgl_dat->read_buf,
264                                         sizeof(pkgl_dat->read_buf))) > 0) {
265                 unsigned int appid;
266                 char *token;
267                 int one_line_len = 0;
268                 int additional_read;
269                 unsigned long ret_gid;
270
271                 while (one_line_len < read_amount) {
272                         if (pkgl_dat->read_buf[one_line_len] == '\n') {
273                                 one_line_len++;
274                                 break;
275                         }
276                         one_line_len++;
277                 }
278                 additional_read = read_amount - one_line_len;
279                 if (additional_read > 0)
280                         sys_lseek(fd, -additional_read, SEEK_CUR);
281
282                 if (sscanf(pkgl_dat->read_buf, "%s %u %*d %*s %*s %s",
283                                 pkgl_dat->app_name_buf, &appid,
284                                 pkgl_dat->gids_buf) == 3) {
285                         ret = insert_str_to_int(pkgl_dat, pkgl_dat->app_name_buf, appid);
286                         if (ret) {
287                                 sys_close(fd);
288                                 mutex_unlock(&pkgl_dat->hashtable_lock);
289                                 return ret;
290                         }
291
292                         token = strtok_r(pkgl_dat->gids_buf, ",", &pkgl_dat->strtok_last);
293                         while (token != NULL) {
294                                 if (!kstrtoul(token, 10, &ret_gid) &&
295                                                 (ret_gid == pkgl_dat->write_gid)) {
296                                         ret = insert_int_to_null(pkgl_dat, appid, 1);
297                                         if (ret) {
298                                                 sys_close(fd);
299                                                 mutex_unlock(&pkgl_dat->hashtable_lock);
300                                                 return ret;
301                                         }
302                                         break;
303                                 }
304                                 token = strtok_r(NULL, ",", &pkgl_dat->strtok_last);
305                         }
306                 }
307         }
308
309         sys_close(fd);
310         mutex_unlock(&pkgl_dat->hashtable_lock);
311         return 0;
312 }
313
314 static int packagelist_reader(void *thread_data)
315 {
316         struct packagelist_data *pkgl_dat = (struct packagelist_data *)thread_data;
317         struct inotify_event *event;
318         bool active = false;
319         int event_pos;
320         int event_size;
321         int res = 0;
322         int nfd;
323
324         allow_signal(SIGINT);
325
326         nfd = sys_inotify_init();
327         if (nfd < 0) {
328                 printk(KERN_ERR "sdcardfs: inotify_init failed: %d\n", nfd);
329                 return nfd;
330         }
331
332         while (!kthread_should_stop()) {
333                 if (signal_pending(current)) {
334                         ssleep(1);
335                         continue;
336                 }
337
338                 if (!active) {
339                         res = sys_inotify_add_watch(nfd, kpackageslist_file, IN_DELETE_SELF);
340                         if (res < 0) {
341                                 if (res == -ENOENT || res == -EACCES) {
342                                 /* Framework may not have created yet, sleep and retry */
343                                         printk(KERN_ERR "sdcardfs: missing packages.list; retrying\n");
344                                         ssleep(2);
345                                         printk(KERN_ERR "sdcardfs: missing packages.list_end; retrying\n");
346                                         continue;
347                                 } else {
348                                         printk(KERN_ERR "sdcardfs: inotify_add_watch failed: %d\n", res);
349                                         goto interruptable_sleep;
350                                 }
351                         }
352                         /* Watch above will tell us about any future changes, so
353                          * read the current state. */
354                         res = read_package_list(pkgl_dat);
355                         if (res) {
356                                 printk(KERN_ERR "sdcardfs: read_package_list failed: %d\n", res);
357                                 goto interruptable_sleep;
358                         }
359                         active = true;
360                 }
361
362                 event_pos = 0;
363                 res = sys_read(nfd, pkgl_dat->event_buf, sizeof(pkgl_dat->event_buf));
364                 if (res < (int) sizeof(*event)) {
365                         if (res == -EINTR)
366                                 continue;
367                         printk(KERN_ERR "sdcardfs: failed to read inotify event: %d\n", res);
368                         goto interruptable_sleep;
369                 }
370
371                 while (res >= (int) sizeof(*event)) {
372                         event = (struct inotify_event *) (pkgl_dat->event_buf + event_pos);
373
374                         printk(KERN_INFO "sdcardfs: inotify event: %08x\n", event->mask);
375                         if ((event->mask & IN_IGNORED) == IN_IGNORED) {
376                                 /* Previously watched file was deleted, probably due to move
377                                  * that swapped in new data; re-arm the watch and read. */
378                                 active = false;
379                         }
380
381                         event_size = sizeof(*event) + event->len;
382                         res -= event_size;
383                         event_pos += event_size;
384                 }
385                 continue;
386
387 interruptable_sleep:
388                 set_current_state(TASK_INTERRUPTIBLE);
389                 schedule();
390         }
391         flush_signals(current);
392         sys_close(nfd);
393         return res;
394 }
395
396 void * packagelist_create(gid_t write_gid)
397 {
398         struct packagelist_data *pkgl_dat;
399         struct task_struct *packagelist_thread;
400
401         pkgl_dat = kmalloc(sizeof(*pkgl_dat), GFP_KERNEL | __GFP_ZERO);
402         if (!pkgl_dat) {
403                 printk(KERN_ERR "sdcardfs: creating kthread failed\n");
404                 return ERR_PTR(-ENOMEM);
405         }
406
407         mutex_init(&pkgl_dat->hashtable_lock);
408         hash_init(pkgl_dat->package_to_appid);
409         hash_init(pkgl_dat->appid_with_rw);
410         pkgl_dat->write_gid = write_gid;
411
412         packagelist_thread = kthread_run(packagelist_reader, (void *)pkgl_dat, "pkgld");
413         if (IS_ERR(packagelist_thread)) {
414                 printk(KERN_ERR "sdcardfs: creating kthread failed\n");
415                 kfree(pkgl_dat);
416                 return packagelist_thread;
417         }
418         pkgl_dat->thread_id = packagelist_thread;
419
420         printk(KERN_INFO "sdcardfs: created packagelist pkgld/%d\n",
421                                 (int)pkgl_dat->thread_id->pid);
422
423         return (void *)pkgl_dat;
424 }
425
426 void packagelist_destroy(void *pkgl_id)
427 {
428         struct packagelist_data *pkgl_dat = (struct packagelist_data *)pkgl_id;
429         pid_t pkgl_pid = pkgl_dat->thread_id->pid;
430
431         force_sig_info(SIGINT, SEND_SIG_PRIV, pkgl_dat->thread_id);
432         kthread_stop(pkgl_dat->thread_id);
433         remove_all_hashentrys(pkgl_dat);
434         printk(KERN_INFO "sdcardfs: destroyed packagelist pkgld/%d\n", (int)pkgl_pid);
435         kfree(pkgl_dat);
436 }
437
438 int packagelist_init(void)
439 {
440         hashtable_entry_cachep =
441                 kmem_cache_create("packagelist_hashtable_entry",
442                                         sizeof(struct hashtable_entry), 0, 0, NULL);
443         if (!hashtable_entry_cachep) {
444                 printk(KERN_ERR "sdcardfs: failed creating pkgl_hashtable entry slab cache\n");
445                 return -ENOMEM;
446         }
447
448         return 0;
449 }
450
451 void packagelist_exit(void)
452 {
453         if (hashtable_entry_cachep)
454                 kmem_cache_destroy(hashtable_entry_cachep);
455 }
456
457