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_owner = current->files; 130 fl->fl_pid = current->tgid; 131 fl->fl_flags = FL_POSIX; 132 fl->fl_type = F_RDLCK; /* as good as anything else */ 133 start = ntohl(*p++); 134 len = ntohl(*p++); 135 end = start + len - 1; 136 137 fl->fl_start = s32_to_loff_t(start); 138 139 if (len == 0 || end < 0) 140 fl->fl_end = OFFSET_MAX; 141 else 142 fl->fl_end = s32_to_loff_t(end); 143 return p; 144 } 145 146 /* 147 * Encode result of a TEST/TEST_MSG call 148 */ 149 static __be32 * 150 nlm_encode_testres(__be32 *p, struct nlm_res *resp) 151 { 152 s32 start, len; 153 154 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 155 return NULL; 156 *p++ = resp->status; 157 158 if (resp->status == nlm_lck_denied) { 159 struct file_lock *fl = &resp->lock.fl; 160 161 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 162 *p++ = htonl(resp->lock.svid); 163 164 /* Encode owner handle. */ 165 if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 166 return NULL; 167 168 start = loff_t_to_s32(fl->fl_start); 169 if (fl->fl_end == OFFSET_MAX) 170 len = 0; 171 else 172 len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); 173 174 *p++ = htonl(start); 175 *p++ = htonl(len); 176 } 177 178 return p; 179 } 180 181 182 /* 183 * First, the server side XDR functions 184 */ 185 int 186 nlmsvc_decode_testargs(struct svc_rqst *rqstp, __be32 *p) 187 { 188 struct nlm_args *argp = rqstp->rq_argp; 189 u32 exclusive; 190 191 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 192 return 0; 193 194 exclusive = ntohl(*p++); 195 if (!(p = nlm_decode_lock(p, &argp->lock))) 196 return 0; 197 if (exclusive) 198 argp->lock.fl.fl_type = F_WRLCK; 199 200 return xdr_argsize_check(rqstp, p); 201 } 202 203 int 204 nlmsvc_encode_testres(struct svc_rqst *rqstp, __be32 *p) 205 { 206 struct nlm_res *resp = rqstp->rq_resp; 207 208 if (!(p = nlm_encode_testres(p, resp))) 209 return 0; 210 return xdr_ressize_check(rqstp, p); 211 } 212 213 int 214 nlmsvc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p) 215 { 216 struct nlm_args *argp = rqstp->rq_argp; 217 u32 exclusive; 218 219 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 220 return 0; 221 argp->block = ntohl(*p++); 222 exclusive = ntohl(*p++); 223 if (!(p = nlm_decode_lock(p, &argp->lock))) 224 return 0; 225 if (exclusive) 226 argp->lock.fl.fl_type = F_WRLCK; 227 argp->reclaim = ntohl(*p++); 228 argp->state = ntohl(*p++); 229 argp->monitor = 1; /* monitor client by default */ 230 231 return xdr_argsize_check(rqstp, p); 232 } 233 234 int 235 nlmsvc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p) 236 { 237 struct nlm_args *argp = rqstp->rq_argp; 238 u32 exclusive; 239 240 if (!(p = nlm_decode_cookie(p, &argp->cookie))) 241 return 0; 242 argp->block = ntohl(*p++); 243 exclusive = ntohl(*p++); 244 if (!(p = nlm_decode_lock(p, &argp->lock))) 245 return 0; 246 if (exclusive) 247 argp->lock.fl.fl_type = F_WRLCK; 248 return xdr_argsize_check(rqstp, p); 249 } 250 251 int 252 nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p) 253 { 254 struct nlm_args *argp = rqstp->rq_argp; 255 256 if (!(p = nlm_decode_cookie(p, &argp->cookie)) 257 || !(p = nlm_decode_lock(p, &argp->lock))) 258 return 0; 259 argp->lock.fl.fl_type = F_UNLCK; 260 return xdr_argsize_check(rqstp, p); 261 } 262 263 int 264 nlmsvc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p) 265 { 266 struct nlm_args *argp = rqstp->rq_argp; 267 struct nlm_lock *lock = &argp->lock; 268 269 memset(lock, 0, sizeof(*lock)); 270 locks_init_lock(&lock->fl); 271 lock->svid = ~(u32) 0; 272 lock->fl.fl_pid = current->tgid; 273 274 if (!(p = nlm_decode_cookie(p, &argp->cookie)) 275 || !(p = xdr_decode_string_inplace(p, &lock->caller, 276 &lock->len, NLM_MAXSTRLEN)) 277 || !(p = nlm_decode_fh(p, &lock->fh)) 278 || !(p = nlm_decode_oh(p, &lock->oh))) 279 return 0; 280 argp->fsm_mode = ntohl(*p++); 281 argp->fsm_access = ntohl(*p++); 282 return xdr_argsize_check(rqstp, p); 283 } 284 285 int 286 nlmsvc_encode_shareres(struct svc_rqst *rqstp, __be32 *p) 287 { 288 struct nlm_res *resp = rqstp->rq_resp; 289 290 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 291 return 0; 292 *p++ = resp->status; 293 *p++ = xdr_zero; /* sequence argument */ 294 return xdr_ressize_check(rqstp, p); 295 } 296 297 int 298 nlmsvc_encode_res(struct svc_rqst *rqstp, __be32 *p) 299 { 300 struct nlm_res *resp = rqstp->rq_resp; 301 302 if (!(p = nlm_encode_cookie(p, &resp->cookie))) 303 return 0; 304 *p++ = resp->status; 305 return xdr_ressize_check(rqstp, p); 306 } 307 308 int 309 nlmsvc_decode_notify(struct svc_rqst *rqstp, __be32 *p) 310 { 311 struct nlm_args *argp = rqstp->rq_argp; 312 struct nlm_lock *lock = &argp->lock; 313 314 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 315 &lock->len, NLM_MAXSTRLEN))) 316 return 0; 317 argp->state = ntohl(*p++); 318 return xdr_argsize_check(rqstp, p); 319 } 320 321 int 322 nlmsvc_decode_reboot(struct svc_rqst *rqstp, __be32 *p) 323 { 324 struct nlm_reboot *argp = rqstp->rq_argp; 325 326 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 327 return 0; 328 argp->state = ntohl(*p++); 329 memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 330 p += XDR_QUADLEN(SM_PRIV_SIZE); 331 return xdr_argsize_check(rqstp, p); 332 } 333 334 int 335 nlmsvc_decode_res(struct svc_rqst *rqstp, __be32 *p) 336 { 337 struct nlm_res *resp = rqstp->rq_argp; 338 339 if (!(p = nlm_decode_cookie(p, &resp->cookie))) 340 return 0; 341 resp->status = *p++; 342 return xdr_argsize_check(rqstp, p); 343 } 344 345 int 346 nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p) 347 { 348 return xdr_argsize_check(rqstp, p); 349 } 350 351 int 352 nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p) 353 { 354 return xdr_ressize_check(rqstp, p); 355 } 356