aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorwengang wang <wen.gang.wang@oracle.com>2009-02-09 22:27:51 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-03-18 17:30:50 -0400
commit4ac35c2f794503d3acda20d98e89cf63f6e94332 (patch)
tree00a5afc26c1c59cda2c9b88cb07db5fc26e08bf6 /fs
parente33d1ea60c3a17b8b5c2910b1eef4c1faf0ac450 (diff)
nfsd(v2/v3): fix the failure of creation from HPUX client
sometimes HPUX nfs client sends a create request to linux nfs server(v2/v3). the dump of the request is like: obj_attributes mode: value follows set_it: value follows (1) mode: 00 uid: no value set_it: no value (0) gid: value follows set_it: value follows (1) gid: 8030 size: value follows set_it: value follows (1) size: 0 atime: don't change set_it: don't change (0) mtime: don't change set_it: don't change (0) note that mode is 00(havs no rwx privilege even for the owner) and it requires to set size to 0. as current nfsd(v2/v3) implementation, the server does mainly 2 steps: 1) creates the file in mode specified by calling vfs_create(). 2) sets attributes for the file by calling nfsd_setattr(). at step 2), it finally calls file system specific setattr() function which may fail when checking permission because changing size needs WRITE privilege but it has none since mode is 000. for this case, a new file created, we may simply ignore the request of setting size to 0, so that WRITE privilege is not needed and the open succeeds. Signed-off-by: Wengang Wang <wen.gang.wang@oracle.com> -- vfs.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/vfs.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6e50aaa56ca2..0c076293155d 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1176,6 +1176,21 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp,
1176 return 0; 1176 return 0;
1177} 1177}
1178 1178
1179/* HPUX client sometimes creates a file in mode 000, and sets size to 0.
1180 * setting size to 0 may fail for some specific file systems by the permission
1181 * checking which requires WRITE permission but the mode is 000.
1182 * we ignore the resizing(to 0) on the just new created file, since the size is
1183 * 0 after file created.
1184 *
1185 * call this only after vfs_create() is called.
1186 * */
1187static void
1188nfsd_check_ignore_resizing(struct iattr *iap)
1189{
1190 if ((iap->ia_valid & ATTR_SIZE) && (iap->ia_size == 0))
1191 iap->ia_valid &= ~ATTR_SIZE;
1192}
1193
1179/* 1194/*
1180 * Create a file (regular, directory, device, fifo); UNIX sockets 1195 * Create a file (regular, directory, device, fifo); UNIX sockets
1181 * not yet implemented. 1196 * not yet implemented.
@@ -1271,6 +1286,8 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1271 switch (type) { 1286 switch (type) {
1272 case S_IFREG: 1287 case S_IFREG:
1273 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); 1288 host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
1289 if (!host_err)
1290 nfsd_check_ignore_resizing(iap);
1274 break; 1291 break;
1275 case S_IFDIR: 1292 case S_IFDIR:
1276 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); 1293 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
@@ -1424,6 +1441,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1424 /* setattr will sync the child (or not) */ 1441 /* setattr will sync the child (or not) */
1425 } 1442 }
1426 1443
1444 nfsd_check_ignore_resizing(iap);
1445
1427 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1446 if (createmode == NFS3_CREATE_EXCLUSIVE) {
1428 /* Cram the verifier into atime/mtime */ 1447 /* Cram the verifier into atime/mtime */
1429 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1448 iap->ia_valid = ATTR_MTIME|ATTR_ATIME