aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c31
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"
599int 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
1352do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, 1370do_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;