}
/* While renaming, there is a point where we want the path from dentry, but the name from newdentry */
-void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const char *name)
+void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name)
{
struct sdcardfs_inode_info *info = SDCARDFS_I(d_inode(dentry));
struct sdcardfs_inode_info *parent_info= SDCARDFS_I(d_inode(parent));
appid_t appid;
+ struct qstr q_Android = QSTR_LITERAL("Android");
+ struct qstr q_data = QSTR_LITERAL("data");
+ struct qstr q_obb = QSTR_LITERAL("obb");
+ struct qstr q_media = QSTR_LITERAL("media");
+ struct qstr q_cache = QSTR_LITERAL("cache");
/* By default, each inode inherits from its parent.
* the properties are maintained on its private fields
case PERM_PRE_ROOT:
/* Legacy internal layout places users at top level */
info->perm = PERM_ROOT;
- info->userid = simple_strtoul(name, NULL, 10);
+ info->userid = simple_strtoul(name->name, NULL, 10);
set_top(info, &info->vfs_inode);
break;
case PERM_ROOT:
/* Assume masked off by default. */
- if (!strcasecmp(name, "Android")) {
+ if (qstr_case_eq(name, &q_Android)) {
/* App-specific directories inside; let anyone traverse */
info->perm = PERM_ANDROID;
info->under_android = true;
}
break;
case PERM_ANDROID:
- if (!strcasecmp(name, "data")) {
+ if (qstr_case_eq(name, &q_data)) {
/* App-specific directories inside; let anyone traverse */
info->perm = PERM_ANDROID_DATA;
set_top(info, &info->vfs_inode);
- } else if (!strcasecmp(name, "obb")) {
+ } else if (qstr_case_eq(name, &q_obb)) {
/* App-specific directories inside; let anyone traverse */
info->perm = PERM_ANDROID_OBB;
info->under_obb = true;
set_top(info, &info->vfs_inode);
/* Single OBB directory is always shared */
- } else if (!strcasecmp(name, "media")) {
+ } else if (qstr_case_eq(name, &q_media)) {
/* App-specific directories inside; let anyone traverse */
info->perm = PERM_ANDROID_MEDIA;
set_top(info, &info->vfs_inode);
case PERM_ANDROID_DATA:
case PERM_ANDROID_MEDIA:
info->perm = PERM_ANDROID_PACKAGE;
- appid = get_appid(name);
- if (appid != 0 && !is_excluded(name, parent_info->userid)) {
+ appid = get_appid(name->name);
+ if (appid != 0 && !is_excluded(name->name, parent_info->userid)) {
info->d_uid = multiuser_get_uid(parent_info->userid, appid);
}
set_top(info, &info->vfs_inode);
break;
case PERM_ANDROID_PACKAGE:
- if (!strcasecmp(name, "cache")) {
+ if (qstr_case_eq(name, &q_cache)) {
info->perm = PERM_ANDROID_PACKAGE_CACHE;
info->under_cache = true;
}
void get_derived_permission(struct dentry *parent, struct dentry *dentry)
{
- get_derived_permission_new(parent, dentry, dentry->d_name.name);
+ get_derived_permission_new(parent, dentry, &dentry->d_name);
}
static appid_t get_type(const char *name)
struct dentry *parent = dget_parent(dentry);
struct sdcardfs_inode_info *parent_info= SDCARDFS_I(d_inode(parent));
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+ struct qstr obb = QSTR_LITERAL("obb");
if(parent_info->perm == PERM_ANDROID &&
- !strcasecmp(dentry->d_name.name, "obb")) {
+ qstr_case_eq(&dentry->d_name, &obb)) {
/* /Android/obb is the base obbpath of DERIVED_UNIFIED */
if(!(sbi->options.multiuser == false
} else {
obbpath_s = d_path(&di->lower_path, path_buf, PATH_MAX);
if (d_unhashed(di->lower_path.dentry) ||
- strcasecmp(sbi->obbpath_s, obbpath_s)) {
+ !str_case_eq(sbi->obbpath_s, obbpath_s)) {
ret = 1;
}
kfree(path_buf);
struct dentry *parent = dget_parent(dentry);
struct sdcardfs_inode_info *parent_info= SDCARDFS_I(d_inode(parent));
struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb);
+ struct qstr q_obb = QSTR_LITERAL("obb");
spin_lock(&SDCARDFS_D(dentry)->lock);
if (sbi->options.multiuser) {
if(parent_info->perm == PERM_PRE_ROOT &&
- !strcasecmp(dentry->d_name.name, "obb")) {
+ qstr_case_eq(&dentry->d_name, &q_obb)) {
ret = 1;
}
} else if (parent_info->perm == PERM_ANDROID &&
- !strcasecmp(dentry->d_name.name, "obb")) {
+ qstr_case_eq(&dentry->d_name, &q_obb)) {
ret = 1;
}
spin_unlock(&SDCARDFS_D(dentry)->lock);
goto out_err;
}
- if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
struct fs_struct *saved_fs;
struct fs_struct *copied_fs;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
+ if (!check_caller_access_to_name(dir, &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
struct path lower_path;
const struct cred *saved_cred = NULL;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
+ if (!check_caller_access_to_name(dir, &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
int touch_err = 0;
struct fs_struct *saved_fs;
struct fs_struct *copied_fs;
+ struct qstr q_obb = QSTR_LITERAL("obb");
+ struct qstr q_data = QSTR_LITERAL("data");
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
+ if (!check_caller_access_to_name(dir, &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
set_nlink(dir, sdcardfs_lower_inode(dir)->i_nlink);
fixup_lower_ownership(dentry, dentry->d_name.name);
unlock_dir(lower_parent_dentry);
- if ((!sbi->options.multiuser) && (!strcasecmp(dentry->d_name.name, "obb"))
+ if ((!sbi->options.multiuser) && (qstr_case_eq(&dentry->d_name, &q_obb))
&& (pi->perm == PERM_ANDROID) && (pi->userid == 0))
make_nomedia_in_obb = 1;
/* When creating /Android/data and /Android/obb, mark them as .nomedia */
if (make_nomedia_in_obb ||
- ((pi->perm == PERM_ANDROID) && (!strcasecmp(dentry->d_name.name, "data")))) {
+ ((pi->perm == PERM_ANDROID) && (qstr_case_eq(&dentry->d_name, &q_data)))) {
REVERT_CRED(saved_cred);
OVERRIDE_CRED(SDCARDFS_SB(dir->i_sb), saved_cred, SDCARDFS_I(d_inode(dentry)));
set_fs_pwd(current->fs, &lower_path);
struct path lower_path;
const struct cred *saved_cred = NULL;
- if(!check_caller_access_to_name(dir, dentry->d_name.name)) {
+ if (!check_caller_access_to_name(dir, &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
if (flags)
return -EINVAL;
- if(!check_caller_access_to_name(old_dir, old_dentry->d_name.name) ||
- !check_caller_access_to_name(new_dir, new_dentry->d_name.name)) {
+ if (!check_caller_access_to_name(old_dir, &old_dentry->d_name) ||
+ !check_caller_access_to_name(new_dir, &new_dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" new_dentry: %s, task:%s\n",
__func__, new_dentry->d_name.name, current->comm);
sdcardfs_copy_and_fix_attrs(old_dir, d_inode(lower_old_dir_dentry));
fsstack_copy_inode_size(old_dir, d_inode(lower_old_dir_dentry));
}
- get_derived_permission_new(new_dentry->d_parent, old_dentry, new_dentry->d_name.name);
+ get_derived_permission_new(new_dentry->d_parent, old_dentry, &new_dentry->d_name);
fixup_tmp_permissions(d_inode(old_dentry));
fixup_lower_ownership(old_dentry, new_dentry->d_name.name);
drop_recursive(old_dentry); /* Can't fixup ownership recursively :( */
if (!err) {
/* check the Android group ID */
parent = dget_parent(dentry);
- if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
int err;
parent = dget_parent(dentry);
- if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
__func__, dentry->d_name.name, current->comm);
struct vfsmount *lower_dir_mnt;
struct dentry *lower_dir_dentry = NULL;
struct dentry *lower_dentry;
- const char *name;
+ const struct qstr *name;
struct path lower_path;
- struct qstr this;
struct sdcardfs_sb_info *sbi;
sbi = SDCARDFS_SB(dentry->d_sb);
if (IS_ROOT(dentry))
goto out;
- name = dentry->d_name.name;
+ name = &dentry->d_name;
/* now start the actual lookup procedure */
lower_dir_dentry = lower_parent_path->dentry;
lower_dir_mnt = lower_parent_path->mnt;
/* Use vfs_path_lookup to check if the dentry exists or not */
- err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
+ err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name->name, 0,
&lower_path);
/* check for other cases */
if (err == -ENOENT) {
spin_lock(&lower_dir_dentry->d_lock);
list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) {
if (child && d_inode(child)) {
- if (strcasecmp(child->d_name.name, name)==0) {
+ if (qstr_case_eq(&child->d_name, name)) {
match = dget(child);
break;
}
goto out;
/* instatiate a new negative dentry */
- this.name = name;
- this.len = strlen(name);
- this.hash = full_name_hash(dentry, this.name, this.len);
- lower_dentry = d_lookup(lower_dir_dentry, &this);
+ lower_dentry = d_lookup(lower_dir_dentry, name);
if (lower_dentry)
goto setup_lower;
- lower_dentry = d_alloc(lower_dir_dentry, &this);
+ lower_dentry = d_alloc(lower_dir_dentry, name);
if (!lower_dentry) {
err = -ENOMEM;
goto out;
parent = dget_parent(dentry);
- if(!check_caller_access_to_name(d_inode(parent), dentry->d_name.name)) {
+ if (!check_caller_access_to_name(d_inode(parent), &dentry->d_name)) {
ret = ERR_PTR(-EACCES);
printk(KERN_INFO "%s: need to check the caller's gid in packages.list\n"
" dentry: %s, task:%s\n",
rcu_read_lock();
hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name)) {
+ if (qstr_case_eq(key, &hash_cur->key)) {
ret_id = atomic_read(&hash_cur->value);
rcu_read_unlock();
return ret_id;
rcu_read_lock();
hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name)) {
+ if (qstr_case_eq(key, &hash_cur->key)) {
ret_id = atomic_read(&hash_cur->value);
rcu_read_unlock();
return ret_id;
rcu_read_lock();
hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
if (atomic_read(&hash_cur->value) == user &&
- !strcasecmp(app_name->name, hash_cur->key.name)) {
+ qstr_case_eq(app_name, &hash_cur->key)) {
rcu_read_unlock();
return 1;
}
return 0;
}
-appid_t is_excluded(const char *app_name, userid_t user)
+appid_t is_excluded(const char *key, userid_t user)
{
struct qstr q;
- qstr_init(&q, app_name);
+ qstr_init(&q, key);
return __is_excluded(&q, user);
}
-
/* Kernel has already enforced everything we returned through
* derive_permissions_locked(), so this is used to lock down access
* even further, such as enforcing that apps hold sdcard_rw. */
-int check_caller_access_to_name(struct inode *parent_node, const char *name)
+int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name)
{
+ struct qstr q_autorun = QSTR_LITERAL("autorun.inf");
+ struct qstr q__android_secure = QSTR_LITERAL(".android_secure");
+ struct qstr q_android_secure = QSTR_LITERAL("android_secure");
+
/* Always block security-sensitive files at root */
if (parent_node && SDCARDFS_I(parent_node)->perm == PERM_ROOT) {
- if (!strcasecmp(name, "autorun.inf")
- || !strcasecmp(name, ".android_secure")
- || !strcasecmp(name, "android_secure")) {
+ if (qstr_case_eq(name, &q_autorun)
+ || qstr_case_eq(name, &q__android_secure)
+ || qstr_case_eq(name, &q_android_secure)) {
return 0;
}
}
unsigned int hash = key->hash;
hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name)) {
+ if (qstr_case_eq(key, &hash_cur->key)) {
atomic_set(&hash_cur->value, value);
return 0;
}
/* An extension can only belong to one gid */
hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name))
+ if (qstr_case_eq(key, &hash_cur->key))
return -EINVAL;
}
new_entry = alloc_hashtable_entry(key, value);
/* Only insert if not already present */
hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
if (atomic_read(&hash_cur->value) == value &&
- !strcasecmp(key->name, hash_cur->key.name))
+ qstr_case_eq(key, &hash_cur->key))
return 0;
}
new_entry = alloc_hashtable_entry(key, value);
HLIST_HEAD(free_list);
hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name)) {
+ if (qstr_case_eq(key, &hash_cur->key)) {
hash_del_rcu(&hash_cur->hlist);
hlist_add_head(&hash_cur->dlist, &free_list);
}
}
hash_for_each_possible_rcu(package_to_appid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name)) {
+ if (qstr_case_eq(key, &hash_cur->key)) {
hash_del_rcu(&hash_cur->hlist);
hlist_add_head(&hash_cur->dlist, &free_list);
break;
unsigned int hash = key->hash;
hash_for_each_possible_rcu(ext_to_groupid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name) && atomic_read(&hash_cur->value) == group) {
+ if (qstr_case_eq(key, &hash_cur->key) && atomic_read(&hash_cur->value) == group) {
hash_del_rcu(&hash_cur->hlist);
synchronize_rcu();
free_hashtable_entry(hash_cur);
unsigned int hash = key->hash;
hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
- if (!strcasecmp(key->name, hash_cur->key.name) &&
+ if (qstr_case_eq(key, &hash_cur->key) &&
atomic_read(&hash_cur->value) == userid) {
hash_del_rcu(&hash_cur->hlist);
synchronize_rcu();
rcu_read_lock();
hash_for_each_possible_rcu(package_to_userid, hash_cur, hlist, hash) {
- if (!strcasecmp(package_details->name.name, hash_cur->key.name))
+ if (qstr_case_eq(&package_details->name, &hash_cur->key))
count += scnprintf(page + count, PAGE_SIZE - count,
"%d ", atomic_read(&hash_cur->value));
}
hash_cur_app->key.name, atomic_read(&hash_cur_app->value));
hash = hash_cur_app->key.hash;
hash_for_each_possible_rcu(package_to_userid, hash_cur_user, hlist, hash) {
- if (!strcasecmp(hash_cur_app->key.name, hash_cur_user->key.name)) {
+ if (qstr_case_eq(&hash_cur_app->key, &hash_cur_user->key)) {
written += scnprintf(page + count + written - 1,
PAGE_SIZE - sizeof(errormsg) - count - written + 1,
" %d\n", atomic_read(&hash_cur_user->value)) - 1;
extern appid_t get_appid(const char *app_name);
extern appid_t get_ext_gid(const char *app_name);
extern appid_t is_excluded(const char *app_name, userid_t userid);
-extern int check_caller_access_to_name(struct inode *parent_node, const char* name);
+extern int check_caller_access_to_name(struct inode *parent_node, const struct qstr *name);
extern int open_flags_to_access_mode(int open_flags);
extern int packagelist_init(void);
extern void packagelist_exit(void);
extern void setup_derived_state(struct inode *inode, perm_t perm, userid_t userid,
uid_t uid, bool under_android, struct inode *top);
extern void get_derived_permission(struct dentry *parent, struct dentry *dentry);
-extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const char *name);
+extern void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, const struct qstr *name);
extern void drop_recursive(struct dentry *parent);
extern void fixup_top_recursive(struct dentry *parent);
extern void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit);
dest->i_flags = src->i_flags;
set_nlink(dest, src->i_nlink);
}
+
+static inline bool str_case_eq(const char *s1, const char *s2)
+{
+ return !strcasecmp(s1, s2);
+}
+
+static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
+{
+ return q1->len == q2->len && str_case_eq(q1->name, q2->name);
+}
+
+#define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1)
+
#endif /* not _SDCARDFS_H_ */