~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/lockd/xdr4.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * linux/fs/lockd/xdr4.c
  4  *
  5  * XDR support for lockd and the lock client.
  6  *
  7  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  8  * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no>
  9  */
 10 
 11 #include <linux/types.h>
 12 #include <linux/sched.h>
 13 #include <linux/nfs.h>
 14 
 15 #include <linux/sunrpc/xdr.h>
 16 #include <linux/sunrpc/clnt.h>
 17 #include <linux/sunrpc/svc.h>
 18 #include <linux/sunrpc/stats.h>
 19 #include <linux/lockd/lockd.h>
 20 
 21 #include "svcxdr.h"
 22 
 23 static inline s64
 24 loff_t_to_s64(loff_t offset)
 25 {
 26         s64 res;
 27         if (offset > NLM4_OFFSET_MAX)
 28                 res = NLM4_OFFSET_MAX;
 29         else if (offset < -NLM4_OFFSET_MAX)
 30                 res = -NLM4_OFFSET_MAX;
 31         else
 32                 res = offset;
 33         return res;
 34 }
 35 
 36 void nlm4svc_set_file_lock_range(struct file_lock *fl, u64 off, u64 len)
 37 {
 38         s64 end = off + len - 1;
 39 
 40         fl->fl_start = off;
 41         if (len == 0 || end < 0)
 42                 fl->fl_end = OFFSET_MAX;
 43         else
 44                 fl->fl_end = end;
 45 }
 46 
 47 /*
 48  * NLM file handles are defined by specification to be a variable-length
 49  * XDR opaque no longer than 1024 bytes. However, this implementation
 50  * limits their length to the size of an NFSv3 file handle.
 51  */
 52 static bool
 53 svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
 54 {
 55         __be32 *p;
 56         u32 len;
 57 
 58         if (xdr_stream_decode_u32(xdr, &len) < 0)
 59                 return false;
 60         if (len > NFS_MAXFHSIZE)
 61                 return false;
 62 
 63         p = xdr_inline_decode(xdr, len);
 64         if (!p)
 65                 return false;
 66         fh->size = len;
 67         memcpy(fh->data, p, len);
 68         memset(fh->data + len, 0, sizeof(fh->data) - len);
 69 
 70         return true;
 71 }
 72 
 73 static bool
 74 svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
 75 {
 76         struct file_lock *fl = &lock->fl;
 77 
 78         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
 79                 return false;
 80         if (!svcxdr_decode_fhandle(xdr, &lock->fh))
 81                 return false;
 82         if (!svcxdr_decode_owner(xdr, &lock->oh))
 83                 return false;
 84         if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
 85                 return false;
 86         if (xdr_stream_decode_u64(xdr, &lock->lock_start) < 0)
 87                 return false;
 88         if (xdr_stream_decode_u64(xdr, &lock->lock_len) < 0)
 89                 return false;
 90 
 91         locks_init_lock(fl);
 92         fl->c.flc_flags = FL_POSIX;
 93         fl->c.flc_type  = F_RDLCK;
 94         nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
 95         return true;
 96 }
 97 
 98 static bool
 99 svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
