Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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