Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.2-rc3 355 lines 7.5 kB view raw
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 25static inline loff_t 26s32_to_loff_t(__s32 offset) 27{ 28 return (loff_t)offset; 29} 30 31static inline __s32 32loff_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 */ 47static __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 74static inline __be32 * 75nlm_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 83static __be32 * 84nlm_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 */ 102static inline __be32 * 103nlm_decode_oh(__be32 *p, struct xdr_netobj *oh) 104{ 105 return xdr_decode_netobj(p, oh); 106} 107 108static inline __be32 * 109nlm_encode_oh(__be32 *p, struct xdr_netobj *oh) 110{ 111 return xdr_encode_netobj(p, oh); 112} 113 114static __be32 * 115nlm_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 = (pid_t)lock->svid; 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 */ 149static __be32 * 150nlm_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 */ 185int 186nlmsvc_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 203int 204nlmsvc_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 213int 214nlmsvc_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 234int 235nlmsvc_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 251int 252nlmsvc_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 263int 264nlmsvc_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 = (pid_t)lock->svid; 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 285int 286nlmsvc_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 297int 298nlmsvc_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 308int 309nlmsvc_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 321int 322nlmsvc_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 334int 335nlmsvc_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 345int 346nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p) 347{ 348 return xdr_argsize_check(rqstp, p); 349} 350 351int 352nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p) 353{ 354 return xdr_ressize_check(rqstp, p); 355}