Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/nfs/callback.c
0004  *
0005  * Copyright (C) 2004 Trond Myklebust
0006  *
0007  * NFSv4 callback handling
0008  */
0009 
0010 #include <linux/completion.h>
0011 #include <linux/ip.h>
0012 #include <linux/module.h>
0013 #include <linux/sched/signal.h>
0014 #include <linux/sunrpc/svc.h>
0015 #include <linux/sunrpc/svcsock.h>
0016 #include <linux/nfs_fs.h>
0017 #include <linux/errno.h>
0018 #include <linux/mutex.h>
0019 #include <linux/freezer.h>
0020 #include <linux/sunrpc/svcauth_gss.h>
0021 #include <linux/sunrpc/bc_xprt.h>
0022 
0023 #include <net/inet_sock.h>
0024 
0025 #include "nfs4_fs.h"
0026 #include "callback.h"
0027 #include "internal.h"
0028 #include "netns.h"
0029 
0030 #define NFSDBG_FACILITY NFSDBG_CALLBACK
0031 
0032 struct nfs_callback_data {
0033     unsigned int users;
0034     struct svc_serv *serv;
0035 };
0036 
0037 static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
0038 static DEFINE_MUTEX(nfs_callback_mutex);
0039 static struct svc_program nfs4_callback_program;
0040 
0041 static int nfs4_callback_up_net(struct svc_serv *serv, struct net *net)
0042 {
0043     const struct cred *cred = current_cred();
0044     int ret;
0045     struct nfs_net *nn = net_generic(net, nfs_net_id);
0046 
0047     ret = svc_xprt_create(serv, "tcp", net, PF_INET,
0048                   nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
0049                   cred);
0050     if (ret <= 0)
0051         goto out_err;
0052     nn->nfs_callback_tcpport = ret;
0053     dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
0054         nn->nfs_callback_tcpport, PF_INET, net->ns.inum);
0055 
0056     ret = svc_xprt_create(serv, "tcp", net, PF_INET6,
0057                   nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS,
0058                   cred);
0059     if (ret > 0) {
0060         nn->nfs_callback_tcpport6 = ret;
0061         dprintk("NFS: Callback listener port = %u (af %u, net %x)\n",
0062             nn->nfs_callback_tcpport6, PF_INET6, net->ns.inum);
0063     } else if (ret != -EAFNOSUPPORT)
0064         goto out_err;
0065     return 0;
0066 
0067 out_err:
0068     return (ret) ? ret : -ENOMEM;
0069 }
0070 
0071 /*
0072  * This is the NFSv4 callback kernel thread.
0073  */
0074 static int
0075 nfs4_callback_svc(void *vrqstp)
0076 {
0077     int err;
0078     struct svc_rqst *rqstp = vrqstp;
0079 
0080     set_freezable();
0081 
0082     while (!kthread_freezable_should_stop(NULL)) {
0083 
0084         if (signal_pending(current))
0085             flush_signals(current);
0086         /*
0087          * Listen for a request on the socket
0088          */
0089         err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
0090         if (err == -EAGAIN || err == -EINTR)
0091             continue;
0092         svc_process(rqstp);
0093     }
0094 
0095     svc_exit_thread(rqstp);
0096     return 0;
0097 }
0098 
0099 #if defined(CONFIG_NFS_V4_1)
0100 /*
0101  * The callback service for NFSv4.1 callbacks
0102  */
0103 static int
0104 nfs41_callback_svc(void *vrqstp)
0105 {
0106     struct svc_rqst *rqstp = vrqstp;
0107     struct svc_serv *serv = rqstp->rq_server;
0108     struct rpc_rqst *req;
0109     int error;
0110     DEFINE_WAIT(wq);
0111 
0112     set_freezable();
0113 
0114     while (!kthread_freezable_should_stop(NULL)) {
0115 
0116         if (signal_pending(current))
0117             flush_signals(current);
0118 
0119         prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
0120         spin_lock_bh(&serv->sv_cb_lock);
0121         if (!list_empty(&serv->sv_cb_list)) {
0122             req = list_first_entry(&serv->sv_cb_list,
0123                     struct rpc_rqst, rq_bc_list);
0124             list_del(&req->rq_bc_list);
0125             spin_unlock_bh(&serv->sv_cb_lock);
0126             finish_wait(&serv->sv_cb_waitq, &wq);
0127             dprintk("Invoking bc_svc_process()\n");
0128             error = bc_svc_process(serv, req, rqstp);
0129             dprintk("bc_svc_process() returned w/ error code= %d\n",
0130                 error);
0131         } else {
0132             spin_unlock_bh(&serv->sv_cb_lock);
0133             if (!kthread_should_stop())
0134                 schedule();
0135             finish_wait(&serv->sv_cb_waitq, &wq);
0136         }
0137     }
0138 
0139     svc_exit_thread(rqstp);
0140     return 0;
0141 }
0142 
0143 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
0144         struct svc_serv *serv)
0145 {
0146     if (minorversion)
0147         /*
0148          * Save the svc_serv in the transport so that it can
0149          * be referenced when the session backchannel is initialized
0150          */
0151         xprt->bc_serv = serv;
0152 }
0153 #else
0154 static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
0155         struct svc_serv *serv)
0156 {
0157 }
0158 #endif /* CONFIG_NFS_V4_1 */
0159 
0160 static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
0161                   struct svc_serv *serv)
0162 {
0163     int nrservs = nfs_callback_nr_threads;
0164     int ret;
0165 
0166     nfs_callback_bc_serv(minorversion, xprt, serv);
0167 
0168     if (nrservs < NFS4_MIN_NR_CALLBACK_THREADS)
0169         nrservs = NFS4_MIN_NR_CALLBACK_THREADS;
0170 
0171     if (serv->sv_nrthreads == nrservs)
0172         return 0;
0173 
0174     ret = svc_set_num_threads(serv, NULL, nrservs);
0175     if (ret) {
0176         svc_set_num_threads(serv, NULL, 0);
0177         return ret;
0178     }
0179     dprintk("nfs_callback_up: service started\n");
0180     return 0;
0181 }
0182 
0183 static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net)
0184 {
0185     struct nfs_net *nn = net_generic(net, nfs_net_id);
0186 
0187     if (--nn->cb_users[minorversion])
0188         return;
0189 
0190     dprintk("NFS: destroy per-net callback data; net=%x\n", net->ns.inum);
0191     svc_xprt_destroy_all(serv, net);
0192 }
0193 
0194 static int nfs_callback_up_net(int minorversion, struct svc_serv *serv,
0195                    struct net *net, struct rpc_xprt *xprt)
0196 {
0197     struct nfs_net *nn = net_generic(net, nfs_net_id);
0198     int ret;
0199 
0200     if (nn->cb_users[minorversion]++)
0201         return 0;
0202 
0203     dprintk("NFS: create per-net callback data; net=%x\n", net->ns.inum);
0204 
0205     ret = svc_bind(serv, net);
0206     if (ret < 0) {
0207         printk(KERN_WARNING "NFS: bind callback service failed\n");
0208         goto err_bind;
0209     }
0210 
0211     ret = 0;
0212     if (!IS_ENABLED(CONFIG_NFS_V4_1) || minorversion == 0)
0213         ret = nfs4_callback_up_net(serv, net);
0214     else if (xprt->ops->bc_setup)
0215         set_bc_enabled(serv);
0216     else
0217         ret = -EPROTONOSUPPORT;
0218 
0219     if (ret < 0) {
0220         printk(KERN_ERR "NFS: callback service start failed\n");
0221         goto err_socks;
0222     }
0223     return 0;
0224 
0225 err_socks:
0226     svc_rpcb_cleanup(serv, net);
0227 err_bind:
0228     nn->cb_users[minorversion]--;
0229     dprintk("NFS: Couldn't create callback socket: err = %d; "
0230             "net = %x\n", ret, net->ns.inum);
0231     return ret;
0232 }
0233 
0234 static struct svc_serv *nfs_callback_create_svc(int minorversion)
0235 {
0236     struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
0237     int (*threadfn)(void *data);
0238     struct svc_serv *serv;
0239 
0240     /*
0241      * Check whether we're already up and running.
0242      */
0243     if (cb_info->serv)
0244         return svc_get(cb_info->serv);
0245 
0246     /*
0247      * Sanity check: if there's no task,
0248      * we should be the first user ...
0249      */
0250     if (cb_info->users)
0251         printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
0252             cb_info->users);
0253 
0254     threadfn = nfs4_callback_svc;
0255 #if defined(CONFIG_NFS_V4_1)
0256     if (minorversion)
0257         threadfn = nfs41_callback_svc;
0258 #else
0259     if (minorversion)
0260         return ERR_PTR(-ENOTSUPP);
0261 #endif
0262     serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
0263               threadfn);
0264     if (!serv) {
0265         printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
0266         return ERR_PTR(-ENOMEM);
0267     }
0268     cb_info->serv = serv;
0269     /* As there is only one thread we need to over-ride the
0270      * default maximum of 80 connections
0271      */
0272     serv->sv_maxconn = 1024;
0273     dprintk("nfs_callback_create_svc: service created\n");
0274     return serv;
0275 }
0276 
0277 /*
0278  * Bring up the callback thread if it is not already up.
0279  */
0280 int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
0281 {
0282     struct svc_serv *serv;
0283     struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
0284     int ret;
0285     struct net *net = xprt->xprt_net;
0286 
0287     mutex_lock(&nfs_callback_mutex);
0288 
0289     serv = nfs_callback_create_svc(minorversion);
0290     if (IS_ERR(serv)) {
0291         ret = PTR_ERR(serv);
0292         goto err_create;
0293     }
0294 
0295     ret = nfs_callback_up_net(minorversion, serv, net, xprt);
0296     if (ret < 0)
0297         goto err_net;
0298 
0299     ret = nfs_callback_start_svc(minorversion, xprt, serv);
0300     if (ret < 0)
0301         goto err_start;
0302 
0303     cb_info->users++;
0304 err_net:
0305     if (!cb_info->users)
0306         cb_info->serv = NULL;
0307     svc_put(serv);
0308 err_create:
0309     mutex_unlock(&nfs_callback_mutex);
0310     return ret;
0311 
0312 err_start:
0313     nfs_callback_down_net(minorversion, serv, net);
0314     dprintk("NFS: Couldn't create server thread; err = %d\n", ret);
0315     goto err_net;
0316 }
0317 
0318 /*
0319  * Kill the callback thread if it's no longer being used.
0320  */
0321 void nfs_callback_down(int minorversion, struct net *net)
0322 {
0323     struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
0324     struct svc_serv *serv;
0325 
0326     mutex_lock(&nfs_callback_mutex);
0327     serv = cb_info->serv;
0328     nfs_callback_down_net(minorversion, serv, net);
0329     cb_info->users--;
0330     if (cb_info->users == 0) {
0331         svc_get(serv);
0332         svc_set_num_threads(serv, NULL, 0);
0333         svc_put(serv);
0334         dprintk("nfs_callback_down: service destroyed\n");
0335         cb_info->serv = NULL;
0336     }
0337     mutex_unlock(&nfs_callback_mutex);
0338 }
0339 
0340 /* Boolean check of RPC_AUTH_GSS principal */
0341 int
0342 check_gss_callback_principal(struct nfs_client *clp, struct svc_rqst *rqstp)
0343 {
0344     char *p = rqstp->rq_cred.cr_principal;
0345 
0346     if (rqstp->rq_authop->flavour != RPC_AUTH_GSS)
0347         return 1;
0348 
0349     /* No RPC_AUTH_GSS on NFSv4.1 back channel yet */
0350     if (clp->cl_minorversion != 0)
0351         return 0;
0352     /*
0353      * It might just be a normal user principal, in which case
0354      * userspace won't bother to tell us the name at all.
0355      */
0356     if (p == NULL)
0357         return 0;
0358 
0359     /*
0360      * Did we get the acceptor from userland during the SETCLIENID
0361      * negotiation?
0362      */
0363     if (clp->cl_acceptor)
0364         return !strcmp(p, clp->cl_acceptor);
0365 
0366     /*
0367      * Otherwise try to verify it using the cl_hostname. Note that this
0368      * doesn't work if a non-canonical hostname was used in the devname.
0369      */
0370 
0371     /* Expect a GSS_C_NT_HOSTBASED_NAME like "nfs@serverhostname" */
0372 
0373     if (memcmp(p, "nfs@", 4) != 0)
0374         return 0;
0375     p += 4;
0376     if (strcmp(p, clp->cl_hostname) != 0)
0377         return 0;
0378     return 1;
0379 }
0380 
0381 /*
0382  * pg_authenticate method for nfsv4 callback threads.
0383  *
0384  * The authflavor has been negotiated, so an incorrect flavor is a server
0385  * bug. Deny packets with incorrect authflavor.
0386  *
0387  * All other checking done after NFS decoding where the nfs_client can be
0388  * found in nfs4_callback_compound
0389  */
0390 static int nfs_callback_authenticate(struct svc_rqst *rqstp)
0391 {
0392     rqstp->rq_auth_stat = rpc_autherr_badcred;
0393 
0394     switch (rqstp->rq_authop->flavour) {
0395     case RPC_AUTH_NULL:
0396         if (rqstp->rq_proc != CB_NULL)
0397             return SVC_DENIED;
0398         break;
0399     case RPC_AUTH_GSS:
0400         /* No RPC_AUTH_GSS support yet in NFSv4.1 */
0401          if (svc_is_backchannel(rqstp))
0402             return SVC_DENIED;
0403     }
0404 
0405     rqstp->rq_auth_stat = rpc_auth_ok;
0406     return SVC_OK;
0407 }
0408 
0409 /*
0410  * Define NFS4 callback program
0411  */
0412 static const struct svc_version *nfs4_callback_version[] = {
0413     [1] = &nfs4_callback_version1,
0414     [4] = &nfs4_callback_version4,
0415 };
0416 
0417 static struct svc_stat nfs4_callback_stats;
0418 
0419 static struct svc_program nfs4_callback_program = {
0420     .pg_prog = NFS4_CALLBACK,           /* RPC service number */
0421     .pg_nvers = ARRAY_SIZE(nfs4_callback_version),  /* Number of entries */
0422     .pg_vers = nfs4_callback_version,       /* version table */
0423     .pg_name = "NFSv4 callback",            /* service name */
0424     .pg_class = "nfs",              /* authentication class */
0425     .pg_stats = &nfs4_callback_stats,
0426     .pg_authenticate = nfs_callback_authenticate,
0427     .pg_init_request = svc_generic_init_request,
0428     .pg_rpcbind_set = svc_generic_rpcbind_set,
0429 };