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 /* 46 * XDR functions for basic NLM types 47 */ 48 static __be32 * 49 nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) 50 { 51 unsigned int len; 52 53 len = ntohl(*p++); 54 55 if(len==0) 56 { 57 c->len=4; 58 memset(c->data, 0, 4); /* hockeypux brain damage */ 59 } 60 else if(len<=NLM_MAXCOOKIELEN) 61 { 62 c->len=len; 63 memcpy(c->data, p, len); 64 p+=XDR_QUADLEN(len); 65 } 66 else 67 { 68 dprintk("lockd: bad cookie size %d (only cookies under " 69 "%d bytes are supported.)\n", 70 len, NLM_MAXCOOKIELEN); 71 return NULL; 72 } 73 return p; 74 } 75 76 static __be32 * 77 nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) 78 { 79 *p++ = htonl(c->len); 80 memcpy(p, c->data, c->len); 81 p+=XDR_QUADLEN(c->len); 82 return p; 83 } 84 85 static __be32 * 86 nlm4_decode_fh(__be32 *p, struct nfs_fh *f) 87 { 88 memset(f->data, 0, sizeof(f->data)); 89 f->size = ntohl(*p++); 90 if (f->size > NFS_MAXFHSIZE) { 91 dprintk("lockd: bad fhandle size %d (should be <=%d)\n", 92 f->size, NFS_MAXFHSIZE); 93 return NULL; 94 } 95 memcpy(f->data, p, f->size); 96 return p + XDR_QUADLEN(f->size); 97 } 98 99 /* 100 * Encode and decode owner handle 101 */ 102 static __be32 * 103 nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) 104 { 105 return xdr_decode_netobj(p, oh); 106 } 107 108 static __be32 * 109 nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) 110 { 111 struct file_lock *fl = &lock->fl; 112 __u64 len, start; 113 __s64 end; 114 115 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 116 &lock->len, NLM_MAXSTRLEN)) 117 || !(p = nlm4_decode_fh(p, &lock->fh)) 118 || !(p = nlm4_decode_oh(p, &lock->oh))) 119 return NULL; 120 lock->svid = ntohl(*p++); 121 122 locks_init_lock(fl); 123 fl->fl_flags = FL_POSIX; 124 fl->fl_type = F_RDLCK; /* as good as anything else */ 125 p = xdr_decode_hyper(p, &start); 126 p = xdr_decode_hyper(p, &len); 127 end = start + len - 1; 128 129 fl->fl_start = s64_to_loff_t(start); 130 131 if (len == 0 || end < 0) 132 fl->fl_end = OFFSET_MAX; 133 else 134 fl->fl_end = s64_to_loff_t(end); 135 return p; 136 } 137 138 /* 139 * Encode result of a TEST/TEST_MSG call 140 */ 141 static __be32 * 142 nlm4_encode_testres(__be32 *p, struct nlm_res *resp) 143 { 144 s64 start, len; 145 146 dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); 147 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 148 return NULL; 149 *p++ = resp->status; 150 151 if (resp->status == nlm_lck_denied) { 152 struct file_lock *fl = &resp->lock.fl; 153 154 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 155 *p++ = htonl(resp->lock.svid); 156 157 /* Encode owner handle. */ 158 if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 159 return NULL; 160 161 start = loff_t_to_s64(fl->fl_start); 162 if (fl->fl_end == OFFSET_MAX) 163 len = 0; 164 else 165 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 166 167 p = xdr_encode_hyper(p, start); 168 p = xdr_encode_hyper(p, len); 169 dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n", 170 resp->status, (int)resp->lock.svid, fl->fl_type, 171 (long long)fl->fl_start, (long long)fl->fl_end); 172 } 173 174 dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); 175 return p; 176 } 177 178 179 /* 180 * Decode Call arguments 181 */ 182 183 int 184 nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p) 185 { 186 return 1; 187 } 188 189 int 190 nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) 191 { 192 struct nlm_args *argp = rqstp->rq_argp; 193 u32 exclusive; 194 195 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 196 return 0; 197 198 exclusive = ntohl(*p++); 199 if (!(p = nlm4_decode_lock(p, &argp->lock))) 200 return 0; 201 if (exclusive) 202 argp->lock.fl.fl_type = F_WRLCK; 203 204 return xdr_argsize_check(rqstp, p); 205 } 206 207 int 208 nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 209 { 210 struct nlm_res *resp = rqstp->rq_resp; 211 212 if (!(p = nlm4_encode_testres(p, resp))) 213 return 0; 214 return xdr_ressize_check(rqstp, p); 215 } 216 217 int 218 nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) 219 { 220 struct nlm_args *argp = rqstp->rq_argp; 221 u32 exclusive; 222 223 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 224 return 0; 225 argp->block = ntohl(*p++); 226 exclusive = ntohl(*p++); 227 if (!(p = nlm4_decode_lock(p, &argp->lock))) 228 return 0; 229 if (exclusive) 230 argp->lock.fl.fl_type = F_WRLCK; 231 argp->reclaim = ntohl(*p++); 232 argp->state = ntohl(*p++); 233 argp->monitor = 1; /* monitor client by default */ 234 235 return xdr_argsize_check(rqstp, p); 236 } 237 238 int 239 nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) 240 { 241 struct nlm_args *argp = rqstp->rq_argp; 242 u32 exclusive; 243 244 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 245 return 0; 246 argp->block = ntohl(*p++); 247 exclusive = ntohl(*p++); 248 if (!(p = nlm4_decode_lock(p, &argp->lock))) 249 return 0; 250 if (exclusive) 251 argp->lock.fl.fl_type = F_WRLCK; 252 return xdr_argsize_check(rqstp, p); 253 } 254 255 int 256 nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) 257 { 258 struct nlm_args *argp = rqstp->rq_argp; 259 260 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 261 || !(p = nlm4_decode_lock(p, &argp->lock))) 262 return 0; 263 argp->lock.fl.fl_type = F_UNLCK; 264 return xdr_argsize_check(rqstp, p); 265 } 266 267 int 268 nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 269 { 270 struct nlm_args *argp = rqstp->rq_argp; 271 struct nlm_lock *lock = &argp->lock; 272 273 memset(lock, 0, sizeof(*lock)); 274 locks_init_lock(&lock->fl); 275 lock->svid = ~(u32) 0; 276 277 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 278 || !(p = xdr_decode_string_inplace(p, &lock->caller, 279 &lock->len, NLM_MAXSTRLEN)) 280 || !(p = nlm4_decode_fh(p, &lock->fh)) 281 || !(p = nlm4_decode_oh(p, &lock->oh))) 282 return 0; 283 argp->fsm_mode = ntohl(*p++); 284 argp->fsm_access = ntohl(*p++); 285 return xdr_argsize_check(rqstp, p); 286 } 287 288 int 289 nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 290 { 291 struct nlm_res *resp = rqstp->rq_resp; 292 293 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 294 return 0; 295 *p++ = resp->status; 296 *p++ = xdr_zero; /* sequence argument */ 297 return xdr_ressize_check(rqstp, p); 298 } 299 300 int 301 nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p) 302 { 303 struct nlm_res *resp = rqstp->rq_resp; 304 305 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 306 return 0; 307 *p++ = resp->status; 308 return xdr_ressize_check(rqstp, p); 309 } 310 311 int 312 nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 313 { 314 struct nlm_args *argp = rqstp->rq_argp; 315 struct nlm_lock *lock = &argp->lock; 316 317 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 318 &lock->len, NLM_MAXSTRLEN))) 319 return 0; 320 argp->state = ntohl(*p++); 321 return xdr_argsize_check(rqstp, p); 322 } 323 324 int 325 nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 326 { 327 struct nlm_reboot *argp = rqstp->rq_argp; 328 329 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 330 return 0; 331 argp->state = ntohl(*p++); 332 memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 333 p += XDR_QUADLEN(SM_PRIV_SIZE); 334 return xdr_argsize_check(rqstp, p); 335 } 336 337 int 338 nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p) 339 { 340 struct nlm_res *resp = rqstp->rq_argp; 341 342 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 343 return 0; 344 resp->status = *p++; 345 return xdr_argsize_check(rqstp, p); 346 } 347 348 int 349 nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p) 350 { 351 return xdr_ressize_check(rqstp, p); 352 } 353