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