#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/pagemap.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/gss_krb5.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_err.h>
#include <linux/workqueue.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/sunrpc/gss_api.h>
#include <linux/uaccess.h>
#include <linux/hashtable.h>
#include "auth_gss_internal.h"
#include "../netns.h"
#include <trace/events/rpcgss.h>
static const struct rpc_authops authgss_ops;
static const struct rpc_credops gss_credops;
static const struct rpc_credops gss_nullops;
#define GSS_RETRY_EXPIRED …
static unsigned int gss_expired_cred_retry_delay = …;
#define GSS_KEY_EXPIRE_TIMEO …
static unsigned int gss_key_expire_timeo = …;
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
#define RPCDBG_FACILITY …
#endif
#define GSS_KRB5_MAX_SLACK_NEEDED …
#define GSS_CRED_SLACK …
#define GSS_VERF_SLACK …
static DEFINE_HASHTABLE(gss_auth_hash_table, 4);
static DEFINE_SPINLOCK(gss_auth_hash_lock);
struct gss_pipe { … };
struct gss_auth { … };
static DEFINE_SPINLOCK(pipe_version_lock);
static struct rpc_wait_queue pipe_version_rpc_waitqueue;
static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
static void gss_put_auth(struct gss_auth *gss_auth);
static void gss_free_ctx(struct gss_cl_ctx *);
static const struct rpc_pipe_ops gss_upcall_ops_v0;
static const struct rpc_pipe_ops gss_upcall_ops_v1;
static inline struct gss_cl_ctx *
gss_get_ctx(struct gss_cl_ctx *ctx)
{ … }
static inline void
gss_put_ctx(struct gss_cl_ctx *ctx)
{ … }
static void
gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
{ … }
static struct gss_cl_ctx *
gss_cred_get_ctx(struct rpc_cred *cred)
{ … }
static struct gss_cl_ctx *
gss_alloc_context(void)
{ … }
#define GSSD_MIN_TIMEOUT …
static const void *
gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm)
{ … }
#define UPCALL_BUF_LEN …
struct gss_upcall_msg { … };
static int get_pipe_version(struct net *net)
{ … }
static void put_pipe_version(struct net *net)
{ … }
static void
gss_release_msg(struct gss_upcall_msg *gss_msg)
{ … }
static struct gss_upcall_msg *
__gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth)
{ … }
static inline struct gss_upcall_msg *
gss_add_msg(struct gss_upcall_msg *gss_msg)
{ … }
static void
__gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{ … }
static void
gss_unhash_msg(struct gss_upcall_msg *gss_msg)
{ … }
static void
gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg)
{ … }
static void
gss_upcall_callback(struct rpc_task *task)
{ … }
static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg,
const struct cred *cred)
{ … }
static ssize_t
gss_v0_upcall(struct file *file, struct rpc_pipe_msg *msg,
char __user *buf, size_t buflen)
{ … }
static int gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
const char *service_name,
const char *target_name,
const struct cred *cred)
{ … }
static ssize_t
gss_v1_upcall(struct file *file, struct rpc_pipe_msg *msg,
char __user *buf, size_t buflen)
{ … }
static struct gss_upcall_msg *
gss_alloc_msg(struct gss_auth *gss_auth,
kuid_t uid, const char *service_name)
{ … }
static struct gss_upcall_msg *
gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred)
{ … }
static void warn_gssd(void)
{ … }
static inline int
gss_refresh_upcall(struct rpc_task *task)
{ … }
static inline int
gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
{ … }
static struct gss_upcall_msg *
gss_find_downcall(struct rpc_pipe *pipe, kuid_t uid)
{ … }
#define MSG_BUF_MAXSIZE …
static ssize_t
gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
{ … }
static int gss_pipe_open(struct inode *inode, int new_version)
{ … }
static int gss_pipe_open_v0(struct inode *inode)
{ … }
static int gss_pipe_open_v1(struct inode *inode)
{ … }
static void
gss_pipe_release(struct inode *inode)
{ … }
static void
gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
{ … }
static void gss_pipe_dentry_destroy(struct dentry *dir,
struct rpc_pipe_dir_object *pdo)
{ … }
static int gss_pipe_dentry_create(struct dentry *dir,
struct rpc_pipe_dir_object *pdo)
{ … }
static const struct rpc_pipe_dir_object_ops gss_pipe_dir_object_ops = …;
static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
const char *name,
const struct rpc_pipe_ops *upcall_ops)
{ … }
struct gss_alloc_pdo { … };
static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data)
{ … }
static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data)
{ … }
static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt,
const char *name,
const struct rpc_pipe_ops *upcall_ops)
{ … }
static void __gss_pipe_free(struct gss_pipe *p)
{ … }
static void __gss_pipe_release(struct kref *kref)
{ … }
static void gss_pipe_free(struct gss_pipe *p)
{ … }
static struct gss_auth *
gss_create_new(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
{ … }
static void
gss_free(struct gss_auth *gss_auth)
{ … }
static void
gss_free_callback(struct kref *kref)
{ … }
static void
gss_put_auth(struct gss_auth *gss_auth)
{ … }
static void
gss_destroy(struct rpc_auth *auth)
{ … }
static struct gss_auth *
gss_auth_find_or_add_hashed(const struct rpc_auth_create_args *args,
struct rpc_clnt *clnt,
struct gss_auth *new)
{ … }
static struct gss_auth *
gss_create_hashed(const struct rpc_auth_create_args *args,
struct rpc_clnt *clnt)
{ … }
static struct rpc_auth *
gss_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
{ … }
static struct gss_cred *
gss_dup_cred(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
{ … }
static void
gss_send_destroy_context(struct rpc_cred *cred)
{ … }
static void
gss_do_free_ctx(struct gss_cl_ctx *ctx)
{ … }
static void
gss_free_ctx_callback(struct rcu_head *head)
{ … }
static void
gss_free_ctx(struct gss_cl_ctx *ctx)
{ … }
static void
gss_free_cred(struct gss_cred *gss_cred)
{ … }
static void
gss_free_cred_callback(struct rcu_head *head)
{ … }
static void
gss_destroy_nullcred(struct rpc_cred *cred)
{ … }
static void
gss_destroy_cred(struct rpc_cred *cred)
{ … }
static int
gss_hash_cred(struct auth_cred *acred, unsigned int hashbits)
{ … }
static struct rpc_cred *gss_lookup_cred(struct rpc_auth *auth,
struct auth_cred *acred, int flags)
{ … }
static struct rpc_cred *
gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags, gfp_t gfp)
{ … }
static int
gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred)
{ … }
static char *
gss_stringify_acceptor(struct rpc_cred *cred)
{ … }
static int
gss_key_timeout(struct rpc_cred *rc)
{ … }
static int
gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
{ … }
static int gss_marshal(struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static int gss_renew_cred(struct rpc_task *task)
{ … }
static int gss_cred_is_negative_entry(struct rpc_cred *cred)
{ … }
static int
gss_refresh(struct rpc_task *task)
{ … }
static int
gss_refresh_null(struct rpc_task *task)
{ … }
static int
gss_validate(struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static noinline_for_stack int
gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static void
priv_release_snd_buf(struct rpc_rqst *rqstp)
{ … }
static int
alloc_enc_pages(struct rpc_rqst *rqstp)
{ … }
static noinline_for_stack int
gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static int gss_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static void gss_update_rslack(struct rpc_task *task, struct rpc_cred *cred,
unsigned int before, unsigned int after)
{ … }
static int
gss_unwrap_resp_auth(struct rpc_task *task, struct rpc_cred *cred)
{ … }
static noinline_for_stack int
gss_unwrap_resp_integ(struct rpc_task *task, struct rpc_cred *cred,
struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp,
struct xdr_stream *xdr)
{ … }
static noinline_for_stack int
gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
struct gss_cl_ctx *ctx, struct rpc_rqst *rqstp,
struct xdr_stream *xdr)
{ … }
static bool
gss_seq_is_newer(u32 new, u32 old)
{ … }
static bool
gss_xmit_need_reencode(struct rpc_task *task)
{ … }
static int
gss_unwrap_resp(struct rpc_task *task, struct xdr_stream *xdr)
{ … }
static const struct rpc_authops authgss_ops = …;
static const struct rpc_credops gss_credops = …;
static const struct rpc_credops gss_nullops = …;
static const struct rpc_pipe_ops gss_upcall_ops_v0 = …;
static const struct rpc_pipe_ops gss_upcall_ops_v1 = …;
static __net_init int rpcsec_gss_init_net(struct net *net)
{ … }
static __net_exit void rpcsec_gss_exit_net(struct net *net)
{ … }
static struct pernet_operations rpcsec_gss_net_ops = …;
static int __init init_rpcsec_gss(void)
{ … }
static void __exit exit_rpcsec_gss(void)
{ … }
MODULE_ALIAS(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_LICENSE(…) …;
module_param_named(expired_cred_retry_delay,
gss_expired_cred_retry_delay,
uint, 0644);
MODULE_PARM_DESC(…) …;
module_param_named(key_expire_timeo,
gss_key_expire_timeo,
uint, 0644);
MODULE_PARM_DESC(…) …;
module_init(…) …
module_exit(…)