From 86acdca1b63e6890540fa19495cfc708beff3d8b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 22 Dec 2009 23:45:11 -0500 Subject: fix autofs/afs/etc. magic mountpoint breakage We end up trying to kfree() nd.last.name on open("/mnt/tmp", O_CREAT) if /mnt/tmp is an autofs direct mount. The reason is that nd.last_type is bogus here; we want LAST_BIND for everything of that kind and we get LAST_NORM left over from finding parent directory. So make sure that it *is* set properly; set to LAST_BIND before doing ->follow_link() - for normal symlinks it will be changed by __vfs_follow_link() and everything else needs it set that way. Signed-off-by: Al Viro --- fs/namei.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index b55440baf7a..1b26b162066 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -561,6 +561,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata dget(dentry); } mntget(path->mnt); + nd->last_type = LAST_BIND; cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie); if (!IS_ERR(cookie)) { -- cgit v1.2.3 From 6d125529c6cbfe570ce3bf9a0728548f087499da Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 24 Dec 2009 06:58:56 -0500 Subject: Fix ACC_MODE() for real commit 5300990c0370e804e49d9a59d928c5d53fb73487 had stepped on a rather nasty mess: definitions of ACC_MODE used to be different. Fixed the resulting breakage, converting them to variant that takes O_... value; all callers have that and it actually simplifies life (see tomoyo part of changes). Signed-off-by: Al Viro --- fs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index 1b26b162066..d930f1856ed 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1620,7 +1620,7 @@ struct file *do_filp_open(int dfd, const char *pathname, open_flag |= O_DSYNC; if (!acc_mode) - acc_mode = MAY_OPEN | ACC_MODE(flag); + acc_mode = MAY_OPEN | ACC_MODE(open_flag); /* O_TRUNC implies we need access checks for write permissions */ if (flag & O_TRUNC) -- cgit v1.2.3 From 9850c056559f3633a32d810aaf00ced39437b364 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 13 Jan 2010 15:01:15 -0500 Subject: Fix the -ESTALE handling in do_filp_open() Instead of playing sick games with path saving, cleanups, just retry the entire thing once with LOOKUP_REVAL added. Post-.34 we'll convert all -ESTALE handling in there to that style, rather than playing with many retry loops deep in the call chain. Signed-off-by: Al Viro --- fs/namei.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index d930f1856ed..94a5e60779f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1604,11 +1604,12 @@ struct file *do_filp_open(int dfd, const char *pathname, struct file *filp; struct nameidata nd; int error; - struct path path, save; + struct path path; struct dentry *dir; int count = 0; int will_truncate; int flag = open_to_namei_flags(open_flag); + int force_reval = 0; /* * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only @@ -1660,9 +1661,12 @@ struct file *do_filp_open(int dfd, const char *pathname, /* * Create - we need to know the parent. */ +reval: error = path_init(dfd, pathname, LOOKUP_PARENT, &nd); if (error) return ERR_PTR(error); + if (force_reval) + nd.flags |= LOOKUP_REVAL; error = path_walk(pathname, &nd); if (error) { if (nd.root.mnt) @@ -1854,17 +1858,7 @@ do_link: error = security_inode_follow_link(path.dentry, &nd); if (error) goto exit_dput; - save = nd.path; - path_get(&save); error = __do_follow_link(&path, &nd); - if (error == -ESTALE) { - /* nd.path had been dropped */ - nd.path = save; - path_get(&nd.path); - nd.flags |= LOOKUP_REVAL; - error = __do_follow_link(&path, &nd); - } - path_put(&save); path_put(&path); if (error) { /* Does someone understand code flow here? Or it is only @@ -1874,6 +1868,10 @@ do_link: release_open_intent(&nd); if (nd.root.mnt) path_put(&nd.root); + if (error == -ESTALE && !force_reval) { + force_reval = 1; + goto reval; + } return ERR_PTR(error); } nd.flags &= ~LOOKUP_PARENT; -- cgit v1.2.3 From 8eb988c70e7709b7bd1a69f0ec53d19ac20dea84 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 20 Jan 2010 15:35:41 -0500 Subject: fix ima breakage The "Untangling ima mess, part 2 with counters" patch messed up the counters. Based on conversations with Al Viro, this patch streamlines ima_path_check() by removing the counter maintaince. The counters are now updated independently, from measuring the file, in __dentry_open() and alloc_file() by calling ima_counts_get(). ima_path_check() is called from nfsd and do_filp_open(). It also did not measure all files that should have been measured. Reason: ima_path_check() got bogus value passed as mask. [AV: mea culpa] [AV: add missing nfsd bits] Signed-off-by: Mimi Zohar Signed-off-by: Al Viro --- fs/namei.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index 94a5e60779f..cd77b6375ef 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1736,8 +1736,7 @@ do_last: if (nd.root.mnt) path_put(&nd.root); if (!IS_ERR(filp)) { - error = ima_path_check(&filp->f_path, filp->f_mode & - (MAY_READ | MAY_WRITE | MAY_EXEC)); + error = ima_path_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); @@ -1797,8 +1796,7 @@ ok: } filp = nameidata_to_filp(&nd); if (!IS_ERR(filp)) { - error = ima_path_check(&filp->f_path, filp->f_mode & - (MAY_READ | MAY_WRITE | MAY_EXEC)); + error = ima_path_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); -- cgit v1.2.3 From 9bbb6cad0173e6220f3ac609e26beb48dab3b7cd Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Tue, 26 Jan 2010 17:02:40 -0500 Subject: ima: rename ima_path_check to ima_file_check ima_path_check actually deals with files! call it ima_file_check instead. Signed-off-by: Eric Paris Acked-by: Mimi Zohar Signed-off-by: Al Viro --- fs/namei.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/namei.c') diff --git a/fs/namei.c b/fs/namei.c index cd77b6375ef..d62fdc875f2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1736,7 +1736,7 @@ do_last: if (nd.root.mnt) path_put(&nd.root); if (!IS_ERR(filp)) { - error = ima_path_check(filp, acc_mode); + error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); @@ -1796,7 +1796,7 @@ ok: } filp = nameidata_to_filp(&nd); if (!IS_ERR(filp)) { - error = ima_path_check(filp, acc_mode); + error = ima_file_check(filp, acc_mode); if (error) { fput(filp); filp = ERR_PTR(error); -- cgit v1.2.3