mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	NFS: Convert NFSv3 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
							
								
									ac83228a71
								
							
						
					
					
						commit
						264d948ce7
					
				
					 1 changed files with 86 additions and 56 deletions
				
			
		
							
								
								
									
										142
									
								
								fs/nfs/nfs3xdr.c
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								fs/nfs/nfs3xdr.c
									
									
									
									
									
								
							| 
						 | 
					@ -104,6 +104,20 @@ static const umode_t nfs_type2fmt[] = {
 | 
				
			||||||
	[NF3FIFO] = S_IFIFO,
 | 
						[NF3FIFO] = S_IFIFO,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Encode/decode NFSv3 basic data types
 | 
					 * Encode/decode NFSv3 basic data types
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -516,7 +530,8 @@ static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
 | 
				
			||||||
 *		set_mtime	mtime;
 | 
					 *		set_mtime	mtime;
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 | 
					static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr,
 | 
				
			||||||
 | 
							struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct timespec ts;
 | 
						struct timespec ts;
 | 
				
			||||||
	u32 nbytes;
 | 
						u32 nbytes;
 | 
				
			||||||
| 
						 | 
					@ -551,13 +566,13 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (attr->ia_valid & ATTR_UID) {
 | 
						if (attr->ia_valid & ATTR_UID) {
 | 
				
			||||||
		*p++ = xdr_one;
 | 
							*p++ = xdr_one;
 | 
				
			||||||
		*p++ = cpu_to_be32(from_kuid(&init_user_ns, attr->ia_uid));
 | 
							*p++ = cpu_to_be32(from_kuid_munged(userns, attr->ia_uid));
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		*p++ = xdr_zero;
 | 
							*p++ = xdr_zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (attr->ia_valid & ATTR_GID) {
 | 
						if (attr->ia_valid & ATTR_GID) {
 | 
				
			||||||
		*p++ = xdr_one;
 | 
							*p++ = xdr_one;
 | 
				
			||||||
		*p++ = cpu_to_be32(from_kgid(&init_user_ns, attr->ia_gid));
 | 
							*p++ = cpu_to_be32(from_kgid_munged(userns, attr->ia_gid));
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		*p++ = xdr_zero;
 | 
							*p++ = xdr_zero;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -606,7 +621,8 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
 | 
				
			||||||
 *		nfstime3	ctime;
 | 
					 *		nfstime3	ctime;
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
					static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 | 
				
			||||||
 | 
							struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	umode_t fmode;
 | 
						umode_t fmode;
 | 
				
			||||||
	__be32 *p;
 | 
						__be32 *p;
 | 
				
			||||||
| 
						 | 
					@ -619,10 +635,10 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
 | 
						fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
 | 
				
			||||||
	fattr->nlink = 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))
 | 
						if (!uid_valid(fattr->uid))
 | 
				
			||||||
		goto out_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))
 | 
						if (!gid_valid(fattr->gid))
 | 
				
			||||||
		goto out_gid;
 | 
							goto out_gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -659,7 +675,8 @@ static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
				
			||||||
 *		void;
 | 
					 *		void;
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
					static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 | 
				
			||||||
 | 
							struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	__be32 *p;
 | 
						__be32 *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -667,7 +684,7 @@ static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
				
			||||||
	if (unlikely(!p))
 | 
						if (unlikely(!p))
 | 
				
			||||||
		return -EIO;
 | 
							return -EIO;
 | 
				
			||||||
	if (*p != xdr_zero)
 | 
						if (*p != xdr_zero)
 | 
				
			||||||
		return decode_fattr3(xdr, fattr);
 | 
							return decode_fattr3(xdr, fattr, userns);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -728,14 +745,15 @@ static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
 | 
					static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr,
 | 
				
			||||||
 | 
							struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = decode_pre_op_attr(xdr, fattr);
 | 
						error = decode_pre_op_attr(xdr, fattr);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, fattr);
 | 
						error = decode_post_op_attr(xdr, fattr, userns);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -837,7 +855,7 @@ static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct nfs3_sattrargs *args = data;
 | 
						const struct nfs3_sattrargs *args = data;
 | 
				
			||||||
	encode_nfs_fh3(xdr, args->fh);
 | 
						encode_nfs_fh3(xdr, args->fh);
 | 
				
			||||||
	encode_sattr3(xdr, args->sattr);
 | 
						encode_sattr3(xdr, args->sattr, rpc_rqst_userns(req));
 | 
				
			||||||
	encode_sattrguard3(xdr, args);
 | 
						encode_sattrguard3(xdr, args);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -998,13 +1016,14 @@ static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void encode_createhow3(struct xdr_stream *xdr,
 | 
					static void encode_createhow3(struct xdr_stream *xdr,
 | 
				
			||||||
			      const struct nfs3_createargs *args)
 | 
								      const struct nfs3_createargs *args,
 | 
				
			||||||
 | 
								      struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	encode_uint32(xdr, args->createmode);
 | 
						encode_uint32(xdr, args->createmode);
 | 
				
			||||||
	switch (args->createmode) {
 | 
						switch (args->createmode) {
 | 
				
			||||||
	case NFS3_CREATE_UNCHECKED:
 | 
						case NFS3_CREATE_UNCHECKED:
 | 
				
			||||||
	case NFS3_CREATE_GUARDED:
 | 
						case NFS3_CREATE_GUARDED:
 | 
				
			||||||
		encode_sattr3(xdr, args->sattr);
 | 
							encode_sattr3(xdr, args->sattr, userns);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NFS3_CREATE_EXCLUSIVE:
 | 
						case NFS3_CREATE_EXCLUSIVE:
 | 
				
			||||||
		encode_createverf3(xdr, args->verifier);
 | 
							encode_createverf3(xdr, args->verifier);
 | 
				
			||||||
| 
						 | 
					@ -1021,7 +1040,7 @@ static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
 | 
				
			||||||
	const struct nfs3_createargs *args = data;
 | 
						const struct nfs3_createargs *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
						encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
				
			||||||
	encode_createhow3(xdr, args);
 | 
						encode_createhow3(xdr, args, rpc_rqst_userns(req));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1039,7 +1058,7 @@ static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
 | 
				
			||||||
	const struct nfs3_mkdirargs *args = data;
 | 
						const struct nfs3_mkdirargs *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
						encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
				
			||||||
	encode_sattr3(xdr, args->sattr);
 | 
						encode_sattr3(xdr, args->sattr, rpc_rqst_userns(req));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1056,11 +1075,12 @@ static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void encode_symlinkdata3(struct xdr_stream *xdr,
 | 
					static void encode_symlinkdata3(struct xdr_stream *xdr,
 | 
				
			||||||
				const void *data)
 | 
									const void *data,
 | 
				
			||||||
 | 
									struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct nfs3_symlinkargs *args = data;
 | 
						const struct nfs3_symlinkargs *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encode_sattr3(xdr, args->sattr);
 | 
						encode_sattr3(xdr, args->sattr, userns);
 | 
				
			||||||
	encode_nfspath3(xdr, args->pages, args->pathlen);
 | 
						encode_nfspath3(xdr, args->pages, args->pathlen);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1071,7 +1091,7 @@ static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
 | 
				
			||||||
	const struct nfs3_symlinkargs *args = data;
 | 
						const struct nfs3_symlinkargs *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
 | 
						encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
 | 
				
			||||||
	encode_symlinkdata3(xdr, args);
 | 
						encode_symlinkdata3(xdr, args, rpc_rqst_userns(req));
 | 
				
			||||||
	xdr->buf->flags |= XDRBUF_WRITE;
 | 
						xdr->buf->flags |= XDRBUF_WRITE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1100,24 +1120,26 @@ static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void encode_devicedata3(struct xdr_stream *xdr,
 | 
					static void encode_devicedata3(struct xdr_stream *xdr,
 | 
				
			||||||
			       const struct nfs3_mknodargs *args)
 | 
								       const struct nfs3_mknodargs *args,
 | 
				
			||||||
 | 
								       struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	encode_sattr3(xdr, args->sattr);
 | 
						encode_sattr3(xdr, args->sattr, userns);
 | 
				
			||||||
	encode_specdata3(xdr, args->rdev);
 | 
						encode_specdata3(xdr, args->rdev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void encode_mknoddata3(struct xdr_stream *xdr,
 | 
					static void encode_mknoddata3(struct xdr_stream *xdr,
 | 
				
			||||||
			      const struct nfs3_mknodargs *args)
 | 
								      const struct nfs3_mknodargs *args,
 | 
				
			||||||
 | 
								      struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	encode_ftype3(xdr, args->type);
 | 
						encode_ftype3(xdr, args->type);
 | 
				
			||||||
	switch (args->type) {
 | 
						switch (args->type) {
 | 
				
			||||||
	case NF3CHR:
 | 
						case NF3CHR:
 | 
				
			||||||
	case NF3BLK:
 | 
						case NF3BLK:
 | 
				
			||||||
		encode_devicedata3(xdr, args);
 | 
							encode_devicedata3(xdr, args, userns);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NF3SOCK:
 | 
						case NF3SOCK:
 | 
				
			||||||
	case NF3FIFO:
 | 
						case NF3FIFO:
 | 
				
			||||||
		encode_sattr3(xdr, args->sattr);
 | 
							encode_sattr3(xdr, args->sattr, userns);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NF3REG:
 | 
						case NF3REG:
 | 
				
			||||||
	case NF3DIR:
 | 
						case NF3DIR:
 | 
				
			||||||
| 
						 | 
					@ -1134,7 +1156,7 @@ static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
 | 
				
			||||||
	const struct nfs3_mknodargs *args = data;
 | 
						const struct nfs3_mknodargs *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
						encode_diropargs3(xdr, args->fh, args->name, args->len);
 | 
				
			||||||
	encode_mknoddata3(xdr, args);
 | 
						encode_mknoddata3(xdr, args, rpc_rqst_userns(req));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -1379,7 +1401,7 @@ static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
		goto out_default;
 | 
							goto out_default;
 | 
				
			||||||
	error = decode_fattr3(xdr, result);
 | 
						error = decode_fattr3(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
| 
						 | 
					@ -1414,7 +1436,7 @@ static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result);
 | 
						error = decode_wcc_data(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1449,6 +1471,7 @@ static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
 | 
				
			||||||
				   struct xdr_stream *xdr,
 | 
									   struct xdr_stream *xdr,
 | 
				
			||||||
				   void *data)
 | 
									   void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct user_namespace *userns = rpc_rqst_userns(req);
 | 
				
			||||||
	struct nfs3_diropres *result = data;
 | 
						struct nfs3_diropres *result = data;
 | 
				
			||||||
	enum nfs_stat status;
 | 
						enum nfs_stat status;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
| 
						 | 
					@ -1461,14 +1484,14 @@ static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfs_fh3(xdr, result->fh);
 | 
						error = decode_nfs_fh3(xdr, result->fh);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->dir_attr);
 | 
						error = decode_post_op_attr(xdr, result->dir_attr, userns);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->dir_attr);
 | 
						error = decode_post_op_attr(xdr, result->dir_attr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	return nfs3_stat_to_errno(status);
 | 
						return nfs3_stat_to_errno(status);
 | 
				
			||||||
| 
						 | 
					@ -1504,7 +1527,7 @@ static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1545,7 +1568,7 @@ static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result);
 | 
						error = decode_post_op_attr(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1623,7 +1646,7 @@ static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	result->op_status = status;
 | 
						result->op_status = status;
 | 
				
			||||||
| 
						 | 
					@ -1694,7 +1717,7 @@ static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->fattr);
 | 
						error = decode_wcc_data(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	result->op_status = status;
 | 
						result->op_status = status;
 | 
				
			||||||
| 
						 | 
					@ -1728,14 +1751,15 @@ static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
 *	};
 | 
					 *	};
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int decode_create3resok(struct xdr_stream *xdr,
 | 
					static int decode_create3resok(struct xdr_stream *xdr,
 | 
				
			||||||
			       struct nfs3_diropres *result)
 | 
								       struct nfs3_diropres *result,
 | 
				
			||||||
 | 
								       struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = decode_post_op_fh3(xdr, result->fh);
 | 
						error = decode_post_op_fh3(xdr, result->fh);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	/* The server isn't required to return a file handle.
 | 
						/* The server isn't required to return a file handle.
 | 
				
			||||||
| 
						 | 
					@ -1744,7 +1768,7 @@ static int decode_create3resok(struct xdr_stream *xdr,
 | 
				
			||||||
	 * values for the new object. */
 | 
						 * values for the new object. */
 | 
				
			||||||
	if (result->fh->size == 0)
 | 
						if (result->fh->size == 0)
 | 
				
			||||||
		result->fattr->valid = 0;
 | 
							result->fattr->valid = 0;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->dir_attr);
 | 
						error = decode_wcc_data(xdr, result->dir_attr, userns);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1753,6 +1777,7 @@ static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
 | 
				
			||||||
				   struct xdr_stream *xdr,
 | 
									   struct xdr_stream *xdr,
 | 
				
			||||||
				   void *data)
 | 
									   void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct user_namespace *userns = rpc_rqst_userns(req);
 | 
				
			||||||
	struct nfs3_diropres *result = data;
 | 
						struct nfs3_diropres *result = data;
 | 
				
			||||||
	enum nfs_stat status;
 | 
						enum nfs_stat status;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
| 
						 | 
					@ -1762,11 +1787,11 @@ static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
		goto out_default;
 | 
							goto out_default;
 | 
				
			||||||
	error = decode_create3resok(xdr, result);
 | 
						error = decode_create3resok(xdr, result, userns);
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->dir_attr);
 | 
						error = decode_wcc_data(xdr, result->dir_attr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	return nfs3_stat_to_errno(status);
 | 
						return nfs3_stat_to_errno(status);
 | 
				
			||||||
| 
						 | 
					@ -1801,7 +1826,7 @@ static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->dir_attr);
 | 
						error = decode_wcc_data(xdr, result->dir_attr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1836,6 +1861,7 @@ static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
 | 
				
			||||||
				   struct xdr_stream *xdr,
 | 
									   struct xdr_stream *xdr,
 | 
				
			||||||
				   void *data)
 | 
									   void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct user_namespace *userns = rpc_rqst_userns(req);
 | 
				
			||||||
	struct nfs_renameres *result = data;
 | 
						struct nfs_renameres *result = data;
 | 
				
			||||||
	enum nfs_stat status;
 | 
						enum nfs_stat status;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
| 
						 | 
					@ -1843,10 +1869,10 @@ static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->old_fattr);
 | 
						error = decode_wcc_data(xdr, result->old_fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->new_fattr);
 | 
						error = decode_wcc_data(xdr, result->new_fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1880,6 +1906,7 @@ static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
 | 
				
			||||||
static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
					static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
				 void *data)
 | 
									 void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct user_namespace *userns = rpc_rqst_userns(req);
 | 
				
			||||||
	struct nfs3_linkres *result = data;
 | 
						struct nfs3_linkres *result = data;
 | 
				
			||||||
	enum nfs_stat status;
 | 
						enum nfs_stat status;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
| 
						 | 
					@ -1887,10 +1914,10 @@ static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->dir_attr);
 | 
						error = decode_wcc_data(xdr, result->dir_attr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -1939,6 +1966,7 @@ static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
 | 
				
			||||||
int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 | 
					int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 | 
				
			||||||
		       bool plus)
 | 
							       bool plus)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct user_namespace *userns = rpc_userns(entry->server->client);
 | 
				
			||||||
	struct nfs_entry old = *entry;
 | 
						struct nfs_entry old = *entry;
 | 
				
			||||||
	__be32 *p;
 | 
						__be32 *p;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
| 
						 | 
					@ -1973,7 +2001,7 @@ int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (plus) {
 | 
						if (plus) {
 | 
				
			||||||
		entry->fattr->valid = 0;
 | 
							entry->fattr->valid = 0;
 | 
				
			||||||
		error = decode_post_op_attr(xdr, entry->fattr);
 | 
							error = decode_post_op_attr(xdr, entry->fattr, userns);
 | 
				
			||||||
		if (unlikely(error))
 | 
							if (unlikely(error))
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
		if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
 | 
							if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
 | 
				
			||||||
| 
						 | 
					@ -2045,11 +2073,12 @@ static int decode_dirlist3(struct xdr_stream *xdr)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int decode_readdir3resok(struct xdr_stream *xdr,
 | 
					static int decode_readdir3resok(struct xdr_stream *xdr,
 | 
				
			||||||
				struct nfs3_readdirres *result)
 | 
									struct nfs3_readdirres *result,
 | 
				
			||||||
 | 
									struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->dir_attr);
 | 
						error = decode_post_op_attr(xdr, result->dir_attr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	/* XXX: do we need to check if result->verf != NULL ? */
 | 
						/* XXX: do we need to check if result->verf != NULL ? */
 | 
				
			||||||
| 
						 | 
					@ -2074,11 +2103,11 @@ static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
		goto out_default;
 | 
							goto out_default;
 | 
				
			||||||
	error = decode_readdir3resok(xdr, result);
 | 
						error = decode_readdir3resok(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->dir_attr);
 | 
						error = decode_post_op_attr(xdr, result->dir_attr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	return nfs3_stat_to_errno(status);
 | 
						return nfs3_stat_to_errno(status);
 | 
				
			||||||
| 
						 | 
					@ -2138,7 +2167,7 @@ static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -2212,7 +2241,7 @@ static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -2273,7 +2302,7 @@ static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
| 
						 | 
					@ -2315,7 +2344,7 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
 | 
				
			||||||
	error = decode_nfsstat3(xdr, &status);
 | 
						error = decode_nfsstat3(xdr, &status);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_wcc_data(xdr, result->fattr);
 | 
						error = decode_wcc_data(xdr, result->fattr, rpc_rqst_userns(req));
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	result->op_status = status;
 | 
						result->op_status = status;
 | 
				
			||||||
| 
						 | 
					@ -2331,14 +2360,15 @@ static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
 | 
				
			||||||
#ifdef CONFIG_NFS_V3_ACL
 | 
					#ifdef CONFIG_NFS_V3_ACL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int decode_getacl3resok(struct xdr_stream *xdr,
 | 
					static inline int decode_getacl3resok(struct xdr_stream *xdr,
 | 
				
			||||||
				      struct nfs3_getaclres *result)
 | 
									      struct nfs3_getaclres *result,
 | 
				
			||||||
 | 
									      struct user_namespace *userns)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct posix_acl **acl;
 | 
						struct posix_acl **acl;
 | 
				
			||||||
	unsigned int *aclcnt;
 | 
						unsigned int *aclcnt;
 | 
				
			||||||
	size_t hdrlen;
 | 
						size_t hdrlen;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result->fattr);
 | 
						error = decode_post_op_attr(xdr, result->fattr, userns);
 | 
				
			||||||
	if (unlikely(error))
 | 
						if (unlikely(error))
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	error = decode_uint32(xdr, &result->mask);
 | 
						error = decode_uint32(xdr, &result->mask);
 | 
				
			||||||
| 
						 | 
					@ -2386,7 +2416,7 @@ static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
		goto out_default;
 | 
							goto out_default;
 | 
				
			||||||
	error = decode_getacl3resok(xdr, result);
 | 
						error = decode_getacl3resok(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
| 
						 | 
					@ -2405,7 +2435,7 @@ static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	if (status != NFS3_OK)
 | 
						if (status != NFS3_OK)
 | 
				
			||||||
		goto out_default;
 | 
							goto out_default;
 | 
				
			||||||
	error = decode_post_op_attr(xdr, result);
 | 
						error = decode_post_op_attr(xdr, result, rpc_rqst_userns(req));
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
	return error;
 | 
						return error;
 | 
				
			||||||
out_default:
 | 
					out_default:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue