Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/lockd/clntxdr.c
0004  *
0005  * XDR functions to encode/decode NLM version 3 RPC arguments and results.
0006  * NLM version 3 is backwards compatible with NLM versions 1 and 2.
0007  *
0008  * NLM client-side only.
0009  *
0010  * Copyright (C) 2010, Oracle.  All rights reserved.
0011  */
0012 
0013 #include <linux/types.h>
0014 #include <linux/sunrpc/xdr.h>
0015 #include <linux/sunrpc/clnt.h>
0016 #include <linux/sunrpc/stats.h>
0017 #include <linux/lockd/lockd.h>
0018 
0019 #include <uapi/linux/nfs2.h>
0020 
0021 #define NLMDBG_FACILITY     NLMDBG_XDR
0022 
0023 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
0024 #  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
0025 #endif
0026 
0027 /*
0028  * Declare the space requirements for NLM arguments and replies as
0029  * number of 32bit-words
0030  */
0031 #define NLM_cookie_sz       (1+(NLM_MAXCOOKIELEN>>2))
0032 #define NLM_caller_sz       (1+(NLMCLNT_OHSIZE>>2))
0033 #define NLM_owner_sz        (1+(NLMCLNT_OHSIZE>>2))
0034 #define NLM_fhandle_sz      (1+(NFS2_FHSIZE>>2))
0035 #define NLM_lock_sz     (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz)
0036 #define NLM_holder_sz       (4+NLM_owner_sz)
0037 
0038 #define NLM_testargs_sz     (NLM_cookie_sz+1+NLM_lock_sz)
0039 #define NLM_lockargs_sz     (NLM_cookie_sz+4+NLM_lock_sz)
0040 #define NLM_cancargs_sz     (NLM_cookie_sz+2+NLM_lock_sz)
0041 #define NLM_unlockargs_sz   (NLM_cookie_sz+NLM_lock_sz)
0042 
0043 #define NLM_testres_sz      (NLM_cookie_sz+1+NLM_holder_sz)
0044 #define NLM_res_sz      (NLM_cookie_sz+1)
0045 #define NLM_norep_sz        (0)
0046 
0047 
0048 static s32 loff_t_to_s32(loff_t offset)
0049 {
0050     s32 res;
0051 
0052     if (offset >= NLM_OFFSET_MAX)
0053         res = NLM_OFFSET_MAX;
0054     else if (offset <= -NLM_OFFSET_MAX)
0055         res = -NLM_OFFSET_MAX;
0056     else
0057         res = offset;
0058     return res;
0059 }
0060 
0061 static void nlm_compute_offsets(const struct nlm_lock *lock,
0062                 u32 *l_offset, u32 *l_len)
0063 {
0064     const struct file_lock *fl = &lock->fl;
0065 
0066     *l_offset = loff_t_to_s32(fl->fl_start);
0067     if (fl->fl_end == OFFSET_MAX)
0068         *l_len = 0;
0069     else
0070         *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
0071 }
0072 
0073 /*
0074  * Encode/decode NLMv3 basic data types
0075  *
0076  * Basic NLMv3 data types are not defined in an IETF standards
0077  * document.  X/Open has a description of these data types that
0078  * is useful.  See Chapter 10 of "Protocols for Interworking:
0079  * XNFS, Version 3W".
0080  *
0081  * Not all basic data types have their own encoding and decoding
0082  * functions.  For run-time efficiency, some data types are encoded
0083  * or decoded inline.
0084  */
0085 
0086 static void encode_bool(struct xdr_stream *xdr, const int value)
0087 {
0088     __be32 *p;
0089 
0090     p = xdr_reserve_space(xdr, 4);
0091     *p = value ? xdr_one : xdr_zero;
0092 }
0093 
0094 static void encode_int32(struct xdr_stream *xdr, const s32 value)
0095 {
0096     __be32 *p;
0097 
0098     p = xdr_reserve_space(xdr, 4);
0099     *p = cpu_to_be32(value);
0100 }
0101 
0102 /*
0103  *  typedef opaque netobj<MAXNETOBJ_SZ>
0104  */
0105 static void encode_netobj(struct xdr_stream *xdr,
0106               const u8 *data, const unsigned int length)
0107 {
0108     __be32 *p;
0109 
0110     p = xdr_reserve_space(xdr, 4 + length);
0111     xdr_encode_opaque(p, data, length);
0112 }
0113 
0114 static int decode_netobj(struct xdr_stream *xdr,
0115              struct xdr_netobj *obj)
0116 {
0117     ssize_t ret;
0118 
0119     ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
0120             XDR_MAX_NETOBJ);
0121     if (unlikely(ret < 0))
0122         return -EIO;
0123     obj->len = ret;
0124     return 0;
0125 }
0126 
0127 /*
0128  *  netobj cookie;
0129  */
0130 static void encode_cookie(struct xdr_stream *xdr,
0131               const struct nlm_cookie *cookie)
0132 {
0133     encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
0134 }
0135 
0136 static int decode_cookie(struct xdr_stream *xdr,
0137              struct nlm_cookie *cookie)
0138 {
0139     u32 length;
0140     __be32 *p;
0141 
0142     p = xdr_inline_decode(xdr, 4);
0143     if (unlikely(p == NULL))
0144         goto out_overflow;
0145     length = be32_to_cpup(p++);
0146     /* apparently HPUX can return empty cookies */
0147     if (length == 0)
0148         goto out_hpux;
0149     if (length > NLM_MAXCOOKIELEN)
0150         goto out_size;
0151     p = xdr_inline_decode(xdr, length);
0152     if (unlikely(p == NULL))
0153         goto out_overflow;
0154     cookie->len = length;
0155     memcpy(cookie->data, p, length);
0156     return 0;
0157 out_hpux:
0158     cookie->len = 4;
0159     memset(cookie->data, 0, 4);
0160     return 0;
0161 out_size:
0162     dprintk("NFS: returned cookie was too long: %u\n", length);
0163     return -EIO;
0164 out_overflow:
0165     return -EIO;
0166 }
0167 
0168 /*
0169  *  netobj fh;
0170  */
0171 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
0172 {
0173     encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
0174 }
0175 
0176 /*
0177  *  enum nlm_stats {
0178  *      LCK_GRANTED = 0,
0179  *      LCK_DENIED = 1,
0180  *      LCK_DENIED_NOLOCKS = 2,
0181  *      LCK_BLOCKED = 3,
0182  *      LCK_DENIED_GRACE_PERIOD = 4
0183  *  };
0184  *
0185  *
0186  *  struct nlm_stat {
0187  *      nlm_stats stat;
0188  *  };
0189  *
0190  * NB: we don't swap bytes for the NLM status values.  The upper
0191  * layers deal directly with the status value in network byte
0192  * order.
0193  */
0194 
0195 static void encode_nlm_stat(struct xdr_stream *xdr,
0196                 const __be32 stat)
0197 {
0198     __be32 *p;
0199 
0200     WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
0201     p = xdr_reserve_space(xdr, 4);
0202     *p = stat;
0203 }
0204 
0205 static int decode_nlm_stat(struct xdr_stream *xdr,
0206                __be32 *stat)
0207 {
0208     __be32 *p;
0209 
0210     p = xdr_inline_decode(xdr, 4);
0211     if (unlikely(p == NULL))
0212         goto out_overflow;
0213     if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
0214         goto out_enum;
0215     *stat = *p;
0216     return 0;
0217 out_enum:
0218     dprintk("%s: server returned invalid nlm_stats value: %u\n",
0219         __func__, be32_to_cpup(p));
0220     return -EIO;
0221 out_overflow:
0222     return -EIO;
0223 }
0224 
0225 /*
0226  *  struct nlm_holder {
0227  *      bool exclusive;
0228  *      int uppid;
0229  *      netobj oh;
0230  *      unsigned l_offset;
0231  *      unsigned l_len;
0232  *  };
0233  */
0234 static void encode_nlm_holder(struct xdr_stream *xdr,
0235                   const struct nlm_res *result)
0236 {
0237     const struct nlm_lock *lock = &result->lock;
0238     u32 l_offset, l_len;
0239     __be32 *p;
0240 
0241     encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
0242     encode_int32(xdr, lock->svid);
0243     encode_netobj(xdr, lock->oh.data, lock->oh.len);
0244 
0245     p = xdr_reserve_space(xdr, 4 + 4);
0246     nlm_compute_offsets(lock, &l_offset, &l_len);
0247     *p++ = cpu_to_be32(l_offset);
0248     *p   = cpu_to_be32(l_len);
0249 }
0250 
0251 static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
0252 {
0253     struct nlm_lock *lock = &result->lock;
0254     struct file_lock *fl = &lock->fl;
0255     u32 exclusive, l_offset, l_len;
0256     int error;
0257     __be32 *p;
0258     s32 end;
0259 
0260     memset(lock, 0, sizeof(*lock));
0261     locks_init_lock(fl);
0262 
0263     p = xdr_inline_decode(xdr, 4 + 4);
0264     if (unlikely(p == NULL))
0265         goto out_overflow;
0266     exclusive = be32_to_cpup(p++);
0267     lock->svid = be32_to_cpup(p);
0268     fl->fl_pid = (pid_t)lock->svid;
0269 
0270     error = decode_netobj(xdr, &lock->oh);
0271     if (unlikely(error))
0272         goto out;
0273 
0274     p = xdr_inline_decode(xdr, 4 + 4);
0275     if (unlikely(p == NULL))
0276         goto out_overflow;
0277 
0278     fl->fl_flags = FL_POSIX;
0279     fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
0280     l_offset = be32_to_cpup(p++);
0281     l_len = be32_to_cpup(p);
0282     end = l_offset + l_len - 1;
0283 
0284     fl->fl_start = (loff_t)l_offset;
0285     if (l_len == 0 || end < 0)
0286         fl->fl_end = OFFSET_MAX;
0287     else
0288         fl->fl_end = (loff_t)end;
0289     error = 0;
0290 out:
0291     return error;
0292 out_overflow:
0293     return -EIO;
0294 }
0295 
0296 /*
0297  *  string caller_name<LM_MAXSTRLEN>;
0298  */
0299 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
0300 {
0301     /* NB: client-side does not set lock->len */
0302     u32 length = strlen(name);
0303     __be32 *p;
0304 
0305     p = xdr_reserve_space(xdr, 4 + length);
0306     xdr_encode_opaque(p, name, length);
0307 }
0308 
0309 /*
0310  *  struct nlm_lock {
0311  *      string caller_name<LM_MAXSTRLEN>;
0312  *      netobj fh;
0313  *      netobj oh;
0314  *      int uppid;
0315  *      unsigned l_offset;
0316  *      unsigned l_len;
0317  *  };
0318  */
0319 static void encode_nlm_lock(struct xdr_stream *xdr,
0320                 const struct nlm_lock *lock)
0321 {
0322     u32 l_offset, l_len;
0323     __be32 *p;
0324 
0325     encode_caller_name(xdr, lock->caller);
0326     encode_fh(xdr, &lock->fh);
0327     encode_netobj(xdr, lock->oh.data, lock->oh.len);
0328 
0329     p = xdr_reserve_space(xdr, 4 + 4 + 4);
0330     *p++ = cpu_to_be32(lock->svid);
0331 
0332     nlm_compute_offsets(lock, &l_offset, &l_len);
0333     *p++ = cpu_to_be32(l_offset);
0334     *p   = cpu_to_be32(l_len);
0335 }
0336 
0337 
0338 /*
0339  * NLMv3 XDR encode functions
0340  *
0341  * NLMv3 argument types are defined in Chapter 10 of The Open Group's
0342  * "Protocols for Interworking: XNFS, Version 3W".
0343  */
0344 
0345 /*
0346  *  struct nlm_testargs {
0347  *      netobj cookie;
0348  *      bool exclusive;
0349  *      struct nlm_lock alock;
0350  *  };
0351  */
0352 static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
0353                  struct xdr_stream *xdr,
0354                  const void *data)
0355 {
0356     const struct nlm_args *args = data;
0357     const struct nlm_lock *lock = &args->lock;
0358 
0359     encode_cookie(xdr, &args->cookie);
0360     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0361     encode_nlm_lock(xdr, lock);
0362 }
0363 
0364 /*
0365  *  struct nlm_lockargs {
0366  *      netobj cookie;
0367  *      bool block;
0368  *      bool exclusive;
0369  *      struct nlm_lock alock;
0370  *      bool reclaim;
0371  *      int state;
0372  *  };
0373  */
0374 static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
0375                  struct xdr_stream *xdr,
0376                  const void *data)
0377 {
0378     const struct nlm_args *args = data;
0379     const struct nlm_lock *lock = &args->lock;
0380 
0381     encode_cookie(xdr, &args->cookie);
0382     encode_bool(xdr, args->block);
0383     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0384     encode_nlm_lock(xdr, lock);
0385     encode_bool(xdr, args->reclaim);
0386     encode_int32(xdr, args->state);
0387 }
0388 
0389 /*
0390  *  struct nlm_cancargs {
0391  *      netobj cookie;
0392  *      bool block;
0393  *      bool exclusive;
0394  *      struct nlm_lock alock;
0395  *  };
0396  */
0397 static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
0398                  struct xdr_stream *xdr,
0399                  const void *data)
0400 {
0401     const struct nlm_args *args = data;
0402     const struct nlm_lock *lock = &args->lock;
0403 
0404     encode_cookie(xdr, &args->cookie);
0405     encode_bool(xdr, args->block);
0406     encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
0407     encode_nlm_lock(xdr, lock);
0408 }
0409 
0410 /*
0411  *  struct nlm_unlockargs {
0412  *      netobj cookie;
0413  *      struct nlm_lock alock;
0414  *  };
0415  */
0416 static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
0417                    struct xdr_stream *xdr,
0418                    const void *data)
0419 {
0420     const struct nlm_args *args = data;
0421     const struct nlm_lock *lock = &args->lock;
0422 
0423     encode_cookie(xdr, &args->cookie);
0424     encode_nlm_lock(xdr, lock);
0425 }
0426 
0427 /*
0428  *  struct nlm_res {
0429  *      netobj cookie;
0430  *      nlm_stat stat;
0431  *  };
0432  */
0433 static void nlm_xdr_enc_res(struct rpc_rqst *req,
0434                 struct xdr_stream *xdr,
0435                 const void *data)
0436 {
0437     const struct nlm_res *result = data;
0438 
0439     encode_cookie(xdr, &result->cookie);
0440     encode_nlm_stat(xdr, result->status);
0441 }
0442 
0443 /*
0444  *  union nlm_testrply switch (nlm_stats stat) {
0445  *  case LCK_DENIED:
0446  *      struct nlm_holder holder;
0447  *  default:
0448  *      void;
0449  *  };
0450  *
0451  *  struct nlm_testres {
0452  *      netobj cookie;
0453  *      nlm_testrply test_stat;
0454  *  };
0455  */
0456 static void encode_nlm_testrply(struct xdr_stream *xdr,
0457                 const struct nlm_res *result)
0458 {
0459     if (result->status == nlm_lck_denied)
0460         encode_nlm_holder(xdr, result);
0461 }
0462 
0463 static void nlm_xdr_enc_testres(struct rpc_rqst *req,
0464                 struct xdr_stream *xdr,
0465                 const void *data)
0466 {
0467     const struct nlm_res *result = data;
0468 
0469     encode_cookie(xdr, &result->cookie);
0470     encode_nlm_stat(xdr, result->status);
0471     encode_nlm_testrply(xdr, result);
0472 }
0473 
0474 
0475 /*
0476  * NLMv3 XDR decode functions
0477  *
0478  * NLMv3 result types are defined in Chapter 10 of The Open Group's
0479  * "Protocols for Interworking: XNFS, Version 3W".
0480  */
0481 
0482 /*
0483  *  union nlm_testrply switch (nlm_stats stat) {
0484  *  case LCK_DENIED:
0485  *      struct nlm_holder holder;
0486  *  default:
0487  *      void;
0488  *  };
0489  *
0490  *  struct nlm_testres {
0491  *      netobj cookie;
0492  *      nlm_testrply test_stat;
0493  *  };
0494  */
0495 static int decode_nlm_testrply(struct xdr_stream *xdr,
0496                    struct nlm_res *result)
0497 {
0498     int error;
0499 
0500     error = decode_nlm_stat(xdr, &result->status);
0501     if (unlikely(error))
0502         goto out;
0503     if (result->status == nlm_lck_denied)
0504         error = decode_nlm_holder(xdr, result);
0505 out:
0506     return error;
0507 }
0508 
0509 static int nlm_xdr_dec_testres(struct rpc_rqst *req,
0510                    struct xdr_stream *xdr,
0511                    void *data)
0512 {
0513     struct nlm_res *result = data;
0514     int error;
0515 
0516     error = decode_cookie(xdr, &result->cookie);
0517     if (unlikely(error))
0518         goto out;
0519     error = decode_nlm_testrply(xdr, result);
0520 out:
0521     return error;
0522 }
0523 
0524 /*
0525  *  struct nlm_res {
0526  *      netobj cookie;
0527  *      nlm_stat stat;
0528  *  };
0529  */
0530 static int nlm_xdr_dec_res(struct rpc_rqst *req,
0531                struct xdr_stream *xdr,
0532                void *data)
0533 {
0534     struct nlm_res *result = data;
0535     int error;
0536 
0537     error = decode_cookie(xdr, &result->cookie);
0538     if (unlikely(error))
0539         goto out;
0540     error = decode_nlm_stat(xdr, &result->status);
0541 out:
0542     return error;
0543 }
0544 
0545 
0546 /*
0547  * For NLM, a void procedure really returns nothing
0548  */
0549 #define nlm_xdr_dec_norep   NULL
0550 
0551 #define PROC(proc, argtype, restype)    \
0552 [NLMPROC_##proc] = {                            \
0553     .p_proc      = NLMPROC_##proc,                  \
0554     .p_encode    = nlm_xdr_enc_##argtype,       \
0555     .p_decode    = nlm_xdr_dec_##restype,               \
0556     .p_arglen    = NLM_##argtype##_sz,              \
0557     .p_replen    = NLM_##restype##_sz,              \
0558     .p_statidx   = NLMPROC_##proc,                  \
0559     .p_name      = #proc,                       \
0560     }
0561 
0562 static const struct rpc_procinfo nlm_procedures[] = {
0563     PROC(TEST,      testargs,   testres),
0564     PROC(LOCK,      lockargs,   res),
0565     PROC(CANCEL,        cancargs,   res),
0566     PROC(UNLOCK,        unlockargs, res),
0567     PROC(GRANTED,       testargs,   res),
0568     PROC(TEST_MSG,      testargs,   norep),
0569     PROC(LOCK_MSG,      lockargs,   norep),
0570     PROC(CANCEL_MSG,    cancargs,   norep),
0571     PROC(UNLOCK_MSG,    unlockargs, norep),
0572     PROC(GRANTED_MSG,   testargs,   norep),
0573     PROC(TEST_RES,      testres,    norep),
0574     PROC(LOCK_RES,      res,        norep),
0575     PROC(CANCEL_RES,    res,        norep),
0576     PROC(UNLOCK_RES,    res,        norep),
0577     PROC(GRANTED_RES,   res,        norep),
0578 };
0579 
0580 static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)];
0581 static const struct rpc_version nlm_version1 = {
0582     .number     = 1,
0583     .nrprocs    = ARRAY_SIZE(nlm_procedures),
0584     .procs      = nlm_procedures,
0585     .counts     = nlm_version1_counts,
0586 };
0587 
0588 static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)];
0589 static const struct rpc_version nlm_version3 = {
0590     .number     = 3,
0591     .nrprocs    = ARRAY_SIZE(nlm_procedures),
0592     .procs      = nlm_procedures,
0593     .counts     = nlm_version3_counts,
0594 };
0595 
0596 static const struct rpc_version *nlm_versions[] = {
0597     [1] = &nlm_version1,
0598     [3] = &nlm_version3,
0599 #ifdef CONFIG_LOCKD_V4
0600     [4] = &nlm_version4,
0601 #endif
0602 };
0603 
0604 static struct rpc_stat      nlm_rpc_stats;
0605 
0606 const struct rpc_program    nlm_program = {
0607     .name       = "lockd",
0608     .number     = NLM_PROGRAM,
0609     .nrvers     = ARRAY_SIZE(nlm_versions),
0610     .version    = nlm_versions,
0611     .stats      = &nlm_rpc_stats,
0612 };