mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	NFS: Convert NFSv2 to use the container user namespace
When mapping NFS identities, we want to substitute for the uids and gids on the wire as we would for the AUTH_UNIX creds. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
		
							parent
							
								
									58002399da
								
							
						
					
					
						commit
						c207db2f5d
					
				
					 1 changed files with 39 additions and 19 deletions
				
			
		| 
						 | 
				
			
			@ -76,6 +76,20 @@ static int nfs_stat_to_errno(enum nfs_stat);
 | 
			
		|||
 * or decoded inline.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static struct user_namespace *rpc_userns(const struct rpc_clnt *clnt)
 | 
			
		||||
{
 | 
			
		||||
	if (clnt && clnt->cl_cred)
 | 
			
		||||
		return clnt->cl_cred->user_ns;
 | 
			
		||||
	return &init_user_ns;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct user_namespace *rpc_rqst_userns(const struct rpc_rqst *rqstp)
 | 
			
		||||
{
 | 
			
		||||
	if (rqstp->rq_task)
 | 
			
		||||
		return rpc_userns(rqstp->rq_task->tk_client);
 | 
			
		||||
	return &init_user_ns;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	typedef opaque	nfsdata<>;
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +262,8 @@ static __be32 *xdr_decode_time(__be32 *p, struct timespec *timep)
 | 
			
		|||
 *	};
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
			
		||||
static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 | 
			
		||||
		struct user_namespace *userns)
 | 
			
		||||
{
 | 
			
		||||
	u32 rdev, type;
 | 
			
		||||
	__be32 *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -263,10 +278,10 @@ static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
			
		|||
 | 
			
		||||
	fattr->mode = be32_to_cpup(p++);
 | 
			
		||||
	fattr->nlink = be32_to_cpup(p++);
 | 
			
		||||
	fattr->uid = make_kuid(&init_user_ns, be32_to_cpup(p++));
 | 
			
		||||
	fattr->uid = make_kuid(userns, be32_to_cpup(p++));
 | 
			
		||||
	if (!uid_valid(fattr->uid))
 | 
			
		||||
		goto out_uid;
 | 
			
		||||
	fattr->gid = make_kgid(&init_user_ns, be32_to_cpup(p++));
 | 
			
		||||
	fattr->gid = make_kgid(userns, be32_to_cpup(p++));
 | 
			
		||||
	if (!gid_valid(fattr->gid))
 | 
			
		||||
		goto out_gid;
 | 
			
		||||
		
 | 
			
		||||
| 
						 | 
				
			
			@ -321,7 +336,8 @@ static __be32 *xdr_time_not_set(__be32 *p)
 | 
			
		|||
	return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
 | 
			
		||||
static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr,
 | 
			
		||||
		struct user_namespace *userns)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec ts;
 | 
			
		||||
	__be32 *p;
 | 
			
		||||
| 
						 | 
				
			
			@ -333,11 +349,11 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
 | 
			
		|||
	else
 | 
			
		||||
		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 | 
			
		||||
	if (attr->ia_valid & ATTR_UID)
 | 
			
		||||
		*p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
 | 
			
		||||
		*p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
 | 
			
		||||
	else
 | 
			
		||||
		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 | 
			
		||||
	if (attr->ia_valid & ATTR_GID)
 | 
			
		||||
		*p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
 | 
			
		||||
		*p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
 | 
			
		||||
	else
 | 
			
		||||
		*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
 | 
			
		||||
	if (attr->ia_valid & ATTR_SIZE)
 | 
			
		||||
| 
						 | 
				
			
			@ -451,7 +467,8 @@ static int decode_path(struct xdr_stream *xdr)
 | 
			
		|||
 *	};
 | 
			
		||||
 */
 | 
			
		||||
static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
 | 
			
		||||
			   __u32 *op_status)
 | 
			
		||||
			   __u32 *op_status,
 | 
			
		||||
			   struct user_namespace *userns)
 | 
			
		||||
{
 | 
			
		||||
	enum nfs_stat status;
 | 
			
		||||
	int error;
 | 
			
		||||
| 
						 | 
				
			
			@ -463,7 +480,7 @@ static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result,
 | 
			
		|||
		*op_status = status;
 | 
			
		||||
	if (status != NFS_OK)
 | 
			
		||||
		goto out_default;
 | 
			
		||||
	error = decode_fattr(xdr, result);
 | 
			
		||||
	error = decode_fattr(xdr, result, userns);
 | 
			
		||||
out:
 | 
			
		||||
	return error;
 | 
			
		||||
out_default:
 | 
			
		||||
| 
						 | 
				
			
			@ -498,19 +515,21 @@ static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
 | 
			
		|||
 *		void;
 | 
			
		||||
 *	};
 | 
			
		||||
 */
 | 
			
		||||
