From ad022c87187b50f50937bd9bcd1ef312442a89af Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 12 Jun 2016 23:37:53 +0200 Subject: [PATCH 1/3] Revert "mtd: switch ubi_open_volume_path() to vfs_stat()" This reverts commit 322ea0bbf3003df17b6253f76e572c37d79a6810. vfs_stat() can only be used on user supplied buffers. UBI's kapi.c is the API to the kernel and therefore vfs_stat() is inappropriate. This solves the problem that mounting any UBIFS will immediately fail with -EINVAL. Cc: Al Viro Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/kapi.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 348dbbcbedc8..cc6fa0115c9a 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -301,24 +301,27 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { - int error, ubi_num, vol_id; - struct kstat stat; + int error, ubi_num, vol_id, mod; + struct inode *inode; + struct path path; dbg_gen("open volume %s, mode %d", pathname, mode); if (!pathname || !*pathname) return ERR_PTR(-EINVAL); - error = vfs_stat(pathname, &stat); + error = kern_path(pathname, LOOKUP_FOLLOW, &path); if (error) return ERR_PTR(error); - if (!S_ISCHR(stat.mode)) + inode = d_backing_inode(path.dentry); + mod = inode->i_mode; + ubi_num = ubi_major2num(imajor(inode)); + vol_id = iminor(inode) - 1; + path_put(&path); + + if (!S_ISCHR(mod)) return ERR_PTR(-EINVAL); - - ubi_num = ubi_major2num(MAJOR(stat.rdev)); - vol_id = MINOR(stat.rdev) - 1; - if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV); From 1a498ec45eeabcb246c3c3f5822ed9ac1b4f70d8 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 13 Jun 2016 00:49:03 +0200 Subject: [PATCH 2/3] Revert "mtd: switch open_mtd_by_chdev() to use of vfs_stat()" This reverts commit 87f15d4add758fb7fc76655721af94be57a4c17d. vfs_stat() can only be used on user supplied buffers. Cc: Al Viro Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 16baeb51b2bd..7091fca0fb44 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1147,19 +1147,22 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) */ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) { - struct kstat stat; - int err, minor; + int err, major, minor, mode; + struct path path; /* Probably this is an MTD character device node path */ - err = vfs_stat(mtd_dev, &stat); + err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); if (err) return ERR_PTR(err); /* MTD device number is defined by the major / minor numbers */ - if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode)) + major = imajor(d_backing_inode(path.dentry)); + minor = iminor(d_backing_inode(path.dentry)); + mode = d_backing_inode(path.dentry)->i_mode; + path_put(&path); + if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode)) return ERR_PTR(-EINVAL); - minor = MINOR(stat.rdev); if (minor & 1) /* * Just do not think the "/dev/mtdrX" devices support is need, From 61edc3f3b51d2d3948029197cfff6fef7d94e939 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 13 Jun 2016 00:49:04 +0200 Subject: [PATCH 3/3] ubi: Don't bypass ->getattr() Directly accessing inode fields bypasses ->getattr() and can cause problems when the underlying filesystem does not have the default ->getattr() implementation. So instead of obtaining the backing inode via d_backing_inode() use vfs_getattr() and obtain what we need from the kstat struct. Cc: Al Viro Reported-by: Al Viro Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/build.c | 16 ++++++++++------ drivers/mtd/ubi/kapi.c | 17 ++++++++++------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 7091fca0fb44..ef3618299494 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -1147,22 +1147,26 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) */ static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) { - int err, major, minor, mode; + int err, minor; struct path path; + struct kstat stat; /* Probably this is an MTD character device node path */ err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); if (err) return ERR_PTR(err); - /* MTD device number is defined by the major / minor numbers */ - major = imajor(d_backing_inode(path.dentry)); - minor = iminor(d_backing_inode(path.dentry)); - mode = d_backing_inode(path.dentry)->i_mode; + err = vfs_getattr(&path, &stat); path_put(&path); - if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode)) + if (err) + return ERR_PTR(err); + + /* MTD device number is defined by the major / minor numbers */ + if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); + minor = MINOR(stat.rdev); + if (minor & 1) /* * Just do not think the "/dev/mtdrX" devices support is need, diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index cc6fa0115c9a..a9e2cef7c95c 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -301,9 +301,9 @@ EXPORT_SYMBOL_GPL(ubi_open_volume_nm); */ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) { - int error, ubi_num, vol_id, mod; - struct inode *inode; + int error, ubi_num, vol_id; struct path path; + struct kstat stat; dbg_gen("open volume %s, mode %d", pathname, mode); @@ -314,14 +314,17 @@ struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) if (error) return ERR_PTR(error); - inode = d_backing_inode(path.dentry); - mod = inode->i_mode; - ubi_num = ubi_major2num(imajor(inode)); - vol_id = iminor(inode) - 1; + error = vfs_getattr(&path, &stat); path_put(&path); + if (error) + return ERR_PTR(error); - if (!S_ISCHR(mod)) + if (!S_ISCHR(stat.mode)) return ERR_PTR(-EINVAL); + + ubi_num = ubi_major2num(MAJOR(stat.rdev)); + vol_id = MINOR(stat.rdev) - 1; + if (vol_id >= 0 && ubi_num >= 0) return ubi_open_volume(ubi_num, vol_id, mode); return ERR_PTR(-ENODEV);