Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <viro@zeniv.linux.org.uk>
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Richard Weinberger <richard@nod.at>

+20 -13
+10 -6
drivers/mtd/ubi/build.c
··· 1147 1147 */ 1148 1148 static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) 1149 1149 { 1150 - int err, major, minor, mode; 1150 + int err, minor; 1151 1151 struct path path; 1152 + struct kstat stat; 1152 1153 1153 1154 /* Probably this is an MTD character device node path */ 1154 1155 err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); 1155 1156 if (err) 1156 1157 return ERR_PTR(err); 1157 1158 1158 - /* MTD device number is defined by the major / minor numbers */ 1159 - major = imajor(d_backing_inode(path.dentry)); 1160 - minor = iminor(d_backing_inode(path.dentry)); 1161 - mode = d_backing_inode(path.dentry)->i_mode; 1159 + err = vfs_getattr(&path, &stat); 1162 1160 path_put(&path); 1163 - if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode)) 1161 + if (err) 1162 + return ERR_PTR(err); 1163 + 1164 + /* MTD device number is defined by the major / minor numbers */ 1165 + if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode)) 1164 1166 return ERR_PTR(-EINVAL); 1167 + 1168 + minor = MINOR(stat.rdev); 1165 1169 1166 1170 if (minor & 1) 1167 1171 /*
+10 -7
drivers/mtd/ubi/kapi.c
··· 301 301 */ 302 302 struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) 303 303 { 304 - int error, ubi_num, vol_id, mod; 305 - struct inode *inode; 304 + int error, ubi_num, vol_id; 306 305 struct path path; 306 + struct kstat stat; 307 307 308 308 dbg_gen("open volume %s, mode %d", pathname, mode); 309 309 ··· 314 314 if (error) 315 315 return ERR_PTR(error); 316 316 317 - inode = d_backing_inode(path.dentry); 318 - mod = inode->i_mode; 319 - ubi_num = ubi_major2num(imajor(inode)); 320 - vol_id = iminor(inode) - 1; 317 + error = vfs_getattr(&path, &stat); 321 318 path_put(&path); 319 + if (error) 320 + return ERR_PTR(error); 322 321 323 - if (!S_ISCHR(mod)) 322 + if (!S_ISCHR(stat.mode)) 324 323 return ERR_PTR(-EINVAL); 324 + 325 + ubi_num = ubi_major2num(MAJOR(stat.rdev)); 326 + vol_id = MINOR(stat.rdev) - 1; 327 + 325 328 if (vol_id >= 0 && ubi_num >= 0) 326 329 return ubi_open_volume(ubi_num, vol_id, mode); 327 330 return ERR_PTR(-ENODEV);