Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.15-rc4 364 lines 7.9 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#include "svcxdr.h" 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 * 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 */ 50static bool 51svcxdr_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 71static bool 72svcxdr_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 103static bool 104svcxdr_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 129static bool 130svcxdr_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 148int 149nlmsvc_decode_void(struct svc_rqst *rqstp, __be32 *p) 150{ 151 return 1; 152} 153 154int 155nlmsvc_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 173int 174nlmsvc_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 199int 200nlmsvc_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 220int 221nlmsvc_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 235int 236nlmsvc_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 249int 250nlmsvc_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 275int 276nlmsvc_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 303int 304nlmsvc_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 323int 324nlmsvc_encode_void(struct svc_rqst *rqstp, __be32 *p) 325{ 326 return 1; 327} 328 329int 330nlmsvc_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 339int 340nlmsvc_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 349int 350nlmsvc_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}