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