NFS: use secinfo when crossing mountpoints
Subsystems (3)
PATCH v6 4/5 NFS: use secinfo when crossing mountpoints
A submount may use different security than the parent mount does. We should figure out what sec flavor the submount uses at mount time.
Signed-off-by Bryan Schumaker <[email protected]>
--- fs/nfs/inode.c | 8 ++- fs/nfs/internal.h | 7 ++ fs/nfs/namespace.c | 113 ++++++++++++++++++++++++++++++++- fs/nfs/nfs4proc.c | 14 ++++ fs/nfs/nfs4xdr.c | 11 ++-- include/linux/nfs_xdr.h | 1 + net/sunrpc/auth_gss/gss_mech_switch.c | 22 +++++++ 7 files changed, 165 insertions(+), 11 deletions(-)
fs/nfs/inode.c +5 -3
@@ -254,7 +254,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)struct inode *inode =ERR_PTR (-ENOENT );unsigned long hash; -if ((fattr->valid &NFS_ATTR_FATTR_FILEID ) ==0 ) +nfs_attr_check_mountpoint (sb, fattr); + +if ((fattr->valid &NFS_ATTR_FATTR_FILEID ) ==0 && (fattr->valid &NFS_ATTR_FATTR_MOUNTPOINT ) ==0 ) goto out_no_inode;if ((fattr->valid &NFS_ATTR_FATTR_TYPE ) ==0 ) goto out_no_inode;
@@ -298,8 +300,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)if (nfs_server_capable (inode,NFS_CAP_READDIRPLUS ))set_bit (NFS_INO_ADVISE_RDPLUS , &NFS_I (inode)->flags);/* Deal with crossing mountpoints */ -if ((fattr->valid &NFS_ATTR_FATTR_FSID ) - && !nfs_fsid_equal (&NFS_SB (sb)->fsid, &fattr->fsid)) { +if (fattr->valid &NFS_ATTR_FATTR_MOUNTPOINT || + fattr->valid &NFS_ATTR_FATTR_V4_REFERRAL ) {if (fattr->valid &NFS_ATTR_FATTR_V4_REFERRAL ) inode->i_op = &nfs_referral_inode_operations;else
fs/nfs/internal.h +7 -0
@@ -39,6 +39,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp)return 0 ; } +static inline void nfs_attr_check_mountpoint (struct super_block *parent,struct nfs_fattr *fattr) +{ +if (!nfs_fsid_equal (&NFS_SB (parent)->fsid, &fattr->fsid)) + fattr->valid |=NFS_ATTR_FATTR_MOUNTPOINT ; +} +struct nfs_clone_mount {const struct super_block *sb;const struct dentry *dentry;
@@ -214,6 +220,7 @@ extern const u32 nfs41_maxwrite_overhead;/* nfs4proc.c */ #ifdef CONFIG_NFS_V4 extern struct rpc_procinfo nfs4_procedures[]; +void nfs_fixup_secinfo_attributes (struct nfs_fattr *,struct nfs_fh *);#endif extern int nfs4_init_ds_session (struct nfs_client *clp);
fs/nfs/namespace.c +110 -3
165 lines not on this page · raw message
fs/nfs/nfs4proc.c +14 -0
@@ -87,6 +87,8 @@ static int nfs4_map_errors(int err)switch (err) {case -NFS4ERR_RESOURCE :return -EREMOTEIO ; +case -NFS4ERR_WRONGSEC : +return -EPERM ;case -NFS4ERR_BADOWNER :case -NFS4ERR_BADNAME :return -EINVAL ;
@@ -2383,6 +2385,16 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir,return status; } +void nfs_fixup_secinfo_attributes (struct nfs_fattr *fattr,struct nfs_fh *fh) +{ +memset (fh,0 ,sizeof (struct nfs_fh )); + fattr->fsid.major =1 ; + fattr->valid |=NFS_ATTR_FATTR_TYPE |NFS_ATTR_FATTR_MODE | +NFS_ATTR_FATTR_NLINK |NFS_ATTR_FATTR_FSID |NFS_ATTR_FATTR_MOUNTPOINT ; + fattr->mode =S_IFDIR |S_IRUGO |S_IXUGO ; + fattr->nlink =2 ; +} +static int nfs4_proc_lookup (struct rpc_clnt *clnt,struct inode *dir,struct qstr *name,struct nfs_fh *fhandle,struct nfs_fattr *fattr) {
@@ -2392,6 +2404,8 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst err =nfs4_handle_exception (NFS_SERVER (dir),_nfs4_proc_lookup (clnt, dir, name, fhandle, fattr), &exception); +if (err == -EPERM ) +nfs_fixup_secinfo_attributes (fattr, fhandle); }while (exception.retry);return err; }
fs/nfs/nfs4xdr.c +6 -5
@@ -113,7 +113,7 @@ static int nfs4_stat_to_errno(int);#define encode_restorefh_maxsz (op_encode_hdr_maxsz)#define decode_restorefh_maxsz (op_decode_hdr_maxsz)#define encode_fsinfo_maxsz (encode_getattr_maxsz) -#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) +#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 15)#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)#define decode_renew_maxsz (op_decode_hdr_maxsz)#define encode_setclientid_maxsz \
@@ -3038,6 +3038,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)if (unlikely (!p)) goto out_overflow; bitmap[0 ] &= ~FATTR4_WORD0_RDATTR_ERROR ; +return -be32_to_cpup (p); }return 0 ; out_overflow:
@@ -4025,6 +4026,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, fattr->valid |= status; status =decode_attr_error (xdr, bitmap); +if (status == -NFS4ERR_WRONGSEC ) { +nfs_fixup_secinfo_attributes (fattr, fh); + status =0 ; + }if (status <0 ) goto xdr_error;
@@ -6444,10 +6449,6 @@ static struct { { NFS4ERR_SYMLINK, -ELOOP }, { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP }, { NFS4ERR_DEADLOCK, -EDEADLK }, - { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs -* to be handled by a -* middle-layer. -*/ { -1, -EIO } };
include/linux/nfs_xdr.h +1 -0
@@ -82,6 +82,7 @@ struct nfs_fattr {#define NFS_ATTR_FATTR_CHANGE (1U << 17)#define NFS_ATTR_FATTR_PRECHANGE (1U << 18)#define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19)/* NFSv4 referral */ +#define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20)/* Treat as mountpoint */ #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ | NFS_ATTR_FATTR_MODE \
net/sunrpc/auth_gss/gss_mech_switch.c +22 -0
@@ -160,6 +160,28 @@ gss_mech_get_by_name(const char *name)EXPORT_SYMBOL_GPL (gss_mech_get_by_name); +struct gss_api_mech * +gss_mech_get_by_OID (struct xdr_netobj *obj) +{ +struct gss_api_mech *pos, *gm =NULL ; + +spin_lock (®istered_mechs_lock); +list_for_each_entry (pos, ®istered_mechs, gm_list) { +if (obj->len == pos->gm_oid.len) { +if (0 ==memcmp (obj->data, pos->gm_oid.data, obj->len)) { +if (try_module_get (pos->gm_owner)) + gm = pos; +break ; + } + } + } +spin_unlock (®istered_mechs_lock); +return gm; + +} + +EXPORT_SYMBOL_GPL (gss_mech_get_by_OID); +static inline int mech_supports_pseudoflavor (struct gss_api_mech *gm,u32 pseudoflavor) {
Signature · 1 line
1.7.4.1