sdcardfs: Bring up to date with Android M permissions:
In M, the workings of sdcardfs were changed significantly.
This brings sdcardfs into line with the changes.
Change-Id: I10e91a84a884c838feef7aa26c0a2b21f02e052e
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index f666eff..ba1c7d9 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -42,6 +42,7 @@
#include <linux/types.h>
#include <linux/security.h>
#include <linux/string.h>
+#include <linux/list.h>
#include "multiuser.h"
/* the file system name */
@@ -70,8 +71,8 @@
#define fix_derived_permission(x) \
do { \
(x)->i_uid = SDCARDFS_I(x)->d_uid; \
- (x)->i_gid = SDCARDFS_I(x)->d_gid; \
- (x)->i_mode = ((x)->i_mode & S_IFMT) | SDCARDFS_I(x)->d_mode;\
+ (x)->i_gid = get_gid(SDCARDFS_I(x)); \
+ (x)->i_mode = ((x)->i_mode & S_IFMT) | get_mode(SDCARDFS_I(x));\
} while (0)
/* OVERRIDE_CRED() and REVERT_CRED()
@@ -99,35 +100,28 @@
(int)current->cred->fsuid, \
(int)current->cred->fsgid);
-/* Android 4.4 support */
+/* Android 5.0 support */
/* Permission mode for a specific node. Controls how file permissions
* are derived for children nodes. */
typedef enum {
- /* Nothing special; this node should just inherit from its parent. */
- PERM_INHERIT,
- /* This node is one level above a normal root; used for legacy layouts
- * which use the first level to represent user_id. */
- PERM_LEGACY_PRE_ROOT,
- /* This node is "/" */
- PERM_ROOT,
- /* This node is "/Android" */
- PERM_ANDROID,
- /* This node is "/Android/data" */
- PERM_ANDROID_DATA,
- /* This node is "/Android/obb" */
- PERM_ANDROID_OBB,
- /* This node is "/Android/user" */
- PERM_ANDROID_USER,
+ /* Nothing special; this node should just inherit from its parent. */
+ PERM_INHERIT,
+ /* This node is one level above a normal root; used for legacy layouts
+ * which use the first level to represent user_id. */
+ PERM_PRE_ROOT,
+ /* This node is "/" */
+ PERM_ROOT,
+ /* This node is "/Android" */
+ PERM_ANDROID,
+ /* This node is "/Android/data" */
+ PERM_ANDROID_DATA,
+ /* This node is "/Android/obb" */
+ PERM_ANDROID_OBB,
+ /* This node is "/Android/media" */
+ PERM_ANDROID_MEDIA,
} perm_t;
-/* Permissions structure to derive */
-typedef enum {
- DERIVE_NONE,
- DERIVE_LEGACY,
- DERIVE_UNIFIED,
-} derive_t;
-
typedef enum {
LOWER_FS_EXT4,
LOWER_FS_FAT,
@@ -161,9 +155,9 @@
extern struct dentry *sdcardfs_lookup(struct inode *dir, struct dentry *dentry,
struct nameidata *nd);
extern struct inode *sdcardfs_iget(struct super_block *sb,
- struct inode *lower_inode);
+ struct inode *lower_inode, userid_t id);
extern int sdcardfs_interpose(struct dentry *dentry, struct super_block *sb,
- struct path *lower_path);
+ struct path *lower_path, userid_t id);
/* file private data */
struct sdcardfs_file_info {
@@ -174,18 +168,16 @@
/* sdcardfs inode data in memory */
struct sdcardfs_inode_info {
struct inode *lower_inode;
- /* state derived based on current position in hierachy
- * caution: d_mode does not include file types
- */
+ /* state derived based on current position in hierachy */
perm_t perm;
userid_t userid;
uid_t d_uid;
- gid_t d_gid;
- mode_t d_mode;
+ bool under_android;
struct inode vfs_inode;
};
+
/* sdcardfs dentry data in memory */
struct sdcardfs_dentry_info {
spinlock_t lock; /* protects lower_path */
@@ -196,15 +188,17 @@
struct sdcardfs_mount_options {
uid_t fs_low_uid;
gid_t fs_low_gid;
- gid_t write_gid;
- int split_perms;
- derive_t derive;
+ userid_t fs_user_id;
+ gid_t gid;
lower_fs_t lower_fs;
+ mode_t mask;
+ bool multiuser;
unsigned int reserved_mb;
};
/* sdcardfs super-block data in memory */
struct sdcardfs_sb_info {
+ struct super_block *sb;
struct super_block *lower_sb;
/* derived perm policy : some of options have been added
* to sdcardfs_mount_options (Android 4.4 support) */
@@ -213,6 +207,7 @@
char *obbpath_s;
struct path obbpath;
void *pkgl_id;
+ struct list_head list;
};
/*
@@ -331,6 +326,44 @@
SDCARDFS_DENT_FUNC(lower_path)
SDCARDFS_DENT_FUNC(orig_path)
+static inline int get_gid(struct sdcardfs_inode_info *info) {
+ struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
+ if (sb_info->options.gid == AID_SDCARD_RW) {
+ /* As an optimization, certain trusted system components only run
+ * as owner but operate across all users. Since we're now handing
+ * out the sdcard_rw GID only to trusted apps, we're okay relaxing
+ * the user boundary enforcement for the default view. The UIDs
+ * assigned to app directories are still multiuser aware. */
+ return AID_SDCARD_RW;
+ } else {
+ return multiuser_get_uid(info->userid, sb_info->options.gid);
+ }
+}
+static inline int get_mode(struct sdcardfs_inode_info *info) {
+ int owner_mode;
+ int filtered_mode;
+ struct sdcardfs_sb_info *sb_info = SDCARDFS_SB(info->vfs_inode.i_sb);
+ int visible_mode = 0775 & ~sb_info->options.mask;
+
+ if (info->perm == PERM_PRE_ROOT) {
+ /* Top of multi-user view should always be visible to ensure
+ * secondary users can traverse inside. */
+ visible_mode = 0711;
+ } else if (info->under_android) {
+ /* Block "other" access to Android directories, since only apps
+ * belonging to a specific user should be in there; we still
+ * leave +x open for the default view. */
+ if (sb_info->options.gid == AID_SDCARD_RW) {
+ visible_mode = visible_mode & ~0006;
+ } else {
+ visible_mode = visible_mode & ~0007;
+ }
+ }
+ owner_mode = info->lower_inode->i_mode & 0700;
+ filtered_mode = visible_mode & (owner_mode | (owner_mode >> 3) | (owner_mode >> 6));
+ return filtered_mode;
+}
+
static inline int has_graft_path(const struct dentry *dent)
{
int ret = 0;
@@ -364,22 +397,24 @@
sdcardfs_put_lower_path(dent, real_lower);
}
+extern struct mutex sdcardfs_super_list_lock;
+extern struct list_head sdcardfs_super_list;
+
/* for packagelist.c */
-extern int get_caller_has_rw_locked(void *pkgl_id, derive_t derive);
extern appid_t get_appid(void *pkgl_id, const char *app_name);
-extern int check_caller_access_to_name(struct inode *parent_node, const char* name,
- derive_t derive, int w_ok, int has_rw);
+extern int check_caller_access_to_name(struct inode *parent_node, const char* name);
extern int open_flags_to_access_mode(int open_flags);
-extern void * packagelist_create(gid_t write_gid);
-extern void packagelist_destroy(void *pkgl_id);
extern int packagelist_init(void);
extern void packagelist_exit(void);
/* for derived_perm.c */
extern void setup_derived_state(struct inode *inode, perm_t perm,
- userid_t userid, uid_t uid, gid_t gid, mode_t mode);
+ userid_t userid, uid_t uid, bool under_android);
extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
-extern void update_derived_permission(struct dentry *dentry);
+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, struct dentry *newdentry);
+extern void get_derive_permissions_recursive(struct dentry *parent);
+
+extern void update_derived_permission_lock(struct dentry *dentry);
extern int need_graft_path(struct dentry *dentry);
extern int is_base_obbpath(struct dentry *dentry);
extern int is_obbpath_invalid(struct dentry *dentry);
@@ -484,4 +519,18 @@
return 1;
}
+/* Copies attrs and maintains sdcardfs managed attrs */
+static inline void sdcardfs_copy_and_fix_attrs(struct inode *dest, const struct inode *src)
+{
+ dest->i_mode = (src->i_mode & S_IFMT) | get_mode(SDCARDFS_I(dest));
+ dest->i_uid = SDCARDFS_I(dest)->d_uid;
+ dest->i_gid = get_gid(SDCARDFS_I(dest));
+ dest->i_rdev = src->i_rdev;
+ dest->i_atime = src->i_atime;
+ dest->i_mtime = src->i_mtime;
+ dest->i_ctime = src->i_ctime;
+ dest->i_blkbits = src->i_blkbits;
+ dest->i_flags = src->i_flags;
+ set_nlink(dest, src->i_nlink);
+}
#endif /* not _SDCARDFS_H_ */