Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19172284 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

RPCSEC_GSS: Switch auth_gss to use the new framework for pipefs dentries

parent 6739ffb7
Loading
Loading
Loading
Loading
+92 −89
Original line number Original line Diff line number Diff line
@@ -71,6 +71,13 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
 * using integrity (two 4-byte integers): */
 * using integrity (two 4-byte integers): */
#define GSS_VERF_SLACK		100
#define GSS_VERF_SLACK		100


struct gss_pipe {
	struct rpc_pipe_dir_object pdo;
	struct rpc_pipe *pipe;
	struct rpc_clnt *clnt;
	const char *name;
};

struct gss_auth {
struct gss_auth {
	struct kref kref;
	struct kref kref;
	struct rpc_auth rpc_auth;
	struct rpc_auth rpc_auth;
@@ -84,7 +91,7 @@ struct gss_auth {
	 * mechanism (for example, "krb5") and exists for
	 * mechanism (for example, "krb5") and exists for
	 * backwards-compatibility with older gssd's.
	 * backwards-compatibility with older gssd's.
	 */
	 */
	struct rpc_pipe *pipe[2];
	struct gss_pipe *gss_pipe[2];
	const char *target_name;
	const char *target_name;
};
};


@@ -456,7 +463,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
		kfree(gss_msg);
		kfree(gss_msg);
		return ERR_PTR(vers);
		return ERR_PTR(vers);
	}
	}
	gss_msg->pipe = gss_auth->pipe[vers];
	gss_msg->pipe = gss_auth->gss_pipe[vers]->pipe;
	INIT_LIST_HEAD(&gss_msg->list);
	INIT_LIST_HEAD(&gss_msg->list);
	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
	rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
	init_waitqueue_head(&gss_msg->waitqueue);
	init_waitqueue_head(&gss_msg->waitqueue);
@@ -791,85 +798,83 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
	}
	}
}
}


static void gss_pipes_dentries_destroy(struct rpc_auth *auth)
static void gss_pipe_dentry_destroy(struct dentry *dir,
		struct rpc_pipe_dir_object *pdo)
{
{
	struct gss_auth *gss_auth;
	struct gss_pipe *gss_pipe = pdo->pdo_data;
	struct rpc_pipe *pipe = gss_pipe->pipe;


	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
	if (pipe->dentry != NULL) {
	if (gss_auth->pipe[0]->dentry) {
		rpc_unlink(pipe->dentry);
		rpc_unlink(gss_auth->pipe[0]->dentry);
		pipe->dentry = NULL;
		gss_auth->pipe[0]->dentry = NULL;
	}
	if (gss_auth->pipe[1]->dentry) {
		rpc_unlink(gss_auth->pipe[1]->dentry);
		gss_auth->pipe[1]->dentry = NULL;
	}
	}
}
}


static int gss_pipes_dentries_create(struct rpc_auth *auth)
static int gss_pipe_dentry_create(struct dentry *dir,
		struct rpc_pipe_dir_object *pdo)
{
{
	int err;
	struct gss_pipe *p = pdo->pdo_data;
	struct gss_auth *gss_auth;
	struct rpc_clnt *clnt;
	struct dentry *dentry;
	struct dentry *dentry;


	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
	dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe);
	clnt = gss_auth->client;
	if (IS_ERR(dentry))

		return PTR_ERR(dentry);
	dentry = rpc_mkpipe_dentry(clnt->cl_dentry, "gssd",
	p->pipe->dentry = dentry;
			clnt, gss_auth->pipe[1]);
	if (IS_ERR(dentry)) {
		err = PTR_ERR(dentry);
		goto err;
	}
	gss_auth->pipe[1]->dentry = dentry;
	dentry = rpc_mkpipe_dentry(clnt->cl_dentry, gss_auth->mech->gm_name,
			clnt, gss_auth->pipe[0]);
	if (IS_ERR(dentry)) {
		err = PTR_ERR(dentry);
		goto err_unlink_pipe_1;
	}
	return 0;
	return 0;

err_unlink_pipe_1:
	rpc_unlink(gss_auth->pipe[1]->dentry);
	gss_auth->pipe[1]->dentry = NULL;
err:
	return err;
}
}


