1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/lockd/svc4proc.c 4 * 5 * Lockd server procedures. We don't implement the NLM_*_RES 6 * procedures because we don't use the async procedures. 7 * 8 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 9 */ 10 11 #include <linux/types.h> 12 #include <linux/time.h> 13 #include <linux/lockd/lockd.h> 14 #include <linux/lockd/share.h> 15 #include <linux/sunrpc/svc_xprt.h> 16 17 #define NLMDBG_FACILITY NLMDBG_CLIENT 18 19 /* 20 * Obtain client and file from arguments 21 */ 22 static __be32 23 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 24 struct nlm_host **hostp, struct nlm_file **filp) 25 { 26 struct nlm_host *host = NULL; 27 struct nlm_file *file = NULL; 28 struct nlm_lock *lock = &argp->lock; 29 __be32 error = 0; 30 31 /* nfsd callbacks must have been installed for this procedure */ 32 if (!nlmsvc_ops) 33 return nlm_lck_denied_nolocks; 34 35 /* Obtain host handle */ 36 if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) 37 || (argp->monitor && nsm_monitor(host) < 0)) 38 goto no_locks; 39 *hostp = host; 40 41 /* Obtain file pointer. Not used by FREE_ALL call. */ 42 if (filp != NULL) { 43 if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) 44 goto no_locks; 45 *filp = file; 46 47 /* Set up the missing parts of the file_lock structure */ 48 lock->fl.fl_file = file->f_file; 49 lock->fl.fl_owner = (fl_owner_t) host; 50 lock->fl.fl_lmops = &nlmsvc_lock_operations; 51 } 52 53 return 0; 54 55 no_locks: 56 nlmsvc_release_host(host); 57 if (error) 58 return error; 59 return nlm_lck_denied_nolocks; 60 } 61 62 /* 63 * NULL: Test for presence of service 64 */ 65 static __be32 66 nlm4svc_proc_null(struct svc_rqst *rqstp) 67 { 68 dprintk("lockd: NULL called\n"); 69 return rpc_success; 70 } 71 72 /* 73 * TEST: Check for conflicting lock 74 */ 75 static __be32 76 __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp) 77 { 78 struct nlm_args *argp = rqstp->rq_argp; 79 struct nlm_host *host; 80 struct nlm_file *file; 81 __be32 rc = rpc_success; 82 83 dprintk("lockd: TEST4 called\n"); 84 resp->cookie = argp->cookie; 85 86 /* Obtain client and file */ 87 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 88 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 89 90 /* Now check for conflicting locks */ 91 resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie); 92 if (resp->status == nlm_drop_reply) 93 rc = rpc_drop_reply; 94 else 95 dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); 96 97 nlmsvc_release_host(host); 98 nlm_release_file(file); 99 return rc; 100 } 101 102 static __be32 103 nlm4svc_proc_test(struct svc_rqst *rqstp) 104 { 105 return __nlm4svc_proc_test(rqstp, rqstp->rq_resp); 106 } 107 108 static __be32 109 __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp) 110 { 111 struct nlm_args *argp = rqstp->rq_argp; 112 struct nlm_host *host; 113 struct nlm_file *file; 114 __be32 rc = rpc_success; 115 116 dprintk("lockd: LOCK called\n"); 117 118 resp->cookie = argp->cookie; 119 120 /* Obtain client and file */ 121 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 122 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 123 124 #if 0 125 /* If supplied state doesn't match current state, we assume it's 126 * an old request that time-warped somehow. Any error return would 127 * do in this case because it's irrelevant anyway. 128 * 129 * NB: We don't retrieve the remote host's state yet. 130 */ 131 if (host->h_nsmstate && host->h_nsmstate != argp->state) { 132 resp->status = nlm_lck_denied_nolocks; 133 } else 134 #endif 135 136 /* Now try to lock the file */ 137 resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock, 138 argp->block, &argp->cookie, 139 argp->reclaim); 140 if (resp->status == nlm_drop_reply) 141 rc = rpc_drop_reply; 142 else 143 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 144 145 nlmsvc_release_host(host); 146 nlm_release_file(file); 147 return rc; 148 } 149 150 static __be32 151 nlm4svc_proc_lock(struct svc_rqst *rqstp) 152 { 153 return __nlm4svc_proc_lock(rqstp, rqstp->rq_resp); 154 } 155 156 static __be32 157 __nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp) 158 { 159 struct nlm_args *argp = rqstp->rq_argp; 160 struct nlm_host *host; 161 struct nlm_file *file; 162 163 dprintk("lockd: CANCEL called\n"); 164 165 resp->cookie = argp->cookie; 166 167 /* Don't accept requests during grace period */ 168 if (locks_in_grace(SVC_NET(rqstp))) { 169 resp->status = nlm_lck_denied_grace_period; 170 return rpc_success; 171 } 172 173 /* Obtain client and file */ 174 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 175 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 176 177 /* Try to cancel request. */ 178 resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock); 179 180 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 181 nlmsvc_release_host(host); 182 nlm_release_file(file); 183 return rpc_success; 184 } 185 186 static __be32 187 nlm4svc_proc_cancel(struct svc_rqst *rqstp) 188 { 189 return __nlm4svc_proc_cancel(rqstp, rqstp->rq_resp); 190 } 191 192 /* 193 * UNLOCK: release a lock 194 */ 195 static __be32 196 __nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp) 197 { 198 struct nlm_args *argp = rqstp->rq_argp; 199 struct nlm_host *host; 200 struct nlm_file *file; 201 202 dprintk("lockd: UNLOCK called\n"); 203 204 resp->cookie = argp->cookie; 205 206 /* Don't accept new lock requests during grace period */ 207 if (locks_in_grace(SVC_NET(rqstp))) { 208 resp->status = nlm_lck_denied_grace_period; 209 return rpc_success; 210 } 211 212 /* Obtain client and file */ 213 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 214 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 215 216 /* Now try to remove the lock */ 217 resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock); 218 219 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 220 nlmsvc_release_host(host); 221 nlm_release_file(file); 222 return rpc_success; 223 } 224 225 static __be32 226 nlm4svc_proc_unlock(struct svc_rqst *rqstp) 227 { 228 return __nlm4svc_proc_unlock(rqstp, rqstp->rq_resp); 229 } 230 231 /* 232 * GRANTED: A server calls us to tell that a process' lock request 233 * was granted 234 */ 235 static __be32 236 __nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp) 237 { 238 struct nlm_args *argp = rqstp->rq_argp; 239 240 resp->cookie = argp->cookie; 241 242 dprintk("lockd: GRANTED called\n"); 243 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock); 244 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 245 return rpc_success; 246 } 247 248 static __be32 249 nlm4svc_proc_granted(struct svc_rqst *rqstp) 250 { 251 return __nlm4svc_proc_granted(rqstp, rqstp->rq_resp); 252 } 253 254 /* 255 * This is the generic lockd callback for async RPC calls 256 */ 257 static void nlm4svc_callback_exit(struct rpc_task *task, void *data) 258 { 259 dprintk("lockd: %5u callback returned %d\n", task->tk_pid, 260 -task->tk_status); 261 } 262 263 static void nlm4svc_callback_release(void *data) 264 { 265 nlmsvc_release_call(data); 266 } 267 268 static const struct rpc_call_ops nlm4svc_callback_ops = { 269 .rpc_call_done = nlm4svc_callback_exit, 270 .rpc_release = nlm4svc_callback_release, 271 }; 272 273 /* 274 * `Async' versions of the above service routines. They aren't really, 275 * because we send the callback before the reply proper. I hope this 276 * doesn't break any clients. 277 */ 278 static __be32 nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, 279 __be32 (*func)(struct svc_rqst *, struct nlm_res *)) 280 { 281 struct nlm_args *argp = rqstp->rq_argp; 282 struct nlm_host *host; 283 struct nlm_rqst *call; 284 __be32 stat; 285 286 host = nlmsvc_lookup_host(rqstp, 287 argp->lock.caller, 288 argp->lock.len); 289 if (host == NULL) 290 return rpc_system_err; 291 292 call = nlm_alloc_call(host); 293 nlmsvc_release_host(host); 294 if (call == NULL) 295 return rpc_system_err; 296 297 stat = func(rqstp, &call->a_res); 298 if (stat != 0) { 299 nlmsvc_release_call(call); 300 return stat; 301 } 302 303 call->a_flags = RPC_TASK_ASYNC; 304 if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0) 305 return rpc_system_err; 306 return rpc_success; 307 } 308 309 static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp) 310 { 311 dprintk("lockd: TEST_MSG called\n"); 312 return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, __nlm4svc_proc_test); 313 } 314 315 static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp) 316 { 317 dprintk("lockd: LOCK_MSG called\n"); 318 return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, __nlm4svc_proc_lock); 319 } 320 321 static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp) 322 { 323 dprintk("lockd: CANCEL_MSG called\n"); 324 return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, __nlm4svc_proc_cancel); 325 } 326 327 static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp) 328 { 329 dprintk("lockd: UNLOCK_MSG called\n"); 330 return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlm4svc_proc_unlock); 331 } 332 333 static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp) 334 { 335 dprintk("lockd: GRANTED_MSG called\n"); 336 return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, __nlm4svc_proc_granted); 337 } 338 339 /* 340 * SHARE: create a DOS share or alter existing share. 341 */ 342 static __be32 343 nlm4svc_proc_share(struct svc_rqst *rqstp) 344 { 345 struct nlm_args *argp = rqstp->rq_argp; 346 struct nlm_res *resp = rqstp->rq_resp; 347 struct nlm_host *host; 348 struct nlm_file *file; 349 350 dprintk("lockd: SHARE called\n"); 351 352 resp->cookie = argp->cookie; 353 354 /* Don't accept new lock requests during grace period */ 355 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { 356 resp->status = nlm_lck_denied_grace_period; 357 return rpc_success; 358 } 359 360 /* Obtain client and file */ 361 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 362 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 363 364 /* Now try to create the share */ 365 resp->status = nlmsvc_share_file(host, file, argp); 366 367 dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 368 nlmsvc_release_host(host); 369 nlm_release_file(file); 370 return rpc_success; 371 } 372 373 /* 374 * UNSHARE: Release a DOS share. 375 */ 376 static __be32 377 nlm4svc_proc_unshare(struct svc_rqst *rqstp) 378 { 379 struct nlm_args *argp = rqstp->rq_argp; 380 struct nlm_res *resp = rqstp->rq_resp; 381 struct nlm_host *host; 382 struct nlm_file *file; 383 384 dprintk("lockd: UNSHARE called\n"); 385 386 resp->cookie = argp->cookie; 387 388 /* Don't accept requests during grace period */ 389 if (locks_in_grace(SVC_NET(rqstp))) { 390 resp->status = nlm_lck_denied_grace_period; 391 return rpc_success; 392 } 393 394 /* Obtain client and file */ 395 if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file))) 396 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 397 398 /* Now try to lock the file */ 399 resp->status = nlmsvc_unshare_file(host, file, argp); 400 401 dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 402 nlmsvc_release_host(host); 403 nlm_release_file(file); 404 return rpc_success; 405 } 406 407 /* 408 * NM_LOCK: Create an unmonitored lock 409 */ 410 static __be32 411 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp) 412 { 413 struct nlm_args *argp = rqstp->rq_argp; 414 415 dprintk("lockd: NM_LOCK called\n"); 416 417 argp->monitor = 0; /* just clean the monitor flag */ 418 return nlm4svc_proc_lock(rqstp); 419 } 420 421 /* 422 * FREE_ALL: Release all locks and shares held by client 423 */ 424 static __be32 425 nlm4svc_proc_free_all(struct svc_rqst *rqstp) 426 { 427 struct nlm_args *argp = rqstp->rq_argp; 428 struct nlm_host *host; 429 430 /* Obtain client */ 431 if (nlm4svc_retrieve_args(rqstp, argp, &host, NULL)) 432 return rpc_success; 433 434 nlmsvc_free_host_resources(host); 435 nlmsvc_release_host(host); 436 return rpc_success; 437 } 438 439 /* 440 * SM_NOTIFY: private callback from statd (not part of official NLM proto) 441 */ 442 static __be32 443 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp) 444 { 445 struct nlm_reboot *argp = rqstp->rq_argp; 446 447 dprintk("lockd: SM_NOTIFY called\n"); 448 449 if (!nlm_privileged_requester(rqstp)) { 450 char buf[RPC_MAX_ADDRBUFLEN]; 451 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 452 svc_print_addr(rqstp, buf, sizeof(buf))); 453 return rpc_system_err; 454 } 455 456 nlm_host_rebooted(SVC_NET(rqstp), argp); 457 return rpc_success; 458 } 459 460 /* 461 * client sent a GRANTED_RES, let's remove the associated block 462 */ 463 static __be32 464 nlm4svc_proc_granted_res(struct svc_rqst *rqstp) 465 { 466 struct nlm_res *argp = rqstp->rq_argp; 467 468 if (!nlmsvc_ops) 469 return rpc_success; 470 471 dprintk("lockd: GRANTED_RES called\n"); 472 473 nlmsvc_grant_reply(&argp->cookie, argp->status); 474 return rpc_success; 475 } 476 477 478 /* 479 * NLM Server procedures. 480 */ 481 482 #define nlm4svc_encode_norep nlm4svc_encode_void 483 #define nlm4svc_decode_norep nlm4svc_decode_void 484 #define nlm4svc_decode_testres nlm4svc_decode_void 485 #define nlm4svc_decode_lockres nlm4svc_decode_void 486 #define nlm4svc_decode_unlockres nlm4svc_decode_void 487 #define nlm4svc_decode_cancelres nlm4svc_decode_void 488 #define nlm4svc_decode_grantedres nlm4svc_decode_void 489 490 #define nlm4svc_proc_none nlm4svc_proc_null 491 #define nlm4svc_proc_test_res nlm4svc_proc_null 492 #define nlm4svc_proc_lock_res nlm4svc_proc_null 493 #define nlm4svc_proc_cancel_res nlm4svc_proc_null 494 #define nlm4svc_proc_unlock_res nlm4svc_proc_null 495 496 struct nlm_void { int dummy; }; 497 498 #define PROC(name, xargt, xrest, argt, rest, respsize) \ 499 { .pc_func = nlm4svc_proc_##name, \ 500 .pc_decode = nlm4svc_decode_##xargt, \ 501 .pc_encode = nlm4svc_encode_##xrest, \ 502 .pc_release = NULL, \ 503 .pc_argsize = sizeof(struct nlm_##argt), \ 504 .pc_ressize = sizeof(struct nlm_##rest), \ 505 .pc_xdrressize = respsize, \ 506 } 507 #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ 508 #define No (1+1024/4) /* netobj */ 509 #define St 1 /* status */ 510 #define Rg 4 /* range (offset + length) */ 511 const struct svc_procedure nlmsvc_procedures4[] = { 512 PROC(null, void, void, void, void, 1), 513 PROC(test, testargs, testres, args, res, Ck+St+2+No+Rg), 514 PROC(lock, lockargs, res, args, res, Ck+St), 515 PROC(cancel, cancargs, res, args, res, Ck+St), 516 PROC(unlock, unlockargs, res, args, res, Ck+St), 517 PROC(granted, testargs, res, args, res, Ck+St), 518 PROC(test_msg, testargs, norep, args, void, 1), 519 PROC(lock_msg, lockargs, norep, args, void, 1), 520 PROC(cancel_msg, cancargs, norep, args, void, 1), 521 PROC(unlock_msg, unlockargs, norep, args, void, 1), 522 PROC(granted_msg, testargs, norep, args, void, 1), 523 PROC(test_res, testres, norep, res, void, 1), 524 PROC(lock_res, lockres, norep, res, void, 1), 525 PROC(cancel_res, cancelres, norep, res, void, 1), 526 PROC(unlock_res, unlockres, norep, res, void, 1), 527 PROC(granted_res, res, norep, res, void, 1), 528 /* statd callback */ 529 PROC(sm_notify, reboot, void, reboot, void, 1), 530 PROC(none, void, void, void, void, 0), 531 PROC(none, void, void, void, void, 0), 532 PROC(none, void, void, void, void, 0), 533 PROC(share, shareargs, shareres, args, res, Ck+St+1), 534 PROC(unshare, shareargs, shareres, args, res, Ck+St+1), 535 PROC(nm_lock, lockargs, res, args, res, Ck+St), 536 PROC(free_all, notify, void, args, void, 1), 537 538 }; 539