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