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 bool 148 nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr) 149 { 150 return true; 151 } 152 153 bool 154 nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 155 { 156 struct nlm_args *argp = rqstp->rq_argp; 157 u32 exclusive; 158 159 if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 160 return false; 161 if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 162 return false; 163 if (!svcxdr_decode_lock(xdr, &argp->lock)) 164 return false; 165 if (exclusive) 166 argp->lock.fl.fl_type = F_WRLCK; 167 168 return true; 169 } 170 171 bool 172 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 173 { 174 struct nlm_args *argp = rqstp->rq_argp; 175 u32 exclusive; 176 177 if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 178 return false; 179 if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 180 return false; 181 if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 182 return false; 183 if (!svcxdr_decode_lock(xdr, &argp->lock)) 184 return false; 185 if (exclusive) 186 argp->lock.fl.fl_type = F_WRLCK; 187 if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0) 188 return false; 189 if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 190 return false; 191 argp->monitor = 1; /* monitor client by default */ 192 193 return true; 194 } 195 196 bool 197 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 198 { 199 struct nlm_args *argp = rqstp->rq_argp; 200 u32 exclusive; 201 202 if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 203 return false; 204 if (xdr_stream_decode_bool(xdr, &argp->block) < 0) 205 return false; 206 if (xdr_stream_decode_bool(xdr, &exclusive) < 0) 207 return false; 208 if (!svcxdr_decode_lock(xdr, &argp->lock)) 209 return false; 210 if (exclusive) 211 argp->lock.fl.fl_type = F_WRLCK; 212 213 return true; 214 } 215 216 bool 217 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 218 { 219 struct nlm_args *argp = rqstp->rq_argp; 220 221 if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 222 return false; 223 if (!svcxdr_decode_lock(xdr, &argp->lock)) 224 return false; 225 argp->lock.fl.fl_type = F_UNLCK; 226 227 return true; 228 } 229 230 bool 231 nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr) 232 { 233 struct nlm_res *resp = rqstp->rq_argp; 234 235 if (!svcxdr_decode_cookie(xdr, &resp->cookie)) 236 return false; 237 if (!svcxdr_decode_stats(xdr, &resp->status)) 238 return false; 239 240 return true; 241 } 242 243 bool 244 nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr) 245 { 246 struct nlm_reboot *argp = rqstp->rq_argp; 247 __be32 *p; 248 u32 len; 249 250 if (xdr_stream_decode_u32(xdr, &len) < 0) 251 return false; 252 if (len > SM_MAXSTRLEN) 253 return false; 254 p = xdr_inline_decode(xdr, len); 255 if (!p) 256 return false; 257 argp->len = len; 258 argp->mon = (char *)p; 259 if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 260 return false; 261 p = xdr_inline_decode(xdr, SM_PRIV_SIZE); 262 if (!p) 263 return false; 264 memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 265 266 return true; 267 } 268 269 bool 270 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) 271 { 272 struct nlm_args *argp = rqstp->rq_argp; 273 struct nlm_lock *lock = &argp->lock; 274 275 memset(lock, 0, sizeof(*lock)); 276 locks_init_lock(&lock->fl); 277 lock->svid = ~(u32)0; 278 279 if (!svcxdr_decode_cookie(xdr, &argp->cookie)) 280 return false; 281 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 282 return false; 283 if (!svcxdr_decode_fhandle(xdr, &lock->fh)) 284 return false; 285 if (!svcxdr_decode_owner(xdr, &lock->oh)) 286 return false; 287 /* XXX: Range checks are missing in the original code */ 288 if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0) 289 return false; 290 if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0) 291 return false; 292 293 return true; 294 } 295 296 bool 297 nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr) 298 { 299 struct nlm_args *argp = rqstp->rq_argp; 300 struct nlm_lock *lock = &argp->lock; 301 302 if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) 303 return false; 304 if (xdr_stream_decode_u32(xdr, &argp->state) < 0) 305 return false; 306 307 return true; 308 } 309 310 311 /* 312 * Encode Reply results 313 */ 314 315 bool 316 nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr) 317 { 318 return true; 319 } 320 321 bool 322 nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 323 { 324 struct nlm_res *resp = rqstp->rq_resp; 325 326 return svcxdr_encode_cookie(xdr, &resp->cookie) && 327 svcxdr_encode_testrply(xdr, resp); 328 } 329 330 bool 331 nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr) 332 { 333 struct nlm_res *resp = rqstp->rq_resp; 334 335 return svcxdr_encode_cookie(xdr, &resp->cookie) && 336 svcxdr_encode_stats(xdr, resp->status); 337 } 338 339 bool 340 nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr) 341 { 342 struct nlm_res *resp = rqstp->rq_resp; 343 344 if (!svcxdr_encode_cookie(xdr, &resp->cookie)) 345 return false; 346 if (!svcxdr_encode_stats(xdr, resp->status)) 347 return false; 348 /* sequence */ 349 if (xdr_stream_encode_u32(xdr, 0) < 0) 350 return false; 351 352 return true; 353 } 354