100 {
101         const struct file_lock *fl = &lock->fl;
102         s64 start, len;
103 
104         /* exclusive */
105         if (xdr_stream_encode_bool(xdr, fl->c.flc_type != F_RDLCK) < 0)
106                 return false;
107         if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
108                 return false;
109         if (!svcxdr_encode_owner(xdr, &lock->oh))
110                 return false;
111         start = loff_t_to_s64(fl->fl_start);
112         if (fl->fl_end == OFFSET_MAX)
113                 len = 0;
114         else
115                 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1);
116         if (xdr_stream_encode_u64(xdr, start) < 0)
117                 return false;
118         if (xdr_stream_encode_u64(xdr, len) < 0)
119                 return false;
120 
121         return true;
122 }
123 
124 static bool
125 svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
126 {
127         if (!svcxdr_encode_stats(xdr, resp->status))
128                 return false;
129         switch (resp->status) {
130         case nlm_lck_denied:
131                 if (!svcxdr_encode_holder(xdr, &resp->lock))
132                         return false;
133         }
134 
135         return true;
136 }
137 
138 
139 /*
140  * Decode Call arguments
141  */
142 
143 bool
144 nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
145 {
146         return true;
147 }
148 
149 bool
150 nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
151 {
152         struct nlm_args *argp = rqstp->rq_argp;
153         u32 exclusive;
154 
155         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
156                 return false;
157         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
158                 return false;
159         if (!svcxdr_decode_lock(xdr, &argp->lock))
160                 return false;
161         if (exclusive)
162                 argp->lock.fl.c.flc_type = F_WRLCK;
163 
164         return true;
165 }
166 
167 bool
168 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
169 {
170         struct nlm_args *argp = rqstp->rq_argp;
171         u32 exclusive;
172 
173         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
174                 return false;
175         if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
176                 return false;
177         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
178                 return false;
179         if (!svcxdr_decode_lock(xdr, &argp->lock))
180                 return false;
181         if (exclusive)
182                 argp->lock.fl.c.flc_type = F_WRLCK;
183         if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
184                 return false;
185         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
186                 return false;
187         argp->monitor = 1;              /* monitor client by default */
188 
189         return true;
190 }
191 
192 bool
193 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
194 {
195         struct nlm_args *argp = rqstp->rq_argp;
196         u32 exclusive;
197 
198         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
199                 return false;
200         if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
201                 return false;
202         if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
203                 return false;
204         if (!svcxdr_decode_lock(xdr, &argp->lock))
205                 return false;
206         if (exclusive)
207                 argp->lock.fl.c.flc_type = F_WRLCK;
208 
209         return true;
210 }
211 
212 bool
213 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
214 {
215         struct nlm_args *argp = rqstp->rq_argp;
216 
217         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
218                 return false;
219         if (!svcxdr_decode_lock(xdr, &argp->lock))
220                 return false;
221         argp->lock.fl.c.flc_type = F_UNLCK;
222 
223         return true;
224 }
225 
226 bool
227 nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
228 {
229         struct nlm_res *resp = rqstp->rq_argp;
230 
231         if (!svcxdr_decode_cookie(xdr, &resp->cookie))
232                 return false;
233         if (!svcxdr_decode_stats(xdr, &resp->status))
234                 return false;
235 
236         return true;
237 }
238 
239 bool
240 nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
241 {
242         struct nlm_reboot *argp = rqstp->rq_argp;
243         __be32 *p;
244         u32 len;
245 
246         if (xdr_stream_decode_u32(xdr, &len) < 0)
247                 return false;
248         if (len > SM_MAXSTRLEN)
249                 return false;
250         p = xdr_inline_decode(xdr, len);
251         if (!p)
252                 return false;
253         argp->len = len;
254         argp->mon = (char *)p;
255         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
256                 return false;
257         p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
258         if (!p)
259                 return false;
260         memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
261 
262         return true;
263 }
264 
265 bool
266 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
267 {
268         struct nlm_args *argp = rqstp->rq_argp;
269         struct nlm_lock *lock = &argp->lock;
270 
271         memset(lock, 0, sizeof(*lock));
272         locks_init_lock(&lock->fl);
273         lock->svid = ~(u32)0;
274 
275         if (!svcxdr_decode_cookie(xdr, &argp->cookie))
276                 return false;
277         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
278                 return false;
279         if (!svcxdr_decode_fhandle(xdr, &lock->fh))
280                 return false;
281         if (!svcxdr_decode_owner(xdr, &lock->oh))
282                 return false;
283         /* XXX: Range checks are missing in the original code */
284         if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
285                 return false;
286         if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
287                 return false;
288 
289         return true;
290 }
291 
292 bool
293 nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
294 {
295         struct nlm_args *argp = rqstp->rq_argp;
296         struct nlm_lock *lock = &argp->lock;
297 
298         if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
299                 return false;
300         if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
301                 return false;
302 
303         return true;
304 }
305 
306 
307 /*
308  * Encode Reply results
309  */
310 
311 bool
312 nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
313 {
314         return true;
315 }
316 
317 bool
318 nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
319 {
320         struct nlm_res *resp = rqstp->rq_resp;
321 
322         return svcxdr_encode_cookie(xdr, &resp->cookie) &&
323                 svcxdr_encode_testrply(xdr, resp);
324 }
325 
326 bool
327 nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
328 {
329         struct nlm_res *resp = rqstp->rq_resp;
330 
331         return svcxdr_encode_cookie(xdr, &resp->cookie) &&
332                 svcxdr_encode_stats(xdr, resp->status);
333 }
334 
335 bool
336 nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
337 {
338         struct nlm_res *resp = rqstp->rq_resp;
339 
340         if (!svcxdr_encode_cookie(xdr, &resp->cookie))
341                 return false;
342         if (!svcxdr_encode_stats(xdr, resp->status))
343                 return false;
344         /* sequence */
345         if (xdr_stream_encode_u32(xdr, 0) < 0)
346                 return false;
347 
348         return true;
349 }
350 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php