From cf8f7947f2939c70d488e6935a050760b7feede7 Mon Sep 17 00:00:00 2001 From: Alistair Delva Date: Tue, 2 Feb 2021 17:10:49 -0800 Subject: [PATCH] ANDROID: Add filp_open_block() for zram We currently plan to disallow use of filp_open() from drivers in GKI, however the ZRAM driver still needs it. Add a new GKI-only variant of filp_open() which only permits a block device to be opened, which can be exported instead. This keeps ZRAM working but cuts down on drivers that attempt to open and write files in kernel mode. Bug: 179220339 Change-Id: Id696b4aaf204b0499ce0a1b6416648670236e570 Signed-off-by: Alistair Delva --- drivers/block/zram/zram_drv.c | 2 +- fs/open.c | 20 ++++++++++++++++++++ include/linux/fs.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) 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 *);