static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
 | 
			
		||||
static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result,
 | 
			
		||||
		struct user_namespace *userns)
 | 
			
		||||
{
 | 
			
		||||
	int error;
 | 
			
		||||
 | 
			
		||||
	error = decode_fhandle(xdr, result->fh);
 | 
			
		||||
	if (unlikely(error))
 | 
			
		||||
		goto out;
 | 
			
		||||
	error = decode_fattr(xdr, result->fattr);
 | 
			
		||||
	error = decode_fattr(xdr, result->fattr, userns);
 | 
			
		||||
out:
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
 | 
			
		||||
static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result,
 | 
			
		||||
		struct user_namespace *userns)
 | 
			
		||||
{
 | 
			
		||||
	enum nfs_stat status;
 | 
			
		||||
	int error;
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +539,7 @@ static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
 | 
			
		|||
		goto out;
 | 
			
		||||
	if (status != NFS_OK)
 | 
			
		||||
		goto out_default;
 | 
			
		||||
	error = decode_diropok(xdr, result);
 | 
			
		||||
	error = decode_diropok(xdr, result, userns);
 | 
			
		||||
out:
 | 
			
		||||
	return error;
 | 
			
		||||
out_default:
 | 
			
		||||
| 
						 | 
				
			
			@ -559,7 +578,7 @@ static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
 | 
			
		|||
	const struct nfs_sattrargs *args = data;
 | 
			
		||||
 | 
			
		||||
	encode_fhandle(xdr, args->fh);
 | 
			
		||||
	encode_sattr(xdr, args->sattr);
 | 
			
		||||
	encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
 | 
			
		||||
| 
						 | 
				
			
			@ -674,7 +693,7 @@ static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
 | 
			
		|||
	const struct nfs_createargs *args = data;
 | 
			
		||||
 | 
			
		||||
	encode_diropargs(xdr, args->fh, args->name, args->len);
 | 
			
		||||
	encode_sattr(xdr, args->sattr);
 | 
			
		||||
	encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
 | 
			
		||||
| 
						 | 
				
			
			@ -741,7 +760,7 @@ static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
 | 
			
		|||
 | 
			
		||||
	encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
 | 
			
		||||
	encode_path(xdr, args->pages, args->pathlen);
 | 
			
		||||
	encode_sattr(xdr, args->sattr);
 | 
			
		||||
	encode_sattr(xdr, args->sattr, rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -803,13 +822,13 @@ static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		|||
static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		||||
				 void *result)
 | 
			
		||||
{
 | 
			
		||||
	return decode_attrstat(xdr, result, NULL);
 | 
			
		||||
	return decode_attrstat(xdr, result, NULL, rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		||||
				 void *result)
 | 
			
		||||
{
 | 
			
		||||
	return decode_diropres(xdr, result);
 | 
			
		||||
	return decode_diropres(xdr, result, rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -864,7 +883,7 @@ static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		|||
	result->op_status = status;
 | 
			
		||||
	if (status != NFS_OK)
 | 
			
		||||
		goto out_default;
 | 
			
		||||
	error = decode_fattr(xdr, result->fattr);
 | 
			
		||||
	error = decode_fattr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
			
		||||
	if (unlikely(error))
 | 
			
		||||
		goto out;
 | 
			
		||||
	error = decode_nfsdata(xdr, result);
 | 
			
		||||
| 
						 | 
				
			
			@ -881,7 +900,8 @@ static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
			
		|||
 | 
			
		||||
	/* All NFSv2 writes are "file sync" writes */
 | 
			
		||||
	result->verf->committed = NFS_FILE_SYNC;
 | 
			
		||||
	return decode_attrstat(xdr, result->fattr, &result->op_status);
 | 
			
		||||
	return decode_attrstat(xdr, result->fattr, &result->op_status,
 | 
			
		||||
			rpc_rqst_userns(req));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue