blob: 00c33a471dcc57e117458f19ae28eb9b5b47ec1e [file] [log] [blame]
Daniel Campello35c9e242015-07-20 16:23:50 -07001/*
2 * fs/sdcardfs/derived_perm.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
23/* copy derived state from parent inode */
24static void inherit_derived_state(struct inode *parent, struct inode *child)
25{
26 struct sdcardfs_inode_info *pi = SDCARDFS_I(parent);
27 struct sdcardfs_inode_info *ci = SDCARDFS_I(child);
28
29 ci->perm = PERM_INHERIT;
30 ci->userid = pi->userid;
31 ci->d_uid = pi->d_uid;
32 ci->d_gid = pi->d_gid;
33 ci->d_mode = pi->d_mode;
34}
35
36/* helper function for derived state */
37void setup_derived_state(struct inode *inode, perm_t perm,
38 userid_t userid, uid_t uid, gid_t gid, mode_t mode)
39{
40 struct sdcardfs_inode_info *info = SDCARDFS_I(inode);
41
42 info->perm = perm;
43 info->userid = userid;
44 info->d_uid = uid;
45 info->d_gid = gid;
46 info->d_mode = mode;
47}
48
49void get_derived_permission(struct dentry *parent, struct dentry *dentry)
50{
51 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
52 struct sdcardfs_inode_info *info = SDCARDFS_I(dentry->d_inode);
53 struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
54 appid_t appid;
55
56 /* By default, each inode inherits from its parent.
57 * the properties are maintained on its private fields
58 * because the inode attributes will be modified with that of
59 * its lower inode.
60 * The derived state will be updated on the last
61 * stage of each system call by fix_derived_permission(inode).
62 */
63
64 inherit_derived_state(parent->d_inode, dentry->d_inode);
65
66 //printk(KERN_INFO "sdcardfs: derived: %s, %s, %d\n", parent->d_name.name,
67 // dentry->d_name.name, parent_info->perm);
68
69 if (sbi->options.derive == DERIVE_NONE) {
70 return;
71 }
72
73 /* Derive custom permissions based on parent and current node */
74 switch (parent_info->perm) {
75 case PERM_INHERIT:
76 /* Already inherited above */
77 break;
78 case PERM_LEGACY_PRE_ROOT:
79 /* Legacy internal layout places users at top level */
80 info->perm = PERM_ROOT;
81 info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
82 break;
83 case PERM_ROOT:
84 /* Assume masked off by default. */
85 info->d_mode = 00770;
86 if (!strcasecmp(dentry->d_name.name, "Android")) {
87 /* App-specific directories inside; let anyone traverse */
88 info->perm = PERM_ANDROID;
89 info->d_mode = 00771;
90 } else if (sbi->options.split_perms) {
91 if (!strcasecmp(dentry->d_name.name, "DCIM")
92 || !strcasecmp(dentry->d_name.name, "Pictures")) {
93 info->d_gid = AID_SDCARD_PICS;
94 } else if (!strcasecmp(dentry->d_name.name, "Alarms")
95 || !strcasecmp(dentry->d_name.name, "Movies")
96 || !strcasecmp(dentry->d_name.name, "Music")
97 || !strcasecmp(dentry->d_name.name, "Notifications")
98 || !strcasecmp(dentry->d_name.name, "Podcasts")
99 || !strcasecmp(dentry->d_name.name, "Ringtones")) {
100 info->d_gid = AID_SDCARD_AV;
101 }
102 }
103 break;
104 case PERM_ANDROID:
105 if (!strcasecmp(dentry->d_name.name, "data")) {
106 /* App-specific directories inside; let anyone traverse */
107 info->perm = PERM_ANDROID_DATA;
108 info->d_mode = 00771;
109 } else if (!strcasecmp(dentry->d_name.name, "obb")) {
110 /* App-specific directories inside; let anyone traverse */
111 info->perm = PERM_ANDROID_OBB;
112 info->d_mode = 00771;
113 // FIXME : this feature will be implemented later.
114 /* Single OBB directory is always shared */
115 } else if (!strcasecmp(dentry->d_name.name, "user")) {
116 /* User directories must only be accessible to system, protected
117 * by sdcard_all. Zygote will bind mount the appropriate user-
118 * specific path. */
119 info->perm = PERM_ANDROID_USER;
120 info->d_gid = AID_SDCARD_ALL;
121 info->d_mode = 00770;
122 }
123 break;
124 /* same policy will be applied on PERM_ANDROID_DATA
125 * and PERM_ANDROID_OBB */
126 case PERM_ANDROID_DATA:
127 case PERM_ANDROID_OBB:
128 appid = get_appid(sbi->pkgl_id, dentry->d_name.name);
129 if (appid != 0) {
130 info->d_uid = multiuser_get_uid(parent_info->userid, appid);
131 }
132 info->d_mode = 00770;
133 break;
134 case PERM_ANDROID_USER:
135 /* Root of a secondary user */
136 info->perm = PERM_ROOT;
137 info->userid = simple_strtoul(dentry->d_name.name, NULL, 10);
138 info->d_gid = AID_SDCARD_R;
139 info->d_mode = 00771;
140 break;
141 }
142}
143
144/* main function for updating derived permission */
145inline void update_derived_permission(struct dentry *dentry)
146{
147 struct dentry *parent;
148
149 if(!dentry || !dentry->d_inode) {
150 printk(KERN_ERR "sdcardfs: %s: invalid dentry\n", __func__);
151 return;
152 }
153 /* FIXME:
154 * 1. need to check whether the dentry is updated or not
155 * 2. remove the root dentry update
156 */
157 if(IS_ROOT(dentry)) {
158 //setup_default_pre_root_state(dentry->d_inode);
159 } else {
160 parent = dget_parent(dentry);
161 if(parent) {
162 get_derived_permission(parent, dentry);
163 dput(parent);
164 }
165 }
166 fix_derived_permission(dentry->d_inode);
167}
168
169int need_graft_path(struct dentry *dentry)
170{
171 int ret = 0;
172 struct dentry *parent = dget_parent(dentry);
173 struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
174 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
175
176 if(parent_info->perm == PERM_ANDROID &&
177 !strcasecmp(dentry->d_name.name, "obb")) {
178
179 /* /Android/obb is the base obbpath of DERIVED_UNIFIED */
180 if(!(sbi->options.derive == DERIVE_UNIFIED
181 && parent_info->userid == 0)) {
182 ret = 1;
183 }
184 }
185 dput(parent);
186 return ret;
187}
188
189int is_obbpath_invalid(struct dentry *dent)
190{
191 int ret = 0;
192 struct sdcardfs_dentry_info *di = SDCARDFS_D(dent);
193 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dent->d_sb);
194 char *path_buf, *obbpath_s;
195
196 /* check the base obbpath has been changed.
197 * this routine can check an uninitialized obb dentry as well.
198 * regarding the uninitialized obb, refer to the sdcardfs_mkdir() */
199 spin_lock(&di->lock);
200 if(di->orig_path.dentry) {
201 if(!di->lower_path.dentry) {
202 ret = 1;
203 } else {
204 path_get(&di->lower_path);
205 //lower_parent = lock_parent(lower_path->dentry);
206
207 path_buf = kmalloc(PATH_MAX, GFP_ATOMIC);
208 if(!path_buf) {
209 ret = 1;
210 printk(KERN_ERR "sdcardfs: "
211 "fail to allocate path_buf in %s.\n", __func__);
212 } else {
213 obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX);
214 if (d_unhashed(di->lower_path.dentry) ||
215 strcasecmp(sbi->obbpath_s, obbpath_s)) {
216 ret = 1;
217 }
218 kfree(path_buf);
219 }
220
221 //unlock_dir(lower_parent);
222 path_put(&di->lower_path);
223 }
224 }
225 spin_unlock(&di->lock);
226 return ret;
227}
228
229int is_base_obbpath(struct dentry *dentry)
230{
231 int ret = 0;
232 struct dentry *parent = dget_parent(dentry);
233 struct sdcardfs_inode_info *parent_info= SDCARDFS_I(parent->d_inode);
234 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
235
236 spin_lock(&SDCARDFS_D(dentry)->lock);
237 /* DERIVED_LEGACY */
238 if(parent_info->perm == PERM_LEGACY_PRE_ROOT &&
239 !strcasecmp(dentry->d_name.name, "obb")) {
240 ret = 1;
241 }
242 /* DERIVED_UNIFIED :/Android/obb is the base obbpath */
243 else if (parent_info->perm == PERM_ANDROID &&
244 !strcasecmp(dentry->d_name.name, "obb")) {
245 if((sbi->options.derive == DERIVE_UNIFIED
246 && parent_info->userid == 0)) {
247 ret = 1;
248 }
249 }
250 spin_unlock(&SDCARDFS_D(dentry)->lock);
251 dput(parent);
252 return ret;
253}
254
255/* The lower_path will be stored to the dentry's orig_path
256 * and the base obbpath will be copyed to the lower_path variable.
257 * if an error returned, there's no change in the lower_path
258 * returns: -ERRNO if error (0: no error) */
259int setup_obb_dentry(struct dentry *dentry, struct path *lower_path)
260{
261 int err = 0;
262 struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
263 struct path obbpath;
264
265 /* A local obb dentry must have its own orig_path to support rmdir
266 * and mkdir of itself. Usually, we expect that the sbi->obbpath
267 * is avaiable on this stage. */
268 sdcardfs_set_orig_path(dentry, lower_path);
269
270 err = kern_path(sbi->obbpath_s,
271 LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &obbpath);
272
273 if(!err) {
274 /* the obbpath base has been found */
275 printk(KERN_INFO "sdcardfs: "
276 "the sbi->obbpath is found\n");
277 pathcpy(lower_path, &obbpath);
278 } else {
279 /* if the sbi->obbpath is not available, we can optionally
280 * setup the lower_path with its orig_path.
281 * but, the current implementation just returns an error
282 * because the sdcard daemon also regards this case as
283 * a lookup fail. */
284 printk(KERN_INFO "sdcardfs: "
285 "the sbi->obbpath is not available\n");
286 }
287 return err;
288}
289
290