Back to home page

OSCL-LXR

 
 

    


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