diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-06-10 19:39:41 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-07-09 12:09:14 -0400 |
commit | 659bfcd6dd88919a5ad453f62afbeffcb3106847 (patch) | |
tree | e3996d809e9ae4860a8adac71474e6ea8850c3b5 | |
parent | a486aeda9b2b0d944aecce7871b3186379b898de (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.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 47 | ||||
-rw-r--r-- | fs/nfs/proc.c | 2 |
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 | ||
352 | int | 352 | int |
353 | nfs_setattr(struct dentry *dentry, struct iattr *attr) | 353 | nfs_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 | ||
1142 | static int _nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, | 1142 | static 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 | ||
1180 | static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr, | 1181 | static 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 | |||
1647 | nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | 1649 | nfs4_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); |
1916 | out_putcred: | ||
1917 | put_rpccred(cred); | ||
1919 | out: | 1918 | out: |
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) |