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 loff_t 24 s64_to_loff_t(__s64 offset) 25 { 26 return (loff_t)offset; 27 } 28 29 30 static inline s64 31 loff_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 */ 48 static bool 49 svcxdr_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 69 static bool 70 svcxdr_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 102 static bool 103 svcxdr_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 128 static bool 129 svcxdr_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 147 int 148 nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p) 149 { 150 return 1; 151 } 152 153 int 154 nlm4svc_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 172 int 173 nlm4svc_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 198 int 199 nlm4svc_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 218 int 219 nlm4svc_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 233 int 234 nlm4svc_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 247 int 248 nlm4svc_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 273 int 274 nlm4svc_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 301 int 302 nlm4svc_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 321 int 322 nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p) 323 { 324 return 1; 325 } 326 327 int 328 nlm4svc_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 337 int 338 nlm4svc_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 347 int 348 nlm4svc_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 } 363