Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/lockd/xdr4.c
0004  *
0005  * XDR support for lockd and the lock client.
0006  *
0007  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
0008  * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
0009  */
0010 
0011 #include <linux/types.h>
0012 #include <linux/sched.h>
0013 #include <linux/nfs.h>
0014 
0015 #include <linux/sunrpc/xdr.h>
0016 #include <linux/sunrpc/clnt.h>
0017 #include <linux/sunrpc/svc.h>
0018 #include <linux/sunrpc/stats.h>
0019 #include <linux/lockd/lockd.h>
0020 
0021 #include "svcxdr.h"
0022 
0023 static inline s64
0024 loff_t_to_s64(loff_t offset)
0025 {
0026     s64 res;
0027     if (offset > NLM4_OFFSET_MAX)
0028         res = NLM4_OFFSET_MAX;
0029     else if (offset < -NLM4_OFFSET_MAX)
0030         res = -NLM4_OFFSET_MAX;
0031     else
0032         res = offset;
0033     return res;
0034 }
0035 
0036 /*
0037  * NLM file handles are defined by specification to be a variable-length
0038  * XDR opaque no longer than 1024 bytes. However, this implementation
0039  * limits their length to the size of an NFSv3 file handle.
0040  */
0041 static bool
0042 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
0043 {
0044     __be32 *p;
0045     u32 len;
0046 
0047     if (xdr_stream_decode_u32(xdr, &len) < 0)
0048         return false;
0049     if (len > NFS_MAXFHSIZE)
0050         return false;
0051 
0052     p = xdr_inline_decode(xdr, len);
0053     if (!p)
0054         return false;
0055     fh->size = len;
0056     memcpy(fh->data, p, len);
0057     memset(fh->data + len, 0, sizeof(fh->data) - len);
0058 
0059     return true;
0060 }
0061 
0062 static bool
0063 svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
0064 {
0065     struct file_lock *fl = &lock->fl;
0066 
0067     if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0068         return false;
0069     if (!svcxdr_decode_fhandle(xdr, &lock->fh))
0070         return false;
0071     if (!svcxdr_decode_owner(xdr, &lock->oh))
0072         return false;
0073     if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
0074         return false;
0075     if (xdr_stream_decode_u64(xdr, &lock->lock_start) < 0)
0076         return false;
0077     if (xdr_stream_decode_u64(xdr, &lock->lock_len) < 0)
0078         return false;
0079 
0080     locks_init_lock(fl);
0081     fl->fl_flags = FL_POSIX;
0082     fl->fl_type  = F_RDLCK;
0083 
0084     return true;
0085 }
0086 
0087 static bool
0088 svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
0089 {
0090     const struct file_lock *fl = &lock->fl;
0091     s64 start, len;
0092 
0093     /* exclusive */
0094     if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0)
0095         return false;
0096     if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
0097         return false;
0098     if (!svcxdr_encode_owner(xdr, &lock->oh))
0099         return false;
0100     start = loff_t_to_s64(fl->fl_start);
0101     if (fl->fl_end == OFFSET_MAX)
0102         len = 0;
0103     else
0104         len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
0105     if (xdr_stream_encode_u64(xdr, start) < 0)
0106         return false;
0107     if (xdr_stream_encode_u64(xdr, len) < 0)
0108         return false;
0109 
0110     return true;
0111 }
0112 
0113 static bool
0114 svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
0115 {
0116     if (!svcxdr_encode_stats(xdr, resp->status))
0117         return false;
0118     switch (resp->status) {
0119     case nlm_lck_denied:
0120         if (!svcxdr_encode_holder(xdr, &resp->lock))
0121             return false;
0122     }
0123 
0124     return true;
0125 }
0126 
0127 
0128 /*
0129  * Decode Call arguments
0130  */
0131 
0132 bool
0133 nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0134 {
0135     return true;
0136 }
0137 
0138 bool
0139 nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0140 {
0141     struct nlm_args *argp = rqstp->rq_argp;
0142     u32 exclusive;
0143 
0144     if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0145         return false;
0146     if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0147         return false;
0148     if (!svcxdr_decode_lock(xdr, &argp->lock))
0149         return false;
0150     if (exclusive)
0151         argp->lock.fl.fl_type = F_WRLCK;
0152 
0153     return true;
0154 }
0155 
0156 bool
0157 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0158 {
0159     struct nlm_args *argp = rqstp->rq_argp;
0160     u32 exclusive;
0161 
0162     if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0163         return false;
0164     if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
0165         return false;
0166     if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0167         return false;
0168     if (!svcxdr_decode_lock(xdr, &argp->lock))
0169         return false;
0170     if (exclusive)
0171         argp->lock.fl.fl_type = F_WRLCK;
0172     if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
0173         return false;
0174     if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0175         return false;
0176     argp->monitor = 1;      /* monitor client by default */
0177 
0178     return true;
0179 }
0180 
0181 bool
0182 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0183 {
0184     struct nlm_args *argp = rqstp->rq_argp;
0185     u32 exclusive;
0186 
0187     if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0188         return false;
0189     if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
0190         return false;
0191     if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
0192         return false;
0193     if (!svcxdr_decode_lock(xdr, &argp->lock))
0194         return false;
0195     if (exclusive)
0196         argp->lock.fl.fl_type = F_WRLCK;
0197 
0198     return true;
0199 }
0200 
0201 bool
0202 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0203 {
0204     struct nlm_args *argp = rqstp->rq_argp;
0205 
0206     if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0207         return false;
0208     if (!svcxdr_decode_lock(xdr, &argp->lock))
0209         return false;
0210     argp->lock.fl.fl_type = F_UNLCK;
0211 
0212     return true;
0213 }
0214 
0215 bool
0216 nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0217 {
0218     struct nlm_res *resp = rqstp->rq_argp;
0219 
0220     if (!svcxdr_decode_cookie(xdr, &resp->cookie))
0221         return false;
0222     if (!svcxdr_decode_stats(xdr, &resp->status))
0223         return false;
0224 
0225     return true;
0226 }
0227 
0228 bool
0229 nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0230 {
0231     struct nlm_reboot *argp = rqstp->rq_argp;
0232     __be32 *p;
0233     u32 len;
0234 
0235     if (xdr_stream_decode_u32(xdr, &len) < 0)
0236         return false;
0237     if (len > SM_MAXSTRLEN)
0238         return false;
0239     p = xdr_inline_decode(xdr, len);
0240     if (!p)
0241         return false;
0242     argp->len = len;
0243     argp->mon = (char *)p;
0244     if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0245         return false;
0246     p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
0247     if (!p)
0248         return false;
0249     memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
0250 
0251     return true;
0252 }
0253 
0254 bool
0255 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0256 {
0257     struct nlm_args *argp = rqstp->rq_argp;
0258     struct nlm_lock *lock = &argp->lock;
0259 
0260     memset(lock, 0, sizeof(*lock));
0261     locks_init_lock(&lock->fl);
0262     lock->svid = ~(u32)0;
0263 
0264     if (!svcxdr_decode_cookie(xdr, &argp->cookie))
0265         return false;
0266     if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0267         return false;
0268     if (!svcxdr_decode_fhandle(xdr, &lock->fh))
0269         return false;
0270     if (!svcxdr_decode_owner(xdr, &lock->oh))
0271         return false;
0272     /* XXX: Range checks are missing in the original code */
0273     if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
0274         return false;
0275     if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
0276         return false;
0277 
0278     return true;
0279 }
0280 
0281 bool
0282 nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0283 {
0284     struct nlm_args *argp = rqstp->rq_argp;
0285     struct nlm_lock *lock = &argp->lock;
0286 
0287     if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
0288         return false;
0289     if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
0290         return false;
0291 
0292     return true;
0293 }
0294 
0295 
0296 /*
0297  * Encode Reply results
0298  */
0299 
0300 bool
0301 nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0302 {
0303     return true;
0304 }
0305 
0306 bool
0307 nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0308 {
0309     struct nlm_res *resp = rqstp->rq_resp;
0310 
0311     return svcxdr_encode_cookie(xdr, &resp->cookie) &&
0312         svcxdr_encode_testrply(xdr, resp);
0313 }
0314 
0315 bool
0316 nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0317 {
0318     struct nlm_res *resp = rqstp->rq_resp;
0319 
0320     return svcxdr_encode_cookie(xdr, &resp->cookie) &&
0321         svcxdr_encode_stats(xdr, resp->status);
0322 }
0323 
0324 bool
0325 nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
0326 {
0327     struct nlm_res *resp = rqstp->rq_resp;
0328 
0329     if (!svcxdr_encode_cookie(xdr, &resp->cookie))
0330         return false;
0331     if (!svcxdr_encode_stats(xdr, resp->status))
0332         return false;
0333     /* sequence */
0334     if (xdr_stream_encode_u32(xdr, 0) < 0)
0335         return false;
0336 
0337     return true;
0338 }