* using integrity (two 4-byte integers): */
#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 kref kref;
struct rpc_auth rpc_auth;
* mechanism (for example, "krb5") and exists for
* backwards-compatibility with older gssd's.
*/
- struct rpc_pipe *pipe[2];
+ struct gss_pipe *gss_pipe[2];
const char *target_name;
};
kfree(gss_msg);
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);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
init_waitqueue_head(&gss_msg->waitqueue);
}
}
-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 (gss_auth->pipe[0]->dentry) {
- rpc_unlink(gss_auth->pipe[0]->dentry);
- 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;
+ if (pipe->dentry != NULL) {
+ rpc_unlink(pipe->dentry);
+ pipe->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_auth *gss_auth;
- struct rpc_clnt *clnt;
+ struct gss_pipe *p = pdo->pdo_data;
struct dentry *dentry;
- gss_auth = container_of(auth, struct gss_auth, rpc_auth);
- clnt = gss_auth->client;
+ dentry = rpc_mkpipe_dentry(dir, p->name, p->clnt, p->pipe);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+ p->pipe->dentry = dentry;
+ return 0;
+}
+
+static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = {
+ .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 net *net = rpc_net_ns(clnt);
+ struct gss_pipe *p;
+ int err = -ENOMEM;
- dentry = rpc_mkpipe_dentry(clnt->cl_dentry, "gssd",
- clnt, gss_auth->pipe[1]);
- if (IS_ERR(dentry)) {
- err = PTR_ERR(dentry);
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL)
goto err;
+ p->pipe = rpc_mkpipe_data(upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+ if (IS_ERR(p->pipe)) {
+ err = PTR_ERR(p->pipe);
+ goto err_free_gss_pipe;
}
- 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;
-
-err_unlink_pipe_1:
- rpc_unlink(gss_auth->pipe[1]->dentry);
- gss_auth->pipe[1]->dentry = NULL;
+ 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;
+ return ERR_PTR(err);
}
-static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt,
- struct rpc_auth *auth)
+static void __gss_pipe_free(struct gss_pipe *p)
{
- struct gss_auth *gss_auth = container_of(auth, struct gss_auth,
- rpc_auth);
- struct net *net = gss_auth->net;
- struct super_block *sb;
+ struct rpc_clnt *clnt = p->clnt;
+ struct net *net = rpc_net_ns(clnt);
- sb = rpc_get_sb_net(net);
- if (sb) {
- if (clnt->cl_dentry)
- gss_pipes_dentries_destroy(auth);
- rpc_put_sb_net(net);
- }
+ rpc_remove_pipe_dir_object(net,
+ &clnt->cl_pipedir_objects,
+ &p->pdo);
+ rpc_destroy_pipe_data(p->pipe);
+ kfree(p);
}
-static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt,
- struct rpc_auth *auth)
+static void gss_pipe_free(struct gss_pipe *p)
{
- struct gss_auth *gss_auth = container_of(auth, struct gss_auth,
- rpc_auth);
- struct net *net = gss_auth->net;
- struct super_block *sb;
- int err = 0;
-
- sb = rpc_get_sb_net(net);
- if (sb) {
- if (clnt->cl_dentry)
- err = gss_pipes_dentries_create(auth);
- rpc_put_sb_net(net);
- }
- return err;
+ if (p != NULL)
+ __gss_pipe_free(p);
}
/*
{
rpc_authflavor_t flavor = args->pseudoflavor;
struct gss_auth *gss_auth;
+ struct gss_pipe *gss_pipe;
struct rpc_auth * auth;
int err = -ENOMEM; /* XXX? */
atomic_set(&auth->au_count, 1);
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
* examined the directory at the right moment might conclude
* that we supported only the old pipe. So we instead create
* the new pipe first.
*/
- gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1,
- RPC_PIPE_WAIT_FOR_OPEN);
- if (IS_ERR(gss_auth->pipe[1])) {
- err = PTR_ERR(gss_auth->pipe[1]);
- goto err_put_mech;
+ gss_pipe = gss_pipe_alloc(clnt, "gssd", &gss_upcall_ops_v1);
+ if (IS_ERR(gss_pipe)) {
+ err = PTR_ERR(gss_pipe);
+ goto err_destroy_credcache;
}
+ gss_auth->gss_pipe[1] = gss_pipe;
- gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0,
- RPC_PIPE_WAIT_FOR_OPEN);
- if (IS_ERR(gss_auth->pipe[0])) {
- err = PTR_ERR(gss_auth->pipe[0]);
+ gss_pipe = gss_pipe_alloc(clnt, gss_auth->mech->gm_name,
+ &gss_upcall_ops_v0);
+ if (IS_ERR(gss_pipe)) {
+ err = PTR_ERR(gss_pipe);
goto err_destroy_pipe_1;
}
- err = gss_pipes_dentries_create_net(clnt, auth);
- if (err)
- goto err_destroy_pipe_0;
- err = rpcauth_init_credcache(auth);
- if (err)
- goto err_unlink_pipes;
+ gss_auth->gss_pipe[0] = gss_pipe;
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:
- 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:
gss_mech_put(gss_auth->mech);
err_put_net:
static void
gss_free(struct gss_auth *gss_auth)
{
- gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth);
- rpc_destroy_pipe_data(gss_auth->pipe[0]);
- rpc_destroy_pipe_data(gss_auth->pipe[1]);
+ gss_pipe_free(gss_auth->gss_pipe[0]);
+ gss_pipe_free(gss_auth->gss_pipe[1]);
gss_mech_put(gss_auth->mech);
put_net(gss_auth->net);
kfree(gss_auth->target_name);
static void
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",
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);
- gss_auth = container_of(auth, struct gss_auth, rpc_auth);
kref_put(&gss_auth->kref, gss_free_callback);
}
.destroy = gss_destroy,
.lookup_cred = gss_lookup_cred,
.crcreate = gss_create_cred,
- .pipes_create = gss_pipes_dentries_create,
- .pipes_destroy = gss_pipes_dentries_destroy,
.list_pseudoflavors = gss_mech_list_pseudoflavors,
.info2flavor = gss_mech_info2flavor,
.flavor2info = gss_mech_flavor2info,