Commit ac83228a authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker
Browse files

SUNRPC: Use namespace of listening daemon in the client AUTH_GSS upcall



When the client needs to talk to rpc.gssd, we should ensure that the
uid argument is encoded to match the user namespace of the daemon.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 283ebe3e
Loading
Loading
Loading
Loading
+44 −16
Original line number Diff line number Diff line
@@ -269,6 +269,7 @@ err:
struct gss_upcall_msg {
	refcount_t count;
	kuid_t	uid;
	const char *service_name;
	struct rpc_pipe_msg msg;
	struct list_head list;
	struct gss_auth *auth;
@@ -316,6 +317,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
		gss_put_ctx(gss_msg->ctx);
	rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
	gss_put_auth(gss_msg->auth);
	kfree_const(gss_msg->service_name);
	kfree(gss_msg);
}

@@ -410,10 +412,10 @@ gss_upcall_callback(struct rpc_task *task)
	gss_release_msg(gss_msg);
}

static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg,
			      const struct cred *cred)
{
	struct user_namespace *userns = gss_msg->auth->client->cl_cred ?
		gss_msg->auth->client->cl_cred->user_ns : &init_user_ns;
	struct user_namespace *userns = cred->user_ns;

	uid_t uid = from_kuid_munged(userns, gss_msg->uid);
	memcpy(gss_msg->databuf, &uid, sizeof(uid));
@@ -423,12 +425,24 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
	BUILD_BUG_ON(sizeof(uid) > sizeof(gss_msg->databuf));
}

static ssize_t
gss_v0_upcall(struct file *file, struct rpc_pipe_msg *msg,
		char __user *buf, size_t buflen)
{
	struct gss_upcall_msg *gss_msg = container_of(msg,
						      struct gss_upcall_msg,
						      msg);
	if (msg->copied == 0)
		gss_encode_v0_msg(gss_msg, file->f_cred);
	return rpc_pipe_generic_upcall(file, msg, buf, buflen);
}

static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
				const char *service_name,
				const char *target_name)
				const char *target_name,
				const struct cred *cred)
{
	struct user_namespace *userns = gss_msg->auth->client->cl_cred ?
		gss_msg->auth->client->cl_cred->user_ns : &init_user_ns;
	struct user_namespace *userns = cred->user_ns;
	struct gss_api_mech *mech = gss_msg->auth->mech;
	char *p = gss_msg->databuf;
	size_t buflen = sizeof(gss_msg->databuf);
@@ -496,6 +510,25 @@ out_overflow:
	return -ENOMEM;
}

static ssize_t
gss_v1_upcall(struct file *file, struct rpc_pipe_msg *msg,
		char __user *buf, size_t buflen)
{
	struct gss_upcall_msg *gss_msg = container_of(msg,
						      struct gss_upcall_msg,
						      msg);
	int err;
	if (msg->copied == 0) {
		err = gss_encode_v1_msg(gss_msg,
					gss_msg->service_name,
					gss_msg->auth->target_name,
					file->f_cred);
		if (err)
			return err;
	}
	return rpc_pipe_generic_upcall(file, msg, buf, buflen);
}

static struct gss_upcall_msg *
gss_alloc_msg(struct gss_auth *gss_auth,
		kuid_t uid, const char *service_name)
@@ -518,16 +551,11 @@ gss_alloc_msg(struct gss_auth *gss_auth,
	refcount_set(&gss_msg->count, 1);
	gss_msg->uid = uid;
	gss_msg->auth = gss_auth;
	switch (vers) {
	case 0:
		gss_encode_v0_msg(gss_msg);
		break;
	default:
		err = gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name);
		if (err)
	if (service_name) {
		gss_msg->service_name = kstrdup_const(service_name, GFP_NOFS);
		if (!gss_msg->service_name)
			goto err_put_pipe_version;
	}
	kref_get(&gss_auth->kref);
	return gss_msg;
err_put_pipe_version:
	put_pipe_version(gss_auth->net);
@@ -2120,7 +2148,7 @@ static const struct rpc_credops gss_nullops = {
};

static const struct rpc_pipe_ops gss_upcall_ops_v0 = {
	.upcall		= rpc_pipe_generic_upcall,
	.upcall		= gss_v0_upcall,
	.downcall	= gss_pipe_downcall,
	.destroy_msg	= gss_pipe_destroy_msg,
	.open_pipe	= gss_pipe_open_v0,
@@ -2128,7 +2156,7 @@ static const struct rpc_pipe_ops gss_upcall_ops_v0 = {
};

static const struct rpc_pipe_ops gss_upcall_ops_v1 = {
	.upcall		= rpc_pipe_generic_upcall,
	.upcall		= gss_v1_upcall,
	.downcall	= gss_pipe_downcall,
	.destroy_msg	= gss_pipe_destroy_msg,
	.open_pipe	= gss_pipe_open_v1,