static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt,
static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
					   struct rpc_auth *auth)
	.create = gss_pipe_dentry_create,
	.destroy = gss_pipe_dentry_destroy,
};

static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
		const char *name,
		const struct rpc_pipe_ops *upcall_ops)
{
{
	struct gss_auth *gss_auth = container_of(auth, struct gss_auth,
	struct net *net = rpc_net_ns(clnt);
			rpc_auth);
	struct gss_pipe *p;
	struct net *net = gss_auth->net;
	int err = -ENOMEM;
	struct super_block *sb;


	sb = rpc_get_sb_net(net);
	p = kmalloc(sizeof(*p), GFP_KERNEL);
	if (sb) {
	if (p == NULL)
		if (clnt->cl_dentry)
		goto err;
			gss_pipes_dentries_destroy(auth);
	p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
		rpc_put_sb_net(net);
	if (IS_ERR(p->pipe)) {
	}
		err = PTR_ERR(p->pipe);
		goto err_free_gss_pipe;
	}
	p->name = name;
	p->clnt = clnt;
	rpc_init_pipe_dir_object(&p->pdo,
			&gss_pipe_dir_object_ops,
			p);
	err = rpc_add_pipe_dir_object(net, &clnt->cl_pipedir_objects, &p->pdo);
	if (!err)
		return p;
	rpc_destroy_pipe_data(p->pipe);
err_free_gss_pipe:
	kfree(p);
err:
	return ERR_PTR(err);
}
}


static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt,
static void __gss_pipe_free(struct gss_pipe *p)
					 struct rpc_auth *auth)
{
{
	struct gss_auth *gss_auth = container_of(auth, struct gss_auth,
	struct rpc_clnt *clnt = p->clnt;
			rpc_auth);
	struct net *net = rpc_net_ns(clnt);
	struct net *net = gss_auth->net;
	struct super_block *sb;
	int err = 0;


	sb = rpc_get_sb_net(net);
	rpc_remove_pipe_dir_object(net,
	if (sb) {
			&clnt->cl_pipedir_objects,
		if (clnt->cl_dentry)
			&p->pdo);
			err = gss_pipes_dentries_create(auth);
	rpc_destroy_pipe_data(p->pipe);
		rpc_put_sb_net(net);
	kfree(p);
}
}
	return err;

static void gss_pipe_free(struct gss_pipe *p)
{
	if (p != NULL)
		__gss_pipe_free(p);
}
}


/*
/*
@@ -881,6 +886,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
{
{
	rpc_authflavor_t flavor = args->pseudoflavor;
	rpc_authflavor_t flavor = args->pseudoflavor;
	struct gss_auth *gss_auth;
	struct gss_auth *gss_auth;
	struct gss_pipe *gss_pipe;
	struct rpc_auth * auth;
	struct rpc_auth * auth;
	int err = -ENOMEM; /* XXX? */
	int err = -ENOMEM; /* XXX? */


@@ -915,39 +921,35 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
	atomic_set(&auth->au_count, 1);
	atomic_set(&auth->au_count, 1);
	kref_init(&gss_auth->kref);
	kref_init(&gss_auth->kref);


	err = rpcauth_init_credcache(auth);
	if (err)
		goto err_put_mech;
	/*
	/*
	 * Note: if we created the old pipe first, then someone who
	 * Note: if we created the old pipe first, then someone who
	 * examined the directory at the right moment might conclude
	 * examined the directory at the right moment might conclude
	 * that we supported only the old pipe.  So we instead create
	 * that we supported only the old pipe.  So we instead create
	 * the new pipe first.
	 * the new pipe first.
	 */
	 */
	gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1,
	gss_pipe = gss_pipe_alloc(clnt, "gssd", &gss_upcall_ops_v1);
					    RPC_PIPE_WAIT_FOR_OPEN);
	if (IS_ERR(gss_pipe)) {
	if (IS_ERR(gss_auth->pipe[1])) {
		err = PTR_ERR(gss_pipe);
		err = PTR_ERR(gss_auth->pipe[1]);
		goto err_destroy_credcache;
		goto err_put_mech;
	}
	}
	gss_auth->gss_pipe[1] = gss_pipe;


	gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0,
	gss_pipe = gss_pipe_alloc(clnt, gss_auth->mech->gm_name,
					    RPC_PIPE_WAIT_FOR_OPEN);
			&gss_upcall_ops_v0);
	if (IS_ERR(gss_auth->pipe[0])) {
	if (IS_ERR(gss_pipe)) {
		err = PTR_ERR(gss_auth->pipe[0]);
		err = PTR_ERR(gss_pipe);
		goto err_destroy_pipe_1;
		goto err_destroy_pipe_1;
	}
	}
	err = gss_pipes_dentries_create_net(clnt, auth);
	gss_auth->gss_pipe[0] = gss_pipe;
	if (err)
		goto err_destroy_pipe_0;
	err = rpcauth_init_credcache(auth);
	if (err)
		goto err_unlink_pipes;


	return auth;
	return auth;
err_unlink_pipes:
	gss_pipes_dentries_destroy_net(clnt, auth);
err_destroy_pipe_0:
	rpc_destroy_pipe_data(gss_auth->pipe[0]);
err_destroy_pipe_1:
err_destroy_pipe_1:
	rpc_destroy_pipe_data(gss_auth->pipe[1]);
	__gss_pipe_free(gss_auth->gss_pipe[1]);
err_destroy_credcache:
	rpcauth_destroy_credcache(auth);
err_put_mech:
err_put_mech:
	gss_mech_put(gss_auth->mech);
	gss_mech_put(gss_auth->mech);
err_put_net:
err_put_net:
@@ -963,9 +965,8 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
static void
static void
gss_free(struct gss_auth *gss_auth)
gss_free(struct gss_auth *gss_auth)
{
{
	gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth);
	gss_pipe_free(gss_auth->gss_pipe[0]);
	rpc_destroy_pipe_data(gss_auth->pipe[0]);
	gss_pipe_free(gss_auth->gss_pipe[1]);
	rpc_destroy_pipe_data(gss_auth->pipe[1]);
	gss_mech_put(gss_auth->mech);
	gss_mech_put(gss_auth->mech);
	put_net(gss_auth->net);
	put_net(gss_auth->net);
	kfree(gss_auth->target_name);
	kfree(gss_auth->target_name);
@@ -985,14 +986,18 @@ gss_free_callback(struct kref *kref)
static void
static void
gss_destroy(struct rpc_auth *auth)
gss_destroy(struct rpc_auth *auth)
{
{
	struct gss_auth *gss_auth;
	struct gss_auth *gss_auth = container_of(auth,
			struct gss_auth, rpc_auth);


	dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
	dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
			auth, auth->au_flavor);
			auth, auth->au_flavor);


	gss_pipe_free(gss_auth->gss_pipe[0]);
	gss_auth->gss_pipe[0] = NULL;
	gss_pipe_free(gss_auth->gss_pipe[1]);
	gss_auth->gss_pipe[1] = NULL;
	rpcauth_destroy_credcache(auth);
	rpcauth_destroy_credcache(auth);


	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
	kref_put(&gss_auth->kref, gss_free_callback);
	kref_put(&gss_auth->kref, gss_free_callback);
}
}


@@ -1676,8 +1681,6 @@ static const struct rpc_authops authgss_ops = {
	.destroy	= gss_destroy,
	.destroy	= gss_destroy,
	.lookup_cred	= gss_lookup_cred,
	.lookup_cred	= gss_lookup_cred,
	.crcreate	= gss_create_cred,
	.crcreate	= gss_create_cred,
	.pipes_create	= gss_pipes_dentries_create,
	.pipes_destroy	= gss_pipes_dentries_destroy,
	.list_pseudoflavors = gss_mech_list_pseudoflavors,
	.list_pseudoflavors = gss_mech_list_pseudoflavors,
	.info2flavor	= gss_mech_info2flavor,
	.info2flavor	= gss_mech_info2flavor,
	.flavor2info	= gss_mech_flavor2info,
	.flavor2info	= gss_mech_flavor2info,