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

9p: don't bother with __getname() in ->follow_link()

We copy there a kmalloc'ed string and proceed to kfree that string immediately
after that. Easier to just feed that string to nd_set_link() and _not_
kfree it until ->put_link() (which becomes kfree_put_link() in that case).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro 90e4fc88 b46c267e

+31 -105
-2
fs/9p/v9fs.h
··· 149 149 extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); 150 150 extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 151 151 struct inode *new_dir, struct dentry *new_dentry); 152 - extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, 153 - void *p); 154 152 extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, 155 153 struct p9_fid *fid, 156 154 struct super_block *sb, int new);
+23 -80
fs/9p/vfs_inode.c
··· 1224 1224 } 1225 1225 1226 1226 /** 1227 - * v9fs_readlink - read a symlink's location (internal version) 1228 - * @dentry: dentry for symlink 1229 - * @buffer: buffer to load symlink location into 1230 - * @buflen: length of buffer 1231 - * 1232 - */ 1233 - 1234 - static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 1235 - { 1236 - int retval; 1237 - 1238 - struct v9fs_session_info *v9ses; 1239 - struct p9_fid *fid; 1240 - struct p9_wstat *st; 1241 - 1242 - p9_debug(P9_DEBUG_VFS, " %pd\n", dentry); 1243 - retval = -EPERM; 1244 - v9ses = v9fs_dentry2v9ses(dentry); 1245 - fid = v9fs_fid_lookup(dentry); 1246 - if (IS_ERR(fid)) 1247 - return PTR_ERR(fid); 1248 - 1249 - if (!v9fs_proto_dotu(v9ses)) 1250 - return -EBADF; 1251 - 1252 - st = p9_client_stat(fid); 1253 - if (IS_ERR(st)) 1254 - return PTR_ERR(st); 1255 - 1256 - if (!(st->mode & P9_DMSYMLINK)) { 1257 - retval = -EINVAL; 1258 - goto done; 1259 - } 1260 - 1261 - /* copy extension buffer into buffer */ 1262 - retval = min(strlen(st->extension)+1, (size_t)buflen); 1263 - memcpy(buffer, st->extension, retval); 1264 - 1265 - p9_debug(P9_DEBUG_VFS, "%pd -> %s (%.*s)\n", 1266 - dentry, st->extension, buflen, buffer); 1267 - 1268 - done: 1269 - p9stat_free(st); 1270 - kfree(st); 1271 - return retval; 1272 - } 1273 - 1274 - /** 1275 1227 * v9fs_vfs_follow_link - follow a symlink path 1276 1228 * @dentry: dentry for symlink 1277 1229 * @nd: nameidata ··· 1232 1280 1233 1281 static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) 1234 1282 { 1235 - int len = 0; 1236 - char *link = __getname(); 1283 + struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry); 1284 + struct p9_fid *fid = v9fs_fid_lookup(dentry); 1285 + struct p9_wstat *st; 1237 1286 1238 1287 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); 1239 1288 1240 - if (!link) 1241 - link = ERR_PTR(-ENOMEM); 1242 - else { 1243 - len = v9fs_readlink(dentry, link, PATH_MAX); 1289 + if (IS_ERR(fid)) 1290 + return ERR_CAST(fid); 1244 1291 1245 - if (len < 0) { 1246 - __putname(link); 1247 - link = ERR_PTR(len); 1248 - } else 1249 - link[min(len, PATH_MAX-1)] = 0; 1292 + if (!v9fs_proto_dotu(v9ses)) 1293 + return ERR_PTR(-EBADF); 1294 + 1295 + st = p9_client_stat(fid); 1296 + if (IS_ERR(st)) 1297 + return ERR_CAST(st); 1298 + 1299 + if (!(st->mode & P9_DMSYMLINK)) { 1300 + p9stat_free(st); 1301 + kfree(st); 1302 + return ERR_PTR(-EINVAL); 1250 1303 } 1251 - nd_set_link(nd, link); 1304 + if (strlen(st->extension) >= PATH_MAX) 1305 + st->extension[PATH_MAX - 1] = '\0'; 1252 1306 1307 + nd_set_link(nd, st->extension); 1308 + st->extension = NULL; 1309 + p9stat_free(st); 1310 + kfree(st); 1253 1311 return NULL; 1254 - } 1255 - 1256 - /** 1257 - * v9fs_vfs_put_link - release a symlink path 1258 - * @dentry: dentry for symlink 1259 - * @nd: nameidata 1260 - * @p: unused 1261 - * 1262 - */ 1263 - 1264 - void 1265 - v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) 1266 - { 1267 - char *s = nd_get_link(nd); 1268 - 1269 - p9_debug(P9_DEBUG_VFS, " %pd %s\n", 1270 - dentry, IS_ERR(s) ? "<error>" : s); 1271 - if (!IS_ERR(s)) 1272 - __putname(s); 1273 1312 } 1274 1313 1275 1314 /** ··· 1457 1514 static const struct inode_operations v9fs_symlink_inode_operations = { 1458 1515 .readlink = generic_readlink, 1459 1516 .follow_link = v9fs_vfs_follow_link, 1460 - .put_link = v9fs_vfs_put_link, 1517 + .put_link = kfree_put_link, 1461 1518 .getattr = v9fs_vfs_getattr, 1462 1519 .setattr = v9fs_vfs_setattr, 1463 1520 };
+8 -23
fs/9p/vfs_inode_dotl.c
··· 912 912 static void * 913 913 v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) 914 914 { 915 - int retval; 916 - struct p9_fid *fid; 917 - char *link = __getname(); 915 + struct p9_fid *fid = v9fs_fid_lookup(dentry); 918 916 char *target; 917 + int retval; 919 918 920 919 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); 921 920 922 - if (!link) { 923 - link = ERR_PTR(-ENOMEM); 924 - goto ndset; 925 - } 926 - fid = v9fs_fid_lookup(dentry); 927 - if (IS_ERR(fid)) { 928 - __putname(link); 929 - link = ERR_CAST(fid); 930 - goto ndset; 931 - } 921 + if (IS_ERR(fid)) 922 + return ERR_CAST(fid); 932 923 retval = p9_client_readlink(fid, &target); 933 - if (!retval) { 934 - strcpy(link, target); 935 - kfree(target); 936 - goto ndset; 937 - } 938 - __putname(link); 939 - link = ERR_PTR(retval); 940 - ndset: 941 - nd_set_link(nd, link); 924 + if (retval) 925 + return ERR_PTR(retval); 926 + nd_set_link(nd, target); 942 927 return NULL; 943 928 } 944 929 ··· 991 1006 const struct inode_operations v9fs_symlink_inode_operations_dotl = { 992 1007 .readlink = generic_readlink, 993 1008 .follow_link = v9fs_vfs_follow_link_dotl, 994 - .put_link = v9fs_vfs_put_link, 1009 + .put_link = kfree_put_link, 995 1010 .getattr = v9fs_vfs_getattr_dotl, 996 1011 .setattr = v9fs_vfs_setattr_dotl, 997 1012 .setxattr = generic_setxattr,