diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index fd0acca5370a..7a2e442623c8 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -168,6 +168,8 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp) | |||
168 | { | 168 | { |
169 | if (d_mountpoint(dentry)) | 169 | if (d_mountpoint(dentry)) |
170 | return 1; | 170 | return 1; |
171 | if (nfsd4_is_junction(dentry)) | ||
172 | return 1; | ||
171 | if (!(exp->ex_flags & NFSEXP_V4ROOT)) | 173 | if (!(exp->ex_flags & NFSEXP_V4ROOT)) |
172 | return 0; | 174 | return 0; |
173 | return dentry->d_inode != NULL; | 175 | return dentry->d_inode != NULL; |
@@ -502,7 +504,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
502 | unsigned int flags = 0; | 504 | unsigned int flags = 0; |
503 | 505 | ||
504 | /* Get inode */ | 506 | /* Get inode */ |
505 | error = fh_verify(rqstp, fhp, 0 /* S_IFREG */, NFSD_MAY_SATTR); | 507 | error = fh_verify(rqstp, fhp, 0, NFSD_MAY_SATTR); |
506 | if (error) | 508 | if (error) |
507 | return error; | 509 | return error; |
508 | 510 | ||
@@ -592,6 +594,22 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac | |||
592 | return error; | 594 | return error; |
593 | } | 595 | } |
594 | 596 | ||
597 | #define NFSD_XATTR_JUNCTION_PREFIX XATTR_TRUSTED_PREFIX "junction." | ||
598 | #define NFSD_XATTR_JUNCTION_TYPE NFSD_XATTR_JUNCTION_PREFIX "type" | ||
599 | int nfsd4_is_junction(struct dentry *dentry) | ||
600 | { | ||
601 | struct inode *inode = dentry->d_inode; | ||
602 | |||
603 | if (inode == NULL) | ||
604 | return 0; | ||
605 | if (inode->i_mode & S_IXUGO) | ||
606 | return 0; | ||
607 | if (!(inode->i_mode & S_ISVTX)) | ||
608 | return 0; | ||
609 | if (vfs_getxattr(dentry, NFSD_XATTR_JUNCTION_TYPE, NULL, 0) <= 0) | ||
610 | return 0; | ||
611 | return 1; | ||
612 | } | ||
595 | #endif /* defined(CONFIG_NFSD_V4) */ | 613 | #endif /* defined(CONFIG_NFSD_V4) */ |
596 | 614 | ||
597 | #ifdef CONFIG_NFSD_V3 | 615 | #ifdef CONFIG_NFSD_V3 |
@@ -1352,7 +1370,7 @@ __be32 | |||
1352 | do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1370 | do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, |
1353 | char *fname, int flen, struct iattr *iap, | 1371 | char *fname, int flen, struct iattr *iap, |
1354 | struct svc_fh *resfhp, int createmode, u32 *verifier, | 1372 | struct svc_fh *resfhp, int createmode, u32 *verifier, |
1355 | int *truncp, int *created) | 1373 | bool *truncp, bool *created) |
1356 | { | 1374 | { |
1357 | struct dentry *dentry, *dchild = NULL; | 1375 | struct dentry *dentry, *dchild = NULL; |
1358 | struct inode *dirp; | 1376 | struct inode *dirp; |
@@ -1632,10 +1650,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1632 | err = fh_verify(rqstp, ffhp, S_IFDIR, NFSD_MAY_CREATE); | 1650 | err = fh_verify(rqstp, ffhp, S_IFDIR, NFSD_MAY_CREATE); |
1633 | if (err) | 1651 | if (err) |
1634 | goto out; | 1652 | goto out; |
1635 | err = fh_verify(rqstp, tfhp, -S_IFDIR, NFSD_MAY_NOP); | 1653 | err = fh_verify(rqstp, tfhp, 0, NFSD_MAY_NOP); |
1636 | if (err) | 1654 | if (err) |
1637 | goto out; | 1655 | goto out; |
1638 | 1656 | err = nfserr_isdir; | |
1657 | if (S_ISDIR(tfhp->fh_dentry->d_inode->i_mode)) | ||
1658 | goto out; | ||
1639 | err = nfserr_perm; | 1659 | err = nfserr_perm; |
1640 | if (!len) | 1660 | if (!len) |
1641 | goto out; | 1661 | goto out; |
@@ -2114,7 +2134,8 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2114 | 2134 | ||
2115 | /* Allow read access to binaries even when mode 111 */ | 2135 | /* Allow read access to binaries even when mode 111 */ |
2116 | if (err == -EACCES && S_ISREG(inode->i_mode) && | 2136 | if (err == -EACCES && S_ISREG(inode->i_mode) && |
2117 | acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) | 2137 | (acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE) || |
2138 | acc == (NFSD_MAY_READ | NFSD_MAY_READ_IF_EXEC))) | ||
2118 | err = inode_permission(inode, MAY_EXEC); | 2139 | err = inode_permission(inode, MAY_EXEC); |
2119 | 2140 | ||
2120 | return err? nfserrno(err) : 0; | 2141 | return err? nfserrno(err) : 0; |