Commit eead19115329c5615ba03cbaf1c3fe24c14858a3

Authored by Christoph Hellwig
Committed by Linus Torvalds
1 parent ebb3e820b8

partially fix up the lookup_one_noperm mess

Try to fix the mess created by sysfs braindamage.

 - refactor code internal to fs/namei.c a little to avoid too much
   duplication:
	o __lookup_hash_kern is renamed back to __lookup_hash
	o the old __lookup_hash goes away, permission checks moves to
	  the two callers
	o useless inline qualifiers on above functions go away
 - lookup_one_len_kern loses it's last argument and is renamed to
   lookup_one_noperm to make it's useage a little more clear
 - added kerneldoc comments to describe lookup_one_len aswell as
   lookup_one_noperm and make it very clear that no one should use
   the latter ever.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Cc: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 39 additions and 26 deletions Side-by-side Diff

... ... @@ -1273,7 +1273,8 @@
1273 1273 return err;
1274 1274 }
1275 1275  
1276   -static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
  1276 +static struct dentry *__lookup_hash(struct qstr *name,
  1277 + struct dentry *base, struct nameidata *nd)
1277 1278 {
1278 1279 struct dentry *dentry;
1279 1280 struct inode *inode;
1280 1281  
1281 1282  
1282 1283  
1283 1284  
... ... @@ -1313,31 +1314,18 @@
1313 1314 * needs parent already locked. Doesn't follow mounts.
1314 1315 * SMP-safe.
1315 1316 */
1316   -static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd)
  1317 +static struct dentry *lookup_hash(struct nameidata *nd)
1317 1318 {
1318   - struct dentry *dentry;
1319   - struct inode *inode;
1320 1319 int err;
1321 1320  
1322   - inode = base->d_inode;
1323   -
1324   - err = permission(inode, MAY_EXEC, nd);
1325   - dentry = ERR_PTR(err);
  1321 + err = permission(nd->dentry->d_inode, MAY_EXEC, nd);
1326 1322 if (err)
1327   - goto out;
1328   -
1329   - dentry = __lookup_hash_kern(name, base, nd);
1330   -out:
1331   - return dentry;
1332   -}
1333   -
1334   -static struct dentry *lookup_hash(struct nameidata *nd)
1335   -{
  1323 + return ERR_PTR(err);
1336 1324 return __lookup_hash(&nd->last, nd->dentry, nd);
1337 1325 }
1338 1326  
1339   -/* SMP-safe */
1340   -static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
  1327 +static int __lookup_one_len(const char *name, struct qstr *this,
  1328 + struct dentry *base, int len)
1341 1329 {
1342 1330 unsigned long hash;
1343 1331 unsigned int c;
... ... @@ -1358,6 +1346,17 @@
1358 1346 return 0;
1359 1347 }
1360 1348  
  1349 +/**
  1350 + * lookup_one_len: filesystem helper to lookup single pathname component
  1351 + * @name: pathname component to lookup
  1352 + * @base: base directory to lookup from
  1353 + * @len: maximum length @len should be interpreted to
  1354 + *
  1355 + * Note that this routine is purely a helper for filesystem useage and should
  1356 + * not be called by generic code. Also note that by using this function to
  1357 + * nameidata argument is passed to the filesystem methods and a filesystem
  1358 + * using this helper needs to be prepared for that.
  1359 + */
1361 1360 struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
1362 1361 {
1363 1362 int err;
1364 1363  
1365 1364  
1366 1365  
... ... @@ -1366,18 +1365,33 @@
1366 1365 err = __lookup_one_len(name, &this, base, len);
1367 1366 if (err)
1368 1367 return ERR_PTR(err);
  1368 +
  1369 + err = permission(base->d_inode, MAY_EXEC, NULL);
  1370 + if (err)
  1371 + return ERR_PTR(err);
1369 1372 return __lookup_hash(&this, base, NULL);
1370 1373 }
1371 1374  
1372   -struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
  1375 +/**
  1376 + * lookup_one_noperm - bad hack for sysfs
  1377 + * @name: pathname component to lookup
  1378 + * @base: base directory to lookup from
  1379 + *
  1380 + * This is a variant of lookup_one_len that doesn't perform any permission
  1381 + * checks. It's a horrible hack to work around the braindead sysfs
  1382 + * architecture and should not be used anywhere else.
  1383 + *
  1384 + * DON'T USE THIS FUNCTION EVER, thanks.
  1385 + */
  1386 +struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
1373 1387 {
1374 1388 int err;
1375 1389 struct qstr this;
1376 1390  
1377   - err = __lookup_one_len(name, &this, base, len);
  1391 + err = __lookup_one_len(name, &this, base, strlen(name));
1378 1392 if (err)
1379 1393 return ERR_PTR(err);
1380   - return __lookup_hash_kern(&this, base, NULL);
  1394 + return __lookup_hash(&this, base, NULL);
1381 1395 }
1382 1396  
1383 1397 int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
... ... @@ -112,8 +112,7 @@
112 112 /* look it up */
113 113 parent = dentry;
114 114 mutex_lock(&parent->d_inode->i_mutex);
115   - dentry = lookup_one_len_kern(cur->s_name, parent,
116   - strlen(cur->s_name));
  115 + dentry = lookup_one_noperm(cur->s_name, parent);
117 116 mutex_unlock(&parent->d_inode->i_mutex);
118 117 dput(parent);
119 118  
include/linux/namei.h
... ... @@ -81,8 +81,8 @@
81 81 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
82 82 extern void release_open_intent(struct nameidata *);
83 83  
84   -extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
85   -extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int);
  84 +extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
  85 +extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
86 86  
87 87 extern int follow_down(struct vfsmount **, struct dentry **);
88 88 extern int follow_up(struct vfsmount **, struct dentry **);