| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * fs/sdcardfs/sdcardfs.h | 
|  | 3 | * | 
|  | 4 | * The sdcardfs v2.0 | 
|  | 5 | *   This file system replaces the sdcard daemon on Android | 
|  | 6 | *   On version 2.0, some of the daemon functions have been ported | 
|  | 7 | *   to support the multi-user concepts of Android 4.4 | 
|  | 8 | * | 
|  | 9 | * Copyright (c) 2013 Samsung Electronics Co. Ltd | 
|  | 10 | *   Authors: Daeho Jeong, Woojoong Lee, Seunghwan Hyun, | 
|  | 11 | *               Sunghwan Yun, Sungjong Seo | 
|  | 12 | * | 
|  | 13 | * This program has been developed as a stackable file system based on | 
|  | 14 | * the WrapFS which written by | 
|  | 15 | * | 
|  | 16 | * Copyright (c) 1998-2011 Erez Zadok | 
|  | 17 | * Copyright (c) 2009     Shrikar Archak | 
|  | 18 | * Copyright (c) 2003-2011 Stony Brook University | 
|  | 19 | * Copyright (c) 2003-2011 The Research Foundation of SUNY | 
|  | 20 | * | 
|  | 21 | * This file is dual licensed.  It may be redistributed and/or modified | 
|  | 22 | * under the terms of the Apache 2.0 License OR version 2 of the GNU | 
|  | 23 | * General Public License. | 
|  | 24 | */ | 
|  | 25 |  | 
|  | 26 | #ifndef _SDCARDFS_H_ | 
|  | 27 | #define _SDCARDFS_H_ | 
|  | 28 |  | 
|  | 29 | #include <linux/dcache.h> | 
|  | 30 | #include <linux/file.h> | 
|  | 31 | #include <linux/fs.h> | 
|  | 32 | #include <linux/mm.h> | 
|  | 33 | #include <linux/mount.h> | 
|  | 34 | #include <linux/namei.h> | 
|  | 35 | #include <linux/seq_file.h> | 
|  | 36 | #include <linux/statfs.h> | 
|  | 37 | #include <linux/fs_stack.h> | 
|  | 38 | #include <linux/magic.h> | 
|  | 39 | #include <linux/uaccess.h> | 
|  | 40 | #include <linux/slab.h> | 
|  | 41 | #include <linux/sched.h> | 
|  | 42 | #include <linux/types.h> | 
|  | 43 | #include <linux/security.h> | 
|  | 44 | #include <linux/string.h> | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 45 | #include <linux/list.h> | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 46 | #include "multiuser.h" | 
|  | 47 |  | 
|  | 48 | /* the file system name */ | 
|  | 49 | #define SDCARDFS_NAME "sdcardfs" | 
|  | 50 |  | 
|  | 51 | /* sdcardfs root inode number */ | 
|  | 52 | #define SDCARDFS_ROOT_INO     1 | 
|  | 53 |  | 
|  | 54 | /* useful for tracking code reachability */ | 
|  | 55 | #define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__) | 
|  | 56 |  | 
|  | 57 | #define SDCARDFS_DIRENT_SIZE 256 | 
|  | 58 |  | 
|  | 59 | /* temporary static uid settings for development */ | 
|  | 60 | #define AID_ROOT             0	/* uid for accessing /mnt/sdcard & extSdcard */ | 
|  | 61 | #define AID_MEDIA_RW      1023	/* internal media storage write access */ | 
|  | 62 |  | 
|  | 63 | #define AID_SDCARD_RW     1015	/* external storage write access */ | 
|  | 64 | #define AID_SDCARD_R      1028	/* external storage read access */ | 
|  | 65 | #define AID_SDCARD_PICS   1033	/* external storage photos access */ | 
|  | 66 | #define AID_SDCARD_AV     1034	/* external storage audio/video access */ | 
|  | 67 | #define AID_SDCARD_ALL    1035	/* access all users external storage */ | 
|  | 68 |  | 
|  | 69 | #define AID_PACKAGE_INFO  1027 | 
|  | 70 |  | 
|  | 71 | #define fix_derived_permission(x)	\ | 
|  | 72 | do {						\ | 
|  | 73 | (x)->i_uid = SDCARDFS_I(x)->d_uid;	\ | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 74 | (x)->i_gid = get_gid(SDCARDFS_I(x));	\ | 
|  | 75 | (x)->i_mode = ((x)->i_mode & S_IFMT) | get_mode(SDCARDFS_I(x));\ | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 76 | } while (0) | 
|  | 77 |  | 
|  | 78 | /* OVERRIDE_CRED() and REVERT_CRED() | 
|  | 79 | * 	OVERRID_CRED() | 
|  | 80 | * 		backup original task->cred | 
|  | 81 | * 		and modifies task->cred->fsuid/fsgid to specified value. | 
|  | 82 | *	REVERT_CRED() | 
|  | 83 | * 		restore original task->cred->fsuid/fsgid. | 
|  | 84 | * These two macro should be used in pair, and OVERRIDE_CRED() should be | 
|  | 85 | * placed at the beginning of a function, right after variable declaration. | 
|  | 86 | */ | 
|  | 87 | #define OVERRIDE_CRED(sdcardfs_sbi, saved_cred)		\ | 
|  | 88 | saved_cred = override_fsids(sdcardfs_sbi);	\ | 
|  | 89 | if (!saved_cred) { return -ENOMEM; } | 
|  | 90 |  | 
|  | 91 | #define OVERRIDE_CRED_PTR(sdcardfs_sbi, saved_cred)	\ | 
|  | 92 | saved_cred = override_fsids(sdcardfs_sbi);	\ | 
|  | 93 | if (!saved_cred) { return ERR_PTR(-ENOMEM); } | 
|  | 94 |  | 
|  | 95 | #define REVERT_CRED(saved_cred)	revert_fsids(saved_cred) | 
|  | 96 |  | 
|  | 97 | #define DEBUG_CRED()		\ | 
|  | 98 | printk("KAKJAGI: %s:%d fsuid %d fsgid %d\n", 	\ | 
|  | 99 | __FUNCTION__, __LINE__, 		\ | 
|  | 100 | (int)current->cred->fsuid, 		\ | 
|  | 101 | (int)current->cred->fsgid); | 
|  | 102 |  | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 103 | /* Android 5.0 support */ | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 104 |  | 
|  | 105 | /* Permission mode for a specific node. Controls how file permissions | 
|  | 106 | * are derived for children nodes. */ | 
|  | 107 | typedef enum { | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 108 | /* Nothing special; this node should just inherit from its parent. */ | 
|  | 109 | PERM_INHERIT, | 
|  | 110 | /* This node is one level above a normal root; used for legacy layouts | 
|  | 111 | * which use the first level to represent user_id. */ | 
|  | 112 | PERM_PRE_ROOT, | 
|  | 113 | /* This node is "/" */ | 
|  | 114 | PERM_ROOT, | 
|  | 115 | /* This node is "/Android" */ | 
|  | 116 | PERM_ANDROID, | 
|  | 117 | /* This node is "/Android/data" */ | 
|  | 118 | PERM_ANDROID_DATA, | 
|  | 119 | /* This node is "/Android/obb" */ | 
|  | 120 | PERM_ANDROID_OBB, | 
|  | 121 | /* This node is "/Android/media" */ | 
|  | 122 | PERM_ANDROID_MEDIA, | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 123 | } perm_t; | 
|  | 124 |  | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 125 | struct sdcardfs_sb_info; | 
|  | 126 | struct sdcardfs_mount_options; | 
|  | 127 |  | 
|  | 128 | /* Do not directly use this function. Use OVERRIDE_CRED() instead. */ | 
|  | 129 | const struct cred * override_fsids(struct sdcardfs_sb_info* sbi); | 
|  | 130 | /* Do not directly use this function, use REVERT_CRED() instead. */ | 
|  | 131 | void revert_fsids(const struct cred * old_cred); | 
|  | 132 |  | 
|  | 133 | /* operations vectors defined in specific files */ | 
|  | 134 | extern const struct file_operations sdcardfs_main_fops; | 
|  | 135 | extern const struct file_operations sdcardfs_dir_fops; | 
|  | 136 | extern const struct inode_operations sdcardfs_main_iops; | 
|  | 137 | extern const struct inode_operations sdcardfs_dir_iops; | 
|  | 138 | extern const struct inode_operations sdcardfs_symlink_iops; | 
|  | 139 | extern const struct super_operations sdcardfs_sops; | 
|  | 140 | extern const struct dentry_operations sdcardfs_ci_dops; | 
|  | 141 | extern const struct address_space_operations sdcardfs_aops, sdcardfs_dummy_aops; | 
|  | 142 | extern const struct vm_operations_struct sdcardfs_vm_ops; | 
|  | 143 |  | 
|  | 144 | extern int sdcardfs_init_inode_cache(void); | 
|  | 145 | extern void sdcardfs_destroy_inode_cache(void); | 
|  | 146 | extern int sdcardfs_init_dentry_cache(void); | 
|  | 147 | extern void sdcardfs_destroy_dentry_cache(void); | 
|  | 148 | extern int new_dentry_private_data(struct dentry *dentry); | 
|  | 149 | extern void free_dentry_private_data(struct dentry *dentry); | 
|  | 150 | extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry, | 
|  | 151 | struct nameidata *nd); | 
| fluxi | 41b26d8 | 2016-07-29 18:52:13 +0200 | [diff] [blame] | 152 | extern struct inode *sdcardfs_iget(struct super_block *sb, | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 153 | struct inode *lower_inode, userid_t id); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 154 | extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb, | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 155 | struct path *lower_path, userid_t id); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 156 |  | 
|  | 157 | /* file private data */ | 
|  | 158 | struct sdcardfs_file_info { | 
|  | 159 | struct file *lower_file; | 
|  | 160 | const struct vm_operations_struct *lower_vm_ops; | 
|  | 161 | }; | 
|  | 162 |  | 
|  | 163 | /* sdcardfs inode data in memory */ | 
|  | 164 | struct sdcardfs_inode_info { | 
|  | 165 | struct inode *lower_inode; | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 166 | /* state derived based on current position in hierachy */ | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 167 | perm_t perm; | 
|  | 168 | userid_t userid; | 
|  | 169 | uid_t d_uid; | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 170 | bool under_android; | 
| Daniel Rosenberg | b07ed40 | 2016-05-18 16:57:10 -0700 | [diff] [blame^] | 171 | /* top folder for ownership */ | 
|  | 172 | struct inode *top; | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 173 |  | 
|  | 174 | struct inode vfs_inode; | 
|  | 175 | }; | 
|  | 176 |  | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 177 |  | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 178 | /* sdcardfs dentry data in memory */ | 
|  | 179 | struct sdcardfs_dentry_info { | 
|  | 180 | spinlock_t lock;	/* protects lower_path */ | 
|  | 181 | struct path lower_path; | 
|  | 182 | struct path orig_path; | 
|  | 183 | }; | 
|  | 184 |  | 
|  | 185 | struct sdcardfs_mount_options { | 
|  | 186 | uid_t fs_low_uid; | 
|  | 187 | gid_t fs_low_gid; | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 188 | userid_t fs_user_id; | 
|  | 189 | gid_t gid; | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 190 | mode_t mask; | 
|  | 191 | bool multiuser; | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 192 | unsigned int reserved_mb; | 
|  | 193 | }; | 
|  | 194 |  | 
|  | 195 | /* sdcardfs super-block data in memory */ | 
|  | 196 | struct sdcardfs_sb_info { | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 197 | struct super_block *sb; | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 198 | struct super_block *lower_sb; | 
|  | 199 | /* derived perm policy : some of options have been added | 
|  | 200 | * to sdcardfs_mount_options (Android 4.4 support) */ | 
|  | 201 | struct sdcardfs_mount_options options; | 
|  | 202 | spinlock_t lock;	/* protects obbpath */ | 
|  | 203 | char *obbpath_s; | 
|  | 204 | struct path obbpath; | 
|  | 205 | void *pkgl_id; | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 206 | struct list_head list; | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 207 | }; | 
|  | 208 |  | 
|  | 209 | /* | 
|  | 210 | * inode to private data | 
|  | 211 | * | 
|  | 212 | * Since we use containers and the struct inode is _inside_ the | 
|  | 213 | * sdcardfs_inode_info structure, SDCARDFS_I will always (given a non-NULL | 
|  | 214 | * inode pointer), return a valid non-NULL pointer. | 
|  | 215 | */ | 
|  | 216 | static inline struct sdcardfs_inode_info *SDCARDFS_I(const struct inode *inode) | 
|  | 217 | { | 
|  | 218 | return container_of(inode, struct sdcardfs_inode_info, vfs_inode); | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | /* dentry to private data */ | 
|  | 222 | #define SDCARDFS_D(dent) ((struct sdcardfs_dentry_info *)(dent)->d_fsdata) | 
|  | 223 |  | 
|  | 224 | /* superblock to private data */ | 
|  | 225 | #define SDCARDFS_SB(super) ((struct sdcardfs_sb_info *)(super)->s_fs_info) | 
|  | 226 |  | 
|  | 227 | /* file to private Data */ | 
|  | 228 | #define SDCARDFS_F(file) ((struct sdcardfs_file_info *)((file)->private_data)) | 
|  | 229 |  | 
|  | 230 | /* file to lower file */ | 
|  | 231 | static inline struct file *sdcardfs_lower_file(const struct file *f) | 
|  | 232 | { | 
|  | 233 | return SDCARDFS_F(f)->lower_file; | 
|  | 234 | } | 
|  | 235 |  | 
|  | 236 | static inline void sdcardfs_set_lower_file(struct file *f, struct file *val) | 
|  | 237 | { | 
|  | 238 | SDCARDFS_F(f)->lower_file = val; | 
|  | 239 | } | 
|  | 240 |  | 
|  | 241 | /* inode to lower inode. */ | 
|  | 242 | static inline struct inode *sdcardfs_lower_inode(const struct inode *i) | 
|  | 243 | { | 
|  | 244 | return SDCARDFS_I(i)->lower_inode; | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | static inline void sdcardfs_set_lower_inode(struct inode *i, struct inode *val) | 
|  | 248 | { | 
|  | 249 | SDCARDFS_I(i)->lower_inode = val; | 
|  | 250 | } | 
|  | 251 |  | 
|  | 252 | /* superblock to lower superblock */ | 
|  | 253 | static inline struct super_block *sdcardfs_lower_super( | 
|  | 254 | const struct super_block *sb) | 
|  | 255 | { | 
|  | 256 | return SDCARDFS_SB(sb)->lower_sb; | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | static inline void sdcardfs_set_lower_super(struct super_block *sb, | 
|  | 260 | struct super_block *val) | 
|  | 261 | { | 
|  | 262 | SDCARDFS_SB(sb)->lower_sb = val; | 
|  | 263 | } | 
|  | 264 |  | 
|  | 265 | /* path based (dentry/mnt) macros */ | 
|  | 266 | static inline void pathcpy(struct path *dst, const struct path *src) | 
|  | 267 | { | 
|  | 268 | dst->dentry = src->dentry; | 
|  | 269 | dst->mnt = src->mnt; | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | /* sdcardfs_get_pname functions calls path_get() | 
|  | 273 | * therefore, the caller must call "proper" path_put functions | 
|  | 274 | */ | 
|  | 275 | #define SDCARDFS_DENT_FUNC(pname) \ | 
|  | 276 | static inline void sdcardfs_get_##pname(const struct dentry *dent, \ | 
|  | 277 | struct path *pname) \ | 
|  | 278 | { \ | 
|  | 279 | spin_lock(&SDCARDFS_D(dent)->lock); \ | 
|  | 280 | pathcpy(pname, &SDCARDFS_D(dent)->pname); \ | 
|  | 281 | path_get(pname); \ | 
|  | 282 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | 
|  | 283 | return; \ | 
|  | 284 | } \ | 
|  | 285 | static inline void sdcardfs_put_##pname(const struct dentry *dent, \ | 
|  | 286 | struct path *pname) \ | 
|  | 287 | { \ | 
|  | 288 | path_put(pname); \ | 
|  | 289 | return; \ | 
|  | 290 | } \ | 
|  | 291 | static inline void sdcardfs_set_##pname(const struct dentry *dent, \ | 
|  | 292 | struct path *pname) \ | 
|  | 293 | { \ | 
|  | 294 | spin_lock(&SDCARDFS_D(dent)->lock); \ | 
|  | 295 | pathcpy(&SDCARDFS_D(dent)->pname, pname); \ | 
|  | 296 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | 
|  | 297 | return; \ | 
|  | 298 | } \ | 
|  | 299 | static inline void sdcardfs_reset_##pname(const struct dentry *dent) \ | 
|  | 300 | { \ | 
|  | 301 | spin_lock(&SDCARDFS_D(dent)->lock); \ | 
|  | 302 | SDCARDFS_D(dent)->pname.dentry = NULL; \ | 
|  | 303 | SDCARDFS_D(dent)->pname.mnt = NULL; \ | 
|  | 304 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | 
|  | 305 | return; \ | 
|  | 306 | } \ | 
|  | 307 | static inline void sdcardfs_put_reset_##pname(const struct dentry *dent) \ | 
|  | 308 | { \ | 
|  | 309 | struct path pname; \ | 
|  | 310 | spin_lock(&SDCARDFS_D(dent)->lock); \ | 
|  | 311 | if(SDCARDFS_D(dent)->pname.dentry) { \ | 
|  | 312 | pathcpy(&pname, &SDCARDFS_D(dent)->pname); \ | 
|  | 313 | SDCARDFS_D(dent)->pname.dentry = NULL; \ | 
|  | 314 | SDCARDFS_D(dent)->pname.mnt = NULL; \ | 
|  | 315 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | 
|  | 316 | path_put(&pname); \ | 
|  | 317 | } else \ | 
|  | 318 | spin_unlock(&SDCARDFS_D(dent)->lock); \ | 
|  | 319 | return; \ | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | SDCARDFS_DENT_FUNC(lower_path) | 
|  | 323 | SDCARDFS_DENT_FUNC(orig_path) | 
|  | 324 |  | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 325 | static inline int get_gid(struct sdcardfs_inode_info *info) { | 
|  | 326 | struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb); | 
|  | 327 | if (sb_info->options.gid == AID_SDCARD_RW) { | 
|  | 328 | /* As an optimization, certain trusted system components only run | 
|  | 329 | * as owner but operate across all users. Since we're now handing | 
|  | 330 | * out the sdcard_rw GID only to trusted apps, we're okay relaxing | 
|  | 331 | * the user boundary enforcement for the default view. The UIDs | 
|  | 332 | * assigned to app directories are still multiuser aware. */ | 
|  | 333 | return AID_SDCARD_RW; | 
|  | 334 | } else { | 
|  | 335 | return multiuser_get_uid(info->userid, sb_info->options.gid); | 
|  | 336 | } | 
|  | 337 | } | 
|  | 338 | static inline int get_mode(struct sdcardfs_inode_info *info) { | 
|  | 339 | int owner_mode; | 
|  | 340 | int filtered_mode; | 
|  | 341 | struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb); | 
|  | 342 | int visible_mode = 0775 & ~sb_info->options.mask; | 
|  | 343 |  | 
|  | 344 | if (info->perm == PERM_PRE_ROOT) { | 
|  | 345 | /* Top of multi-user view should always be visible to ensure | 
|  | 346 | * secondary users can traverse inside. */ | 
|  | 347 | visible_mode = 0711; | 
|  | 348 | } else if (info->under_android) { | 
|  | 349 | /* Block "other" access to Android directories, since only apps | 
|  | 350 | * belonging to a specific user should be in there; we still | 
|  | 351 | * leave +x open for the default view. */ | 
|  | 352 | if (sb_info->options.gid == AID_SDCARD_RW) { | 
|  | 353 | visible_mode = visible_mode & ~0006; | 
|  | 354 | } else { | 
|  | 355 | visible_mode = visible_mode & ~0007; | 
|  | 356 | } | 
|  | 357 | } | 
|  | 358 | owner_mode = info->lower_inode->i_mode & 0700; | 
|  | 359 | filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6)); | 
|  | 360 | return filtered_mode; | 
|  | 361 | } | 
|  | 362 |  | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 363 | static inline int has_graft_path(const struct dentry *dent) | 
|  | 364 | { | 
|  | 365 | int ret = 0; | 
|  | 366 |  | 
|  | 367 | spin_lock(&SDCARDFS_D(dent)->lock); | 
|  | 368 | if (SDCARDFS_D(dent)->orig_path.dentry != NULL) | 
|  | 369 | ret = 1; | 
|  | 370 | spin_unlock(&SDCARDFS_D(dent)->lock); | 
|  | 371 |  | 
|  | 372 | return ret; | 
|  | 373 | } | 
|  | 374 |  | 
|  | 375 | static inline void sdcardfs_get_real_lower(const struct dentry *dent, | 
|  | 376 | struct path *real_lower) | 
|  | 377 | { | 
|  | 378 | /* in case of a local obb dentry | 
|  | 379 | * the orig_path should be returned | 
|  | 380 | */ | 
|  | 381 | if(has_graft_path(dent)) | 
|  | 382 | sdcardfs_get_orig_path(dent, real_lower); | 
|  | 383 | else | 
|  | 384 | sdcardfs_get_lower_path(dent, real_lower); | 
|  | 385 | } | 
|  | 386 |  | 
|  | 387 | static inline void sdcardfs_put_real_lower(const struct dentry *dent, | 
|  | 388 | struct path *real_lower) | 
|  | 389 | { | 
|  | 390 | if(has_graft_path(dent)) | 
|  | 391 | sdcardfs_put_orig_path(dent, real_lower); | 
|  | 392 | else | 
|  | 393 | sdcardfs_put_lower_path(dent, real_lower); | 
|  | 394 | } | 
|  | 395 |  | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 396 | extern struct mutex sdcardfs_super_list_lock; | 
|  | 397 | extern struct list_head sdcardfs_super_list; | 
|  | 398 |  | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 399 | /* for packagelist.c */ | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 400 | extern appid_t get_appid(void *pkgl_id, const char *app_name); | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 401 | extern int check_caller_access_to_name(struct inode *parent_node, const char* name); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 402 | extern int open_flags_to_access_mode(int open_flags); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 403 | extern int packagelist_init(void); | 
|  | 404 | extern void packagelist_exit(void); | 
|  | 405 |  | 
|  | 406 | /* for derived_perm.c */ | 
| Daniel Rosenberg | b07ed40 | 2016-05-18 16:57:10 -0700 | [diff] [blame^] | 407 | extern void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid, | 
|  | 408 | uid_t uid, bool under_android, struct inode *top); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 409 | extern void get_derived_permission(struct dentry *parent, struct dentry *dentry); | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 410 | extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry); | 
| Daniel Rosenberg | b07ed40 | 2016-05-18 16:57:10 -0700 | [diff] [blame^] | 411 | extern void fixup_top_recursive(struct dentry *parent); | 
|  | 412 | extern void fixup_perms_recursive(struct dentry *dentry, const char *name, size_t len); | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 413 |  | 
|  | 414 | extern void update_derived_permission_lock(struct dentry *dentry); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 415 | extern int need_graft_path(struct dentry *dentry); | 
|  | 416 | extern int is_base_obbpath(struct dentry *dentry); | 
|  | 417 | extern int is_obbpath_invalid(struct dentry *dentry); | 
|  | 418 | extern int setup_obb_dentry(struct dentry *dentry, struct path *lower_path); | 
|  | 419 |  | 
|  | 420 | /* locking helpers */ | 
|  | 421 | static inline struct dentry *lock_parent(struct dentry *dentry) | 
|  | 422 | { | 
|  | 423 | struct dentry *dir = dget_parent(dentry); | 
|  | 424 | mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); | 
|  | 425 | return dir; | 
|  | 426 | } | 
|  | 427 |  | 
|  | 428 | static inline void unlock_dir(struct dentry *dir) | 
|  | 429 | { | 
|  | 430 | mutex_unlock(&dir->d_inode->i_mutex); | 
|  | 431 | dput(dir); | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | static inline int prepare_dir(const char *path_s, uid_t uid, gid_t gid, mode_t mode) | 
|  | 435 | { | 
|  | 436 | int err; | 
|  | 437 | struct dentry *dent; | 
|  | 438 | struct iattr attrs; | 
| fluxi | 41b26d8 | 2016-07-29 18:52:13 +0200 | [diff] [blame] | 439 | struct path parent; | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 440 |  | 
| fluxi | 41b26d8 | 2016-07-29 18:52:13 +0200 | [diff] [blame] | 441 | dent = kern_path_locked(path_s, &parent); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 442 | if (IS_ERR(dent)) { | 
|  | 443 | err = PTR_ERR(dent); | 
|  | 444 | if (err == -EEXIST) | 
|  | 445 | err = 0; | 
|  | 446 | goto out_unlock; | 
|  | 447 | } | 
|  | 448 |  | 
| fluxi | 41b26d8 | 2016-07-29 18:52:13 +0200 | [diff] [blame] | 449 | err = vfs_mkdir(parent.dentry->d_inode, dent, mode); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 450 | if (err) { | 
|  | 451 | if (err == -EEXIST) | 
|  | 452 | err = 0; | 
|  | 453 | goto out_dput; | 
|  | 454 | } | 
|  | 455 |  | 
|  | 456 | attrs.ia_uid = uid; | 
|  | 457 | attrs.ia_gid = gid; | 
|  | 458 | attrs.ia_valid = ATTR_UID | ATTR_GID; | 
|  | 459 | mutex_lock(&dent->d_inode->i_mutex); | 
|  | 460 | notify_change(dent, &attrs); | 
|  | 461 | mutex_unlock(&dent->d_inode->i_mutex); | 
|  | 462 |  | 
|  | 463 | out_dput: | 
|  | 464 | dput(dent); | 
|  | 465 |  | 
|  | 466 | out_unlock: | 
|  | 467 | /* parent dentry locked by lookup_create */ | 
| fluxi | 41b26d8 | 2016-07-29 18:52:13 +0200 | [diff] [blame] | 468 | mutex_unlock(&parent.dentry->d_inode->i_mutex); | 
|  | 469 | path_put(&parent); | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 470 |  | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 471 | return err; | 
|  | 472 | } | 
|  | 473 |  | 
|  | 474 | /* | 
|  | 475 | * Return 1, if a disk has enough free space, otherwise 0. | 
|  | 476 | * We assume that any files can not be overwritten. | 
|  | 477 | */ | 
|  | 478 | static inline int check_min_free_space(struct dentry *dentry, size_t size, int dir) | 
|  | 479 | { | 
|  | 480 | int err; | 
|  | 481 | struct path lower_path; | 
|  | 482 | struct kstatfs statfs; | 
|  | 483 | u64 avail; | 
|  | 484 | struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); | 
|  | 485 |  | 
|  | 486 | if (sbi->options.reserved_mb) { | 
|  | 487 | /* Get fs stat of lower filesystem. */ | 
|  | 488 | sdcardfs_get_lower_path(dentry, &lower_path); | 
|  | 489 | err = vfs_statfs(&lower_path, &statfs); | 
|  | 490 | sdcardfs_put_lower_path(dentry, &lower_path); | 
|  | 491 |  | 
|  | 492 | if (unlikely(err)) | 
|  | 493 | return 0; | 
|  | 494 |  | 
|  | 495 | /* Invalid statfs informations. */ | 
|  | 496 | if (unlikely(statfs.f_bsize == 0)) | 
|  | 497 | return 0; | 
|  | 498 |  | 
|  | 499 | /* if you are checking directory, set size to f_bsize. */ | 
|  | 500 | if (unlikely(dir)) | 
|  | 501 | size = statfs.f_bsize; | 
|  | 502 |  | 
|  | 503 | /* available size */ | 
|  | 504 | avail = statfs.f_bavail * statfs.f_bsize; | 
|  | 505 |  | 
|  | 506 | /* not enough space */ | 
|  | 507 | if ((u64)size > avail) | 
|  | 508 | return 0; | 
|  | 509 |  | 
|  | 510 | /* enough space */ | 
|  | 511 | if ((avail - size) > (sbi->options.reserved_mb * 1024 * 1024)) | 
|  | 512 | return 1; | 
|  | 513 |  | 
|  | 514 | return 0; | 
|  | 515 | } else | 
|  | 516 | return 1; | 
|  | 517 | } | 
|  | 518 |  | 
| Daniel Rosenberg | 95e1721 | 2016-02-03 21:08:21 -0800 | [diff] [blame] | 519 | /* Copies attrs and maintains sdcardfs managed attrs */ | 
|  | 520 | static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src) | 
|  | 521 | { | 
|  | 522 | dest->i_mode = (src->i_mode  & S_IFMT) | get_mode(SDCARDFS_I(dest)); | 
|  | 523 | dest->i_uid = SDCARDFS_I(dest)->d_uid; | 
|  | 524 | dest->i_gid = get_gid(SDCARDFS_I(dest)); | 
|  | 525 | dest->i_rdev = src->i_rdev; | 
|  | 526 | dest->i_atime = src->i_atime; | 
|  | 527 | dest->i_mtime = src->i_mtime; | 
|  | 528 | dest->i_ctime = src->i_ctime; | 
|  | 529 | dest->i_blkbits = src->i_blkbits; | 
|  | 530 | dest->i_flags = src->i_flags; | 
|  | 531 | set_nlink(dest, src->i_nlink); | 
|  | 532 | } | 
| Daniel Campello | 593d662 | 2015-07-20 16:23:50 -0700 | [diff] [blame] | 533 | #endif	/* not _SDCARDFS_H_ */ |