Loading net/sunrpc/auth_gss/auth_gss.c +92 −89 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; }; }; Loading Loading @@ -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); Loading Loading @@ -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); } } /* /* Loading @@ -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? */ Loading Loading @@ -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: Loading @@ -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); Loading @@ -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); } } Loading Loading @@ -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, Loading Loading
net/sunrpc/auth_gss/auth_gss.c +92 −89 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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; }; }; Loading Loading @@ -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); Loading Loading @@ -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); } } /* /* Loading @@ -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? */ Loading Loading @@ -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: Loading @@ -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); Loading @@ -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); } } Loading Loading @@ -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, Loading