aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2009-05-27 09:31:52 -0400
committerJames Morris <jmorris@namei.org>2009-05-27 19:32:43 -0400
commit14dba5331b90c20588ae6504fea8049c7283028d (patch)
tree55b55dfd413e7dcad4d33dca131cba70e281e41a /fs/nfsd/vfs.c
parent76b0187525f024cb391c8043adf2e359b2adb988 (diff)
integrity: nfsd imbalance bug fix
An nfsd exported file is opened/closed by the kernel causing the integrity imbalance message. Before a file is opened, there normally is permission checking, which is done in inode_permission(). However, as integrity checking requires a dentry and mount point, which is not available in inode_permission(), the integrity (permission) checking must be called separately. In order to detect any missing integrity checking calls, we keep track of file open/closes. ima_path_check() increments these counts and does the integrity (permission) checking. As a result, the number of calls to ima_path_check()/ima_file_free() should be balanced. An extra call to fput(), indicates the file could have been accessed without first calling ima_path_check(). In nfsv3 permission checking is done once, followed by multiple reads, which do an open/close for each read. The integrity (permission) checking call should be in nfsd_permission() after the inode_permission() call, but as there is no correlation between the number of permission checking and open calls, the integrity checking call should not increment the counters, but defer it to when the file is actually opened. This patch adds: - integrity (permission) checking for nfsd exported files in nfsd_permission(). - a call to increment counts for files opened by nfsd. This patch has been updated to return the nfs error types. Signed-off-by: Mimi Zohar <zohar@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6c68ffd6b4bb..81ff0f4de4b7 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -55,6 +55,7 @@
55#include <linux/security.h> 55#include <linux/security.h>
56#endif /* CONFIG_NFSD_V4 */ 56#endif /* CONFIG_NFSD_V4 */
57#include <linux/jhash.h> 57#include <linux/jhash.h>
58#include <linux/ima.h>
58 59
59#include <asm/uaccess.h> 60#include <asm/uaccess.h>
60 61
@@ -735,6 +736,8 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
735 flags, cred); 736 flags, cred);
736 if (IS_ERR(*filp)) 737 if (IS_ERR(*filp))
737 host_err = PTR_ERR(*filp); 738 host_err = PTR_ERR(*filp);
739 else
740 ima_counts_get(*filp);
738out_nfserr: 741out_nfserr:
739 err = nfserrno(host_err); 742 err = nfserrno(host_err);
740out: 743out:
@@ -2024,6 +2027,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2024 struct dentry *dentry, int acc) 2027 struct dentry *dentry, int acc)
2025{ 2028{
2026 struct inode *inode = dentry->d_inode; 2029 struct inode *inode = dentry->d_inode;
2030 struct path path;
2027 int err; 2031 int err;
2028 2032
2029 if (acc == NFSD_MAY_NOP) 2033 if (acc == NFSD_MAY_NOP)
@@ -2096,7 +2100,17 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2096 if (err == -EACCES && S_ISREG(inode->i_mode) && 2100 if (err == -EACCES && S_ISREG(inode->i_mode) &&
2097 acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) 2101 acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE))
2098 err = inode_permission(inode, MAY_EXEC); 2102 err = inode_permission(inode, MAY_EXEC);
2103 if (err)
2104 goto nfsd_out;
2099 2105
2106 /* Do integrity (permission) checking now, but defer incrementing
2107 * IMA counts to the actual file open.
2108 */
2109 path.mnt = exp->ex_path.mnt;
2110 path.dentry = dentry;
2111 err = ima_path_check(&path, acc & (MAY_READ | MAY_WRITE | MAY_EXEC),
2112 IMA_COUNT_LEAVE);
2113nfsd_out:
2100 return err? nfserrno(err) : 0; 2114 return err? nfserrno(err) : 0;
2101} 2115}
2102 2116