diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 1b697208d661..2ec0ddc24a3d 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -477,7 +477,7 @@ static ssize_t backing_dev_store(struct device *dev, if (sz > 0 && file_name[sz - 1] == '\n') file_name[sz - 1] = 0x00; - backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0); + backing_dev = filp_open_block(file_name, O_RDWR|O_LARGEFILE, 0); if (IS_ERR(backing_dev)) { err = PTR_ERR(backing_dev); backing_dev = NULL; diff --git a/fs/open.c b/fs/open.c index 4d7537ae59df..ce8ebdadbac8 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1141,6 +1141,26 @@ struct file *filp_open(const char *filename, int flags, umode_t mode) } EXPORT_SYMBOL(filp_open); +/* ANDROID: Allow drivers to open only block files from kernel mode */ +struct file *filp_open_block(const char *filename, int flags, umode_t mode) +{ + struct file *file; + + file = filp_open(filename, flags, mode); + if (IS_ERR(file)) + goto err_out; + + /* Drivers should only be allowed to open block devices */ + if (!S_ISBLK(file->f_mapping->host->i_mode)) { + filp_close(file, NULL); + file = ERR_PTR(-ENOTBLK); + } + +err_out: + return file; +} +EXPORT_SYMBOL_GPL(filp_open_block); + struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, const char *filename, int flags, umode_t mode) { diff --git a/include/linux/fs.h b/include/linux/fs.h index d25141fc91c2..70d13ce3052b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2528,6 +2528,7 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode); extern struct file *file_open_name(struct filename *, int, umode_t); extern struct file *filp_open(const char *, int, umode_t); +extern struct file *filp_open_block(const char *, int, umode_t); extern struct file *file_open_root(struct dentry *, struct vfsmount *, const char *, int, umode_t); extern struct file * dentry_open(const struct path *, int, const struct cred *);