X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=fs%2Fnfsd%2Fnfsfh.c;h=7011d62acfc8dd3516b52961ad598a8371fcc08d;hb=a7fa2baf8e2a6c0eb0a21f75e919c226179e8ff4;hp=739dd3c5c3b2bc0871587de2d07736fd902c53b9;hpb=e63340ae6b6205fef26b40a75673d1c9c0c8bb90;p=mv-sheeva.git diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 739dd3c5c3b..7011d62acfc 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -15,10 +15,12 @@ #include #include #include +#include #include #include #include +#include #include #define NFSDDBG_FACILITY NFSDDBG_FH @@ -27,10 +29,6 @@ static int nfsd_nr_verified; static int nfsd_nr_put; -extern struct export_operations export_op_default; - -#define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun) - /* * our acceptability function. * if NOSUBTREECHECK, accept anything @@ -123,8 +121,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) int data_left = fh->fh_size/4; error = nfserr_stale; - if (rqstp->rq_client == NULL) - goto out; if (rqstp->rq_vers > 2) error = nfserr_badhandle; if (rqstp->rq_vers == 4 && fh->fh_size == 0) @@ -148,7 +144,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) fh->fh_fsid[1] = fh->fh_fsid[2]; } if ((data_left -= len)<0) goto out; - exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle); + exp = rqst_exp_find(rqstp, fh->fh_fsid_type, datap); datap += len; } else { dev_t xdev; @@ -159,19 +155,17 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) xdev = old_decode_dev(fh->ofh_xdev); xino = u32_to_ino_t(fh->ofh_xino); mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL); - exp = exp_find(rqstp->rq_client, FSID_DEV, tfh, - &rqstp->rq_chandle); + exp = rqst_exp_find(rqstp, FSID_DEV, tfh); } - if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN - || PTR_ERR(exp) == -ETIMEDOUT)) { - error = nfserrno(PTR_ERR(exp)); + error = nfserr_stale; + if (PTR_ERR(exp) == -ENOENT) goto out; - } - error = nfserr_stale; - if (!exp || IS_ERR(exp)) + if (IS_ERR(exp)) { + error = nfserrno(PTR_ERR(exp)); goto out; + } /* Check if the request originated from a secure port. */ error = nfserr_perm; @@ -211,11 +205,9 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) if (fileid_type == 0) dentry = dget(exp->ex_dentry); else { - struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; - dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb, - datap, data_left, - fileid_type, - nfsd_acceptable, exp); + dentry = exportfs_decode_fh(exp->ex_mnt, datap, + data_left, fileid_type, + nfsd_acceptable, exp); } if (dentry == NULL) goto out; @@ -257,8 +249,19 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) if (error) goto out; + if (!(access & MAY_LOCK)) { + /* + * pseudoflavor restrictions are not enforced on NLM, + * which clients virtually always use auth_sys for, + * even while using RPCSEC_GSS for NFS. + */ + error = check_nfsd_access(exp, rqstp); + if (error) + goto out; + } + /* Finally, check access permissions. */ - error = nfsd_permission(exp, dentry, access); + error = nfsd_permission(rqstp, exp, dentry, access); if (error) { dprintk("fh_verify: %s/%s permission failure, " @@ -286,15 +289,13 @@ out: static inline int _fh_update(struct dentry *dentry, struct svc_export *exp, __u32 *datap, int *maxsize) { - struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op; - if (dentry == exp->ex_dentry) { *maxsize = 0; return 0; } - return CALL(nop,encode_fh)(dentry, datap, maxsize, - !(exp->ex_flags&NFSEXP_NOSUBTREECHECK)); + return exportfs_encode_fh(dentry, datap, maxsize, + !(exp->ex_flags & NFSEXP_NOSUBTREECHECK)); } /* @@ -323,7 +324,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, * */ - u8 version = 1; + u8 version; u8 fsid_type = 0; struct inode * inode = dentry->d_inode; struct dentry *parent = dentry->d_parent; @@ -341,15 +342,59 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry, * the reference filehandle (if it is in the same export) * or the export options. */ + retry: + version = 1; if (ref_fh && ref_fh->fh_export == exp) { version = ref_fh->fh_handle.fh_version; - if (version == 0xca) + fsid_type = ref_fh->fh_handle.fh_fsid_type; + + if (ref_fh == fhp) + fh_put(ref_fh); + ref_fh = NULL; + + switch (version) { + case 0xca: fsid_type = FSID_DEV; - else - fsid_type = ref_fh->fh_handle.fh_fsid_type; - /* We know this version/type works for this export - * so there is no need for further checks. + break; + case 1: + break; + default: + goto retry; + } + + /* Need to check that this type works for this + * export point. As the fsid -> filesystem mapping + * was guided by user-space, there is no guarantee + * that the filesystem actually supports that fsid + * type. If it doesn't we loop around again without + * ref_fh set. */ + switch(fsid_type) { + case FSID_DEV: + if (!old_valid_dev(ex_dev)) + goto retry; + /* FALL THROUGH */ + case FSID_MAJOR_MINOR: + case FSID_ENCODE_DEV: + if (!(exp->ex_dentry->d_inode->i_sb->s_type->fs_flags + & FS_REQUIRES_DEV)) + goto retry; + break; + case FSID_NUM: + if (! (exp->ex_flags & NFSEXP_FSID)) + goto retry; + break; + case FSID_UUID8: + case FSID_UUID16: + if (!root_export) + goto retry; + /* fall through */ + case FSID_UUID4_INUM: + case FSID_UUID16_INUM: + if (exp->ex_uuid == NULL) + goto retry; + break; + } } else if (exp->ex_uuid) { if (fhp->fh_maxsize >= 64) { if (root_export) @@ -521,13 +566,23 @@ enum fsid_source fsid_source(struct svc_fh *fhp) case FSID_DEV: case FSID_ENCODE_DEV: case FSID_MAJOR_MINOR: - return FSIDSOURCE_DEV; + if (fhp->fh_export->ex_dentry->d_inode->i_sb->s_type->fs_flags + & FS_REQUIRES_DEV) + return FSIDSOURCE_DEV; + break; case FSID_NUM: - return FSIDSOURCE_FSID; - default: if (fhp->fh_export->ex_flags & NFSEXP_FSID) return FSIDSOURCE_FSID; - else - return FSIDSOURCE_UUID; + break; + default: + break; } + /* either a UUID type filehandle, or the filehandle doesn't + * match the export. + */ + if (fhp->fh_export->ex_flags & NFSEXP_FSID) + return FSIDSOURCE_FSID; + if (fhp->fh_export->ex_uuid) + return FSIDSOURCE_UUID; + return FSIDSOURCE_DEV; }