aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-06-10 19:39:41 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:14 -0400
commit659bfcd6dd88919a5ad453f62afbeffcb3106847 (patch)
treee3996d809e9ae4860a8adac71474e6ea8850c3b5
parenta486aeda9b2b0d944aecce7871b3186379b898de (diff)
NFS: Fix the ftruncate() credential problem
ftruncate() access checking is supposed to be performed at open() time, just like reads and writes. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/inode.c4
-rw-r--r--fs/nfs/nfs3proc.c2
-rw-r--r--fs/nfs/nfs4proc.c47
-rw-r--r--fs/nfs/proc.c2
4 files changed, 29 insertions, 26 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 596c5d8e86f4..2e4ab4a5e107 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -347,7 +347,7 @@ out_no_inode:
347 goto out; 347 goto out;
348} 348}
349 349
350#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET) 350#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET|ATTR_FILE)
351 351
352int 352int
353nfs_setattr(struct dentry *dentry, struct iattr *attr) 353nfs_setattr(struct dentry *dentry, struct iattr *attr)
@@ -369,7 +369,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
369 369
370 /* Optimization: if the end result is no change, don't RPC */ 370 /* Optimization: if the end result is no change, don't RPC */
371 attr->ia_valid &= NFS_VALID_ATTRS; 371 attr->ia_valid &= NFS_VALID_ATTRS;
372 if (attr->ia_valid == 0) 372 if ((attr->ia_valid & ~ATTR_FILE) == 0)
373 return 0; 373 return 0;
374 374
375 lock_kernel(); 375 lock_kernel();
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index cf7d4e5927d6..b9c2d995332b 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -129,6 +129,8 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
129 int status; 129 int status;
130 130
131 dprintk("NFS call setattr\n"); 131 dprintk("NFS call setattr\n");
132 if (sattr->ia_valid & ATTR_FILE)
133 msg.rpc_cred = nfs_file_cred(sattr->ia_file);
132 nfs_fattr_init(fattr); 134 nfs_fattr_init(fattr);
133 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 135 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
134 if (status == 0) 136 if (status == 0)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 26fbeb3467cb..31a7e4c54a12 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1139,8 +1139,9 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int
1139 return res; 1139 return res;
1140} 1140}
1141 1141
1142static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, 1142static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1143 struct iattr *sattr, struct nfs4_state *state) 1143 struct nfs_fattr *fattr, struct iattr *sattr,
1144 struct nfs4_state *state)
1144{ 1145{
1145 struct nfs_server *server = NFS_SERVER(inode); 1146 struct nfs_server *server = NFS_SERVER(inode);
1146 struct nfs_setattrargs arg = { 1147 struct nfs_setattrargs arg = {
@@ -1154,9 +1155,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1154 .server = server, 1155 .server = server,
1155 }; 1156 };
1156 struct rpc_message msg = { 1157 struct rpc_message msg = {
1157 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], 1158 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
1158 .rpc_argp = &arg, 1159 .rpc_argp = &arg,
1159 .rpc_resp = &res, 1160 .rpc_resp = &res,
1161 .rpc_cred = cred,
1160 }; 1162 };
1161 unsigned long timestamp = jiffies; 1163 unsigned long timestamp = jiffies;
1162 int status; 1164 int status;
@@ -1166,7 +1168,6 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1166 if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { 1168 if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
1167 /* Use that stateid */ 1169 /* Use that stateid */
1168 } else if (state != NULL) { 1170 } else if (state != NULL) {
1169 msg.rpc_cred = state->owner->so_cred;
1170 nfs4_copy_stateid(&arg.stateid, state, current->files); 1171 nfs4_copy_stateid(&arg.stateid, state, current->files);
1171 } else 1172 } else
1172 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); 1173 memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
@@ -1177,15 +1178,16 @@ static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1177 return status; 1178 return status;
1178} 1179}
1179 1180
1180static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, 1181static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1181 struct iattr *sattr, struct nfs4_state *state) 1182 struct nfs_fattr *fattr, struct iattr *sattr,
1183 struct nfs4_state *state)
1182{ 1184{
1183 struct nfs_server *server = NFS_SERVER(inode); 1185 struct nfs_server *server = NFS_SERVER(inode);
1184 struct nfs4_exception exception = { }; 1186 struct nfs4_exception exception = { };
1185 int err; 1187 int err;
1186 do { 1188 do {
1187 err = nfs4_handle_exception(server, 1189 err = nfs4_handle_exception(server,
1188 _nfs4_do_setattr(inode, fattr, sattr, state), 1190 _nfs4_do_setattr(inode, cred, fattr, sattr, state),
1189 &exception); 1191 &exception);
1190 } while (exception.retry); 1192 } while (exception.retry);
1191 return err; 1193 return err;
@@ -1647,29 +1649,25 @@ static int
1647nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, 1649nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
1648 struct iattr *sattr) 1650 struct iattr *sattr)
1649{ 1651{
1650 struct rpc_cred *cred;
1651 struct inode *inode = dentry->d_inode; 1652 struct inode *inode = dentry->d_inode;
1652 struct nfs_open_context *ctx; 1653 struct rpc_cred *cred = NULL;
1653 struct nfs4_state *state = NULL; 1654 struct nfs4_state *state = NULL;
1654 int status; 1655 int status;
1655 1656
1656 nfs_fattr_init(fattr); 1657 nfs_fattr_init(fattr);
1657 1658
1658 cred = rpc_lookup_cred();
1659 if (IS_ERR(cred))
1660 return PTR_ERR(cred);
1661
1662 /* Search for an existing open(O_WRITE) file */ 1659 /* Search for an existing open(O_WRITE) file */
1663 ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); 1660 if (sattr->ia_valid & ATTR_FILE) {
1664 if (ctx != NULL) 1661 struct nfs_open_context *ctx;
1662
1663 ctx = nfs_file_open_context(sattr->ia_file);
1664 cred = ctx->cred;
1665 state = ctx->state; 1665 state = ctx->state;
1666 }
1666 1667
1667 status = nfs4_do_setattr(inode, fattr, sattr, state); 1668 status = nfs4_do_setattr(inode, cred, fattr, sattr, state);
1668 if (status == 0) 1669 if (status == 0)
1669 nfs_setattr_update_inode(inode, sattr); 1670 nfs_setattr_update_inode(inode, sattr);
1670 if (ctx != NULL)
1671 put_nfs_open_context(ctx);
1672 put_rpccred(cred);
1673 return status; 1671 return status;
1674} 1672}
1675 1673
@@ -1897,17 +1895,16 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1897 goto out; 1895 goto out;
1898 } 1896 }
1899 state = nfs4_do_open(dir, &path, flags, sattr, cred); 1897 state = nfs4_do_open(dir, &path, flags, sattr, cred);
1900 put_rpccred(cred);
1901 d_drop(dentry); 1898 d_drop(dentry);
1902 if (IS_ERR(state)) { 1899 if (IS_ERR(state)) {
1903 status = PTR_ERR(state); 1900 status = PTR_ERR(state);
1904 goto out; 1901 goto out_putcred;
1905 } 1902 }
1906 d_add(dentry, igrab(state->inode)); 1903 d_add(dentry, igrab(state->inode));
1907 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1904 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1908 if (flags & O_EXCL) { 1905 if (flags & O_EXCL) {
1909 struct nfs_fattr fattr; 1906 struct nfs_fattr fattr;
1910 status = nfs4_do_setattr(state->inode, &fattr, sattr, state); 1907 status = nfs4_do_setattr(state->inode, cred, &fattr, sattr, state);
1911 if (status == 0) 1908 if (status == 0)
1912 nfs_setattr_update_inode(state->inode, sattr); 1909 nfs_setattr_update_inode(state->inode, sattr);
1913 nfs_post_op_update_inode(state->inode, &fattr); 1910 nfs_post_op_update_inode(state->inode, &fattr);
@@ -1916,6 +1913,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1916 status = nfs4_intent_set_file(nd, &path, state); 1913 status = nfs4_intent_set_file(nd, &path, state);
1917 else 1914 else
1918 nfs4_close_sync(&path, state, flags); 1915 nfs4_close_sync(&path, state, flags);
1916out_putcred:
1917 put_rpccred(cred);
1919out: 1918out:
1920 return status; 1919 return status;
1921} 1920}
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 5c35b02857f3..c7605587d0eb 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -129,6 +129,8 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
129 sattr->ia_mode &= S_IALLUGO; 129 sattr->ia_mode &= S_IALLUGO;
130 130
131 dprintk("NFS call setattr\n"); 131 dprintk("NFS call setattr\n");
132 if (sattr->ia_valid & ATTR_FILE)
133 msg.rpc_cred = nfs_file_cred(sattr->ia_file);
132 nfs_fattr_init(fattr); 134 nfs_fattr_init(fattr);
133 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); 135 status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
134 if (status == 0) 136 if (status == 0)