1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 1993-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 #include "os/os.h" 25 26 #include "rmapi/rmapi.h" 27 #include "rmapi/rs_utils.h" 28 #include "rmapi/client.h" 29 #include "rmapi/client_resource.h" 30 #include "rmapi/resource_fwd_decls.h" 31 #include "core/locks.h" 32 #include "core/system.h" 33 #include "resource_desc.h" 34 #include "gpu_mgr/gpu_mgr.h" 35 #include "gpu/gpu.h" 36 #include "gpu/mmu/kern_gmmu.h" 37 38 #include "gpu/bus/third_party_p2p.h" 39 #include "virtualization/hypervisor/hypervisor.h" 40 41 OsInfoMap g_osInfoList; 42 UserInfoList g_userInfoList; 43 RmClientList g_clientListBehindGpusLock; // RS-TODO remove this WAR 44 45 #define RS_FW_UNIQUE_HANDLE_BASE (0xc9f00000) 46 47 static NV_STATUS _registerUserInfo(PUID_TOKEN *ppUidToken, UserInfo **ppUserInfo); 48 static NV_STATUS _unregisterUserInfo(UserInfo *pUserInfo); 49 static NV_STATUS _registerOSInfo(RmClient *pClient, void *pOSInfo); 50 static NV_STATUS _unregisterOSInfo(RmClient *pClient, void *pOSInfo); 51 52 NV_STATUS 53 rmclientConstruct_IMPL 54 ( 55 RmClient *pClient, 56 PORT_MEM_ALLOCATOR* pAllocator, 57 RS_RES_ALLOC_PARAMS_INTERNAL* pParams 58 ) 59 { 60 NV_STATUS status = NV_OK; 61 NvU32 i; 62 OBJSYS *pSys = SYS_GET_INSTANCE(); 63 RsClient *pRsClient = staticCast(pClient, RsClient); 64 NvBool bReleaseLock = NV_FALSE; 65 API_SECURITY_INFO *pSecInfo = pParams->pSecInfo; 66 OBJGPU *pGpu = NULL; 67 68 // RM client objects can only be created/destroyed with the RW API lock. 69 LOCK_ASSERT_AND_RETURN(rmapiLockIsWriteOwner()); 70 71 if (RMCFG_FEATURE_PLATFORM_GSP) 72 { 73 pGpu = gpumgrGetSomeGpu(); 74 75 if (pGpu == NULL) 76 { 77 NV_PRINTF(LEVEL_ERROR, "GPU is not found\n"); 78 return NV_ERR_INVALID_STATE; 79 } 80 } 81 82 pClient->bIsRootNonPriv = (pParams->externalClassId == NV01_ROOT_NON_PRIV); 83 pClient->pUserInfo = NULL; 84 pClient->pSecurityToken = NULL; 85 pClient->pOSInfo = pSecInfo->clientOSInfo; 86 87 pClient->cachedPrivilege = pSecInfo->privLevel; 88 89 // TODO: Revisit in M2, see GPUSWSEC-1176 90 if (RMCFG_FEATURE_PLATFORM_GSP && IS_VGPU_GSP_PLUGIN_OFFLOAD_ENABLED(pGpu)) 91 { 92 if (pSecInfo->pProcessToken != NULL && 93 ((NvU64) pSecInfo->pProcessToken) < VMMU_MAX_GFID) 94 { 95 // Trunc to NvU32 to fit ProcID (VMMU_MAX_GFID << MAX_INT) 96 pClient->ProcID = (NvU32)((NvU64)pSecInfo->pProcessToken); 97 98 NV_PRINTF(LEVEL_INFO, "Client allocation with GFID = %u\n", 99 (NvU32)((NvU64)pSecInfo->pProcessToken)); 100 } 101 } 102 else 103 { 104 pClient->ProcID = osGetCurrentProcess(); 105 if (pClient->cachedPrivilege <= RS_PRIV_LEVEL_USER_ROOT) 106 pClient->pOsPidInfo = osGetPidInfo(); 107 } 108 109 // Set user-friendly client name from current process 110 osGetCurrentProcessName(pClient->name, NV_PROC_NAME_MAX_LENGTH); 111 112 for (i = 0; i < NV0000_NOTIFIERS_MAXCOUNT; i++) 113 { 114 pClient->CliSysEventInfo.notifyActions[i] = 115 NV0000_CTRL_EVENT_SET_NOTIFICATION_ACTION_DISABLE; 116 } 117 118 // 119 // Enabling this on MODS to avoid clash of client handles. This path gets executed on both 120 // guest & host RM for MODs platform, pGPU handle isnt available here to check for IS_VIRTUAL. 121 // Later code paths will override this for guest RM. 122 // This change affects non-SRIOV case as well, there is no good way to detect SRIOV without pGPU. 123 // 124 if (hypervisorIsVgxHyper() || NV_IS_MODS) 125 { 126 // 127 // Set RM allocated resource handle range for host RM. This minimize clash of guest RM handles with host RM 128 // during VM migration. 129 // 130 status = clientSetHandleGenerator(pRsClient, 131 (RS_UNIQUE_HANDLE_BASE + RS_UNIQUE_HANDLE_RANGE/2), 132 RS_UNIQUE_HANDLE_RANGE/2); 133 if (status != NV_OK) 134 { 135 NV_PRINTF(LEVEL_WARNING, 136 "NVRM_RPC: Failed to set host client resource handle range %x\n", status); 137 goto out; 138 } 139 } 140 141 // Prevent kernel clients from requesting handles in the FW handle generator range 142 status = clientSetRestrictedRange(pRsClient, 143 RS_FW_UNIQUE_HANDLE_BASE, RS_UNIQUE_HANDLE_RANGE); 144 if (status != NV_OK) 145 { 146 NV_PRINTF(LEVEL_WARNING, 147 "Failed to set host client restricted resource handle range. Status=%x\n", status); 148 goto out; 149 } 150 151 if (!rmGpuLockIsOwner()) 152 { 153 // LOCK: acquire GPUs lock 154 if ((status = rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE, RM_LOCK_MODULES_CLIENT)) != NV_OK) 155 { 156 NV_ASSERT(0); 157 goto out; 158 } 159 bReleaseLock = NV_TRUE; 160 } 161 162 _registerOSInfo(pClient, pClient->pOSInfo); 163 164 pClient->bIsClientVirtualMode = (pSecInfo->pProcessToken != NULL); 165 166 // 167 // Cache the security/uid tokens only if the client handle validation is 168 // enabled AND its a user mode path or a non privileged kernel class. 169 // 170 if (pSys->getProperty(pSys, PDB_PROP_SYS_VALIDATE_CLIENT_HANDLE) && 171 ((pParams->pSecInfo->privLevel < RS_PRIV_LEVEL_KERNEL) || pClient->bIsRootNonPriv)) 172 { 173 PSECURITY_TOKEN pSecurityToken = (pClient->bIsClientVirtualMode ? 174 pSecInfo->pProcessToken : osGetSecurityToken()); 175 PUID_TOKEN pUidToken = osGetCurrentUidToken(); 176 UserInfo *pUserInfo = NULL; 177 178 if (RMCFG_FEATURE_PLATFORM_GSP) 179 { 180 pClient->pSecurityToken = pSecurityToken; 181 } 182 else 183 { 184 // pUserInfo takes ownership of pUidToken upon successful registration 185 status = _registerUserInfo(&pUidToken, &pUserInfo); 186 187 if (status == NV_OK) 188 { 189 pClient->pUserInfo = pUserInfo; 190 pClient->pSecurityToken = pSecurityToken; 191 } 192 else 193 { 194 portMemFree(pUidToken); 195 196 if (pSecurityToken != NULL && !pClient->bIsClientVirtualMode) 197 portMemFree(pSecurityToken); 198 } 199 } 200 } 201 202 if (listAppendValue(&g_clientListBehindGpusLock, (void*)&pClient) == NULL) 203 status = NV_ERR_INSUFFICIENT_RESOURCES; 204 205 if (bReleaseLock) 206 { 207 // UNLOCK: release GPUs lock 208 rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL); 209 } 210 211 // RM gets the client handle from the allocation parameters 212 if (status == NV_OK && pParams->pAllocParams != NULL) 213 *(NvHandle*)(pParams->pAllocParams) = pParams->hClient; 214 215 out: 216 if (status != NV_OK) 217 { 218 osPutPidInfo(pClient->pOsPidInfo); 219 pClient->pOsPidInfo = NULL; 220 } 221 222 return status; 223 } 224 225 void 226 rmclientDestruct_IMPL 227 ( 228 RmClient *pClient 229 ) 230 { 231 NV_STATUS status = NV_OK; 232 NvBool bReleaseLock = NV_FALSE; 233 234 // RM client objects can only be created/destroyed with the RW API lock. 235 NV_ASSERT(rmapiLockIsWriteOwner()); 236 237 NV_PRINTF(LEVEL_INFO, " type: client\n"); 238 239 LOCK_METER_DATA(FREE_CLIENT, hClient, 0, 0); 240 241 // Free any association of the client with existing third-party p2p object 242 CliUnregisterFromThirdPartyP2P(pClient); 243 244 osPutPidInfo(pClient->pOsPidInfo); 245 246 // Updating the client list just before client handle unregister // 247 // in case child free functions need to iterate over all clients // 248 if (!rmGpuLockIsOwner()) 249 { 250 // LOCK: acquire GPUs lock 251 if ((status = rmGpuLocksAcquire(GPUS_LOCK_FLAGS_NONE, RM_LOCK_MODULES_CLIENT)) != NV_OK) 252 { 253 // This is the only chance that the shadow client list can be 254 // updated so modify it regardless of whether or not we obtained the lock 255 NV_ASSERT(0); 256 } 257 else 258 { 259 bReleaseLock = NV_TRUE; 260 } 261 } 262 263 _unregisterOSInfo(pClient, pClient->pOSInfo); 264 265 listRemoveFirstByValue(&g_clientListBehindGpusLock, (void*)&pClient); 266 267 if (pClient->pUserInfo != NULL) 268 { 269 _unregisterUserInfo(pClient->pUserInfo); 270 pClient->pUserInfo = NULL; 271 } 272 273 if (pClient->pSecurityToken != NULL) 274 { 275 if (!pClient->bIsClientVirtualMode) 276 portMemFree(pClient->pSecurityToken); 277 278 pClient->pSecurityToken = NULL; 279 } 280 281 if (bReleaseLock) 282 { 283 // UNLOCK: release GPUs lock 284 rmGpuLocksRelease(GPUS_LOCK_FLAGS_NONE, NULL); 285 } 286 } 287 288 NV_STATUS 289 rmclientInterMap_IMPL 290 ( 291 RmClient *pClient, 292 RsResourceRef *pMapperRef, 293 RsResourceRef *pMappableRef, 294 RS_INTER_MAP_PARAMS *pParams 295 ) 296 { 297 RS_INTER_MAP_PRIVATE *pPrivate = pParams->pPrivate; 298 RS_RES_MAP_TO_PARAMS mapToParams; 299 300 // Use virtual MapTo to perform the class-specific mapping to pMapperRef 301 portMemSet(&mapToParams, 0, sizeof(mapToParams)); 302 303 mapToParams.pMemoryRef = pMappableRef; 304 mapToParams.offset = pParams->offset; 305 mapToParams.length = pParams->length; 306 mapToParams.flags = pParams->flags; 307 mapToParams.pDmaOffset = &pParams->dmaOffset; 308 mapToParams.ppMemDesc = (MEMORY_DESCRIPTOR**)&pParams->pMemDesc; 309 310 mapToParams.pGpu = pPrivate->pGpu; 311 mapToParams.pSrcGpu = pPrivate->pSrcGpu; 312 mapToParams.pSrcMemDesc = pPrivate->pSrcMemDesc; 313 mapToParams.hBroadcastDevice = pPrivate->hBroadcastDevice; 314 mapToParams.hMemoryDevice = pPrivate->hMemoryDevice; 315 mapToParams.gpuMask = pPrivate->gpuMask; 316 mapToParams.bSubdeviceHandleProvided = pPrivate->bSubdeviceHandleProvided; 317 mapToParams.bFlaMapping = pPrivate->bFlaMapping; 318 319 return resMapTo(pMapperRef->pResource, &mapToParams); 320 } 321 322 NV_STATUS 323 rmclientInterUnmap_IMPL 324 ( 325 RmClient *pClient, 326 RsResourceRef *pMapperRef, 327 RS_INTER_UNMAP_PARAMS *pParams 328 ) 329 { 330 RS_INTER_UNMAP_PRIVATE *pPrivate = pParams->pPrivate; 331 RS_RES_UNMAP_FROM_PARAMS unmapFromParams; 332 333 // Use virtual UnmapFrom to perform the class-specific unmapping from pMapperRef 334 portMemSet(&unmapFromParams, 0, sizeof(unmapFromParams)); 335 336 unmapFromParams.pMemDesc = pParams->pMemDesc; 337 unmapFromParams.hMemory = pParams->hMappable; 338 unmapFromParams.flags = pParams->flags; 339 unmapFromParams.dmaOffset = pParams->dmaOffset; 340 unmapFromParams.size = pParams->size; 341 342 unmapFromParams.pGpu = pPrivate->pGpu; 343 unmapFromParams.hBroadcastDevice = pPrivate->hBroadcastDevice; 344 unmapFromParams.gpuMask = pPrivate->gpuMask; 345 unmapFromParams.bSubdeviceHandleProvided = pPrivate->bSubdeviceHandleProvided; 346 347 return resUnmapFrom(pMapperRef->pResource, &unmapFromParams); 348 } 349 350 RS_PRIV_LEVEL 351 rmclientGetCachedPrivilege_IMPL 352 ( 353 RmClient *pClient 354 ) 355 { 356 return pClient->cachedPrivilege; 357 } 358 359 NvBool 360 rmclientIsAdmin_IMPL 361 ( 362 RmClient *pClient, 363 RS_PRIV_LEVEL privLevel 364 ) 365 { 366 if (pClient == NULL) 367 return NV_FALSE; 368 369 return (privLevel >= RS_PRIV_LEVEL_USER_ROOT) && !pClient->bIsRootNonPriv; 370 } 371 372 void 373 rmclientSetClientFlags_IMPL 374 ( 375 RmClient *pClient, 376 NvU32 clientFlags 377 ) 378 { 379 pClient->Flags |= clientFlags; 380 } 381 382 static void 383 _rmclientPromoteDebuggerState 384 ( 385 RmClient *pClient, 386 NvU32 newMinimumState 387 ) 388 { 389 if (pClient->ClientDebuggerState < newMinimumState) 390 { 391 pClient->ClientDebuggerState = newMinimumState; 392 } 393 } 394 395 void * 396 rmclientGetSecurityToken_IMPL 397 ( 398 RmClient *pClient 399 ) 400 { 401 return pClient->pSecurityToken; 402 } 403 404 /*! 405 * @brief Given a client handle, validate the handle for security. 406 * 407 * Important!! This function should be called ONLY in the user mode paths. 408 * The security validations will fail in kernel paths, especially if called 409 * with privileged kernel handles. 410 * 411 * @param[in] hClient The client handle 412 * @param[in] pSecInfo The new calling context's security info. 413 * 414 * @return NV_OK if validated 415 * NV_ERR_INVALID_CLIENT if client cannot be found 416 * or if there isn't a match. 417 */ 418 static NV_STATUS 419 _rmclientUserClientSecurityCheck 420 ( 421 RmClient *pClient, 422 const API_SECURITY_INFO *pSecInfo 423 ) 424 { 425 NV_STATUS status = NV_OK; 426 OBJSYS *pSys = SYS_GET_INSTANCE(); 427 PSECURITY_TOKEN pCurrentToken = NULL; 428 PSECURITY_TOKEN pSecurityToken = pSecInfo->pProcessToken; 429 430 if ((pSys == NULL) || 431 (!pSys->getProperty(pSys, PDB_PROP_SYS_VALIDATE_CLIENT_HANDLE))) 432 { 433 return NV_OK; 434 } 435 436 // 437 // Check 1: 438 // The following check to make sure that user paths cannot be called with 439 // privileged kernel handles 440 // 441 // Note: For the user paths, we are checking against both kernel and admin. 442 // client The reason is that KMD today creates unprivileged kernel handles 443 // (of class NV01_ROOT_NON_PRIV) on behalf of user clients (cuda debugger, 444 // profiler, OGL etc) and gives out those handles. These handles are 445 // kernel, but they do not have admin privileges and since clients already 446 // use these handles to call into RM through the user paths, we are allowing 447 // them through ... for now. 448 // 449 // Till we either fix the clients to wean off these kernel handles or change 450 // KMD to not give out the kernel handles, we need to keep the check restricted 451 // to handles created with NV01_ROOT using the the CliCheckAdmin interface. 452 // 453 if ((pSecInfo->privLevel >= RS_PRIV_LEVEL_KERNEL) && !pClient->bIsRootNonPriv) 454 { 455 NV_PRINTF(LEVEL_WARNING, "Incorrect client handle used in the User export\n"); 456 return NV_ERR_INVALID_CLIENT; 457 } 458 459 // 460 // Check 2: 461 // Validate the client handle to make sure that the user who created the 462 // handle is the one that uses it. Otherwise a malicious user can guess the 463 // client handle created by another user and access information that its 464 // not privy to. 465 // 466 pCurrentToken = (pSecurityToken != NULL ? pSecurityToken : osGetSecurityToken()); 467 if (pCurrentToken == NULL) 468 { 469 NV_PRINTF(LEVEL_WARNING, 470 "Cannot get the security token for the current user.\n"); 471 NV_PRINTF(LEVEL_WARNING, 472 "The user client cannot be validated\n"); 473 status = NV_ERR_INVALID_CLIENT; 474 DBG_BREAKPOINT(); 475 goto CliUserClientSecurityCheck_exit; 476 } 477 478 status = osValidateClientTokens((void*)rmclientGetSecurityToken(pClient), 479 (void*)pCurrentToken); 480 if (status != NV_OK) 481 { 482 NV_PRINTF(LEVEL_WARNING, 483 "Error validating client token. Status = 0x%08x\n", status); 484 goto CliUserClientSecurityCheck_exit; 485 } 486 487 CliUserClientSecurityCheck_exit: 488 if (pCurrentToken != NULL && pSecurityToken == NULL) 489 { 490 portMemFree(pCurrentToken); 491 pCurrentToken = NULL; 492 } 493 return status; 494 } 495 496 NV_STATUS 497 rmclientPostProcessPendingFreeList_IMPL 498 ( 499 RmClient *pClient, 500 RsResourceRef **ppFirstLowPriRef 501 ) 502 { 503 RsClient *pRsClient = staticCast(pClient, RsClient); 504 RsResourceRef *pTargetRef = NULL; 505 RsResourceRef *pStopRef = NULL; 506 RsResourceRef *pFirstLowPriRef = NULL; 507 508 pStopRef = pRsClient->pFreeStack->pResourceRef; 509 pTargetRef = listHead(&pRsClient->pendingFreeList); 510 while (pTargetRef != pStopRef) 511 { 512 RsResourceRef *pNextRef = listNext(&pRsClient->pendingFreeList, pTargetRef); 513 514 // Ensure that high priority resources (and their children/dependents) are freed first 515 if (pTargetRef->pResourceDesc->freePriority == RS_FREE_PRIORITY_HIGH) 516 { 517 clientUpdatePendingFreeList(pRsClient, pTargetRef, pTargetRef, NV_TRUE); 518 } 519 pTargetRef = pNextRef; 520 } 521 522 // 523 // Find the last high-priority resource in the list. 524 // The next resource will be the first low priority resource. 525 // If there are no high-priority resources: use the head of the list 526 // 527 pTargetRef = (pStopRef != NULL) 528 ? pStopRef 529 : listTail(&pRsClient->pendingFreeList); 530 pFirstLowPriRef = listHead(&pRsClient->pendingFreeList); 531 532 while (pTargetRef != NULL) 533 { 534 RsResourceRef *pPrevRef = listPrev(&pRsClient->pendingFreeList, pTargetRef); 535 536 if (pTargetRef->pResourceDesc->freePriority == RS_FREE_PRIORITY_HIGH) 537 { 538 pFirstLowPriRef = listNext(&pRsClient->pendingFreeList, pTargetRef); 539 break; 540 } 541 pTargetRef = pPrevRef; 542 } 543 544 if (ppFirstLowPriRef) 545 *ppFirstLowPriRef = pFirstLowPriRef; 546 547 return NV_OK; 548 } 549 550 RS_PRIV_LEVEL rmclientGetCachedPrivilegeByHandle(NvHandle hClient) 551 { 552 RmClient *pClient = serverutilGetClientUnderLock(hClient); 553 return pClient ? rmclientGetCachedPrivilege(pClient) : RS_PRIV_LEVEL_USER; 554 } 555 556 NvBool rmclientIsAdminByHandle(NvHandle hClient, RS_PRIV_LEVEL privLevel) 557 { 558 RmClient *pClient = serverutilGetClientUnderLock(hClient); 559 return pClient ? rmclientIsAdmin(pClient, privLevel) : NV_FALSE; 560 } 561 562 NvBool rmclientIsKernelOnlyByHandle(NvHandle hClient) 563 { 564 RmClient *pClient = serverutilGetClientUnderLock(hClient); 565 return pClient ? (pClient->pSecurityToken == NULL) : NV_FALSE; 566 } 567 568 NvBool rmclientSetClientFlagsByHandle(NvHandle hClient, NvU32 clientFlags) 569 { 570 RmClient *pClient = serverutilGetClientUnderLock(hClient); 571 if (pClient) 572 rmclientSetClientFlags(pClient, clientFlags); 573 return !!pClient; 574 } 575 576 void rmclientPromoteDebuggerStateByHandle(NvHandle hClient, NvU32 newMinimumState) 577 { 578 RmClient *pClient = serverutilGetClientUnderLock(hClient); 579 if (pClient) 580 _rmclientPromoteDebuggerState(pClient, newMinimumState); 581 } 582 583 void *rmclientGetSecurityTokenByHandle(NvHandle hClient) 584 { 585 RmClient *pClient = serverutilGetClientUnderLock(hClient); 586 return pClient ? rmclientGetSecurityToken(pClient) : NULL; 587 } 588 589 NV_STATUS rmclientUserClientSecurityCheckByHandle(NvHandle hClient, const API_SECURITY_INFO *pSecInfo) 590 { 591 RmClient *pClient = serverutilGetClientUnderLock(hClient); 592 593 // 594 // Return early if it's a null object. This is probably the allocation of 595 // the root client object, so the client class is going to be null. 596 // 597 // RS-TODO - This check should move to the caller. 598 // 599 if (hClient == NV01_NULL_OBJECT) 600 { 601 return NV_OK; 602 } 603 604 if (pClient) 605 { 606 return _rmclientUserClientSecurityCheck(pClient, pSecInfo); 607 } 608 else 609 return NV_ERR_INVALID_CLIENT; 610 } 611 612 /** 613 * Register a uid token with the client database and return a UserInfo that 614 * corresponds to the uid token. 615 * 616 * If the uid token has not been registered before, a new UserInfo will be registered and returned. 617 * If the uid token is already registered, an existing UserInfo will be ref-counted and 618 * returned. 619 * 620 * This function must be protected by a lock (currently the GPUs lock.) 621 * 622 * @param[inout] ppUidToken 623 * @param[out] ppUserInfo 624 */ 625 static NV_STATUS 626 _registerUserInfo 627 ( 628 PUID_TOKEN *ppUidToken, 629 UserInfo **ppUserInfo 630 ) 631 { 632 NV_STATUS status = NV_OK; 633 NvBool bFound = NV_FALSE; 634 UserInfo *pUserInfo = NULL; 635 UserInfoListIter it = listIterAll(&g_userInfoList); 636 PUID_TOKEN pUidToken; 637 638 if ((!ppUidToken) || (!(*ppUidToken))) 639 return NV_ERR_INVALID_ARGUMENT; 640 641 pUidToken = *ppUidToken; 642 643 // Find matching user token 644 while(listIterNext(&it)) 645 { 646 pUserInfo = *it.pValue; 647 if (osUidTokensEqual(pUserInfo->pUidToken, pUidToken)) 648 { 649 bFound = NV_TRUE; 650 break; 651 } 652 } 653 654 if (!bFound) 655 { 656 RsShared *pShared; 657 status = serverAllocShare(&g_resServ, classInfo(UserInfo), &pShared); 658 if (status != NV_OK) 659 return status; 660 661 pUserInfo = dynamicCast(pShared, UserInfo); 662 pUserInfo->pUidToken = pUidToken; 663 664 if (listAppendValue(&g_userInfoList, (void*)&pUserInfo) == NULL) 665 { 666 serverFreeShare(&g_resServ, pShared); 667 return NV_ERR_INSUFFICIENT_RESOURCES; 668 } 669 } 670 else 671 { 672 serverRefShare(&g_resServ, staticCast(pUserInfo, RsShared)); 673 portMemFree(pUidToken); 674 *ppUidToken = NULL; 675 } 676 677 *ppUserInfo = pUserInfo; 678 679 return NV_OK; 680 } 681 682 /** 683 * 684 * Unregister a client from a user info list 685 * 686 * This function must be protected by a lock (currently the GPUs lock.) 687 * 688 * @param[in] pUserInfo 689 */ 690 static NV_STATUS 691 _unregisterUserInfo 692 ( 693 UserInfo *pUserInfo 694 ) 695 { 696 NvS32 refCount = serverGetShareRefCount(&g_resServ, staticCast(pUserInfo, RsShared)); 697 if (--refCount == 0) 698 { 699 listRemoveFirstByValue(&g_userInfoList, (void*)&pUserInfo); 700 } 701 return serverFreeShare(&g_resServ, staticCast(pUserInfo, RsShared)); 702 } 703 704 NV_STATUS userinfoConstruct_IMPL 705 ( 706 UserInfo *pUserInfo 707 ) 708 { 709 return NV_OK; 710 } 711 712 void 713 userinfoDestruct_IMPL 714 ( 715 UserInfo *pUserInfo 716 ) 717 { 718 portMemFree(pUserInfo->pUidToken); 719 } 720 721 NV_STATUS 722 rmclientValidate_IMPL 723 ( 724 RmClient *pClient, 725 const API_SECURITY_INFO *pSecInfo 726 ) 727 { 728 NV_STATUS status = NV_OK; 729 OBJSYS *pSys = SYS_GET_INSTANCE(); 730 731 if (pSys->getProperty(pSys, PDB_PROP_SYS_VALIDATE_CLIENT_HANDLE) && 732 pSecInfo != NULL) 733 { 734 if (pSys->getProperty(pSys, PDB_PROP_SYS_VALIDATE_CLIENT_HANDLE_STRICT) && 735 pSecInfo->clientOSInfo != NULL) 736 { 737 if (pClient->pOSInfo != pSecInfo->clientOSInfo) 738 { 739 status = NV_ERR_INVALID_CLIENT; 740 } 741 } 742 else if (pSecInfo->privLevel < RS_PRIV_LEVEL_KERNEL) 743 { 744 status = _rmclientUserClientSecurityCheck(pClient, pSecInfo); 745 } 746 } 747 748 return status; 749 } 750 751 NV_STATUS 752 rmclientFreeResource_IMPL 753 ( 754 RmClient *pClient, 755 RsServer *pServer, 756 RS_RES_FREE_PARAMS_INTERNAL *pRmFreeParams 757 ) 758 { 759 NV_STATUS status; 760 OBJGPU *pGpu; 761 NvBool bBcState; 762 NvBool bRestoreBcState = NV_FALSE; 763 764 if (gpuGetByRef(pRmFreeParams->pResourceRef, NULL, &pGpu) == NV_OK) 765 { 766 bBcState = gpumgrGetBcEnabledStatus(pGpu); 767 bRestoreBcState = NV_TRUE; 768 } 769 770 rmapiFreeResourcePrologue(pRmFreeParams); 771 772 status = clientFreeResource_IMPL(staticCast(pClient, RsClient), pServer, pRmFreeParams); 773 774 if (bRestoreBcState) 775 { 776 gpumgrSetBcEnabledStatus(pGpu, bBcState); 777 } 778 return status; 779 } 780 781 static NvBool _rmclientIsCapable 782 ( 783 NvHandle hClient, 784 NvU32 capability 785 ) 786 { 787 NvU32 internalClassId; 788 RsResourceRef *pResourceRef = NULL; 789 790 switch(capability) 791 { 792 case NV_RM_CAP_SYS_SMC_CONFIG: 793 { 794 internalClassId = classId(MIGConfigSession); 795 break; 796 } 797 case NV_RM_CAP_EXT_FABRIC_MGMT: 798 { 799 internalClassId = classId(FmSessionApi); 800 break; 801 } 802 case NV_RM_CAP_SYS_FABRIC_IMEX_MGMT: 803 { 804 internalClassId = classId(ImexSessionApi); 805 break; 806 } 807 case NV_RM_CAP_SYS_SMC_MONITOR: 808 { 809 internalClassId = classId(MIGMonitorSession); 810 break; 811 } 812 default: 813 { 814 NV_ASSERT(0); 815 return NV_FALSE; 816 } 817 } 818 819 // Check if client has allocated a given class 820 pResourceRef = serverutilFindChildRefByType(hClient, hClient, internalClassId, NV_TRUE); 821 if (pResourceRef == NULL) 822 { 823 return NV_FALSE; 824 } 825 826 return NV_TRUE; 827 } 828 829 NvBool rmclientIsCapableOrAdmin_IMPL 830 ( 831 RmClient *pClient, 832 NvU32 capability, 833 RS_PRIV_LEVEL privLevel 834 ) 835 { 836 RsClient *pRsClient = staticCast(pClient, RsClient); 837 NvHandle hClient = pRsClient->hClient; 838 839 if (rmclientIsAdmin(pClient, privLevel)) 840 { 841 return NV_TRUE; 842 } 843 844 return _rmclientIsCapable(hClient, capability); 845 } 846 847 // 848 // RS-TODO: Delete this function once the RM Capabilities framework is in place. 849 // JIRA GR-139 850 // 851 NvBool rmclientIsCapableOrAdminByHandle 852 ( 853 NvHandle hClient, 854 NvU32 capability, 855 RS_PRIV_LEVEL privLevel 856 ) 857 { 858 RmClient *pClient = serverutilGetClientUnderLock(hClient); 859 if (pClient == NULL) 860 { 861 return NV_FALSE; 862 } 863 864 return rmclientIsCapableOrAdmin(pClient, capability, privLevel); 865 } 866 867 NvBool rmclientIsCapable_IMPL 868 ( 869 RmClient *pClient, 870 NvU32 capability 871 ) 872 { 873 RsClient *pRsClient = staticCast(pClient, RsClient); 874 NvHandle hClient = pRsClient->hClient; 875 876 return _rmclientIsCapable(hClient, capability); 877 } 878 879 // 880 // RS-TODO: Delete this function once the RM Capabilities framework is in place. 881 // JIRA GR-139 882 // 883 NvBool rmclientIsCapableByHandle 884 ( 885 NvHandle hClient, 886 NvU32 capability 887 ) 888 { 889 RmClient *pClient = serverutilGetClientUnderLock(hClient); 890 if (pClient == NULL) 891 { 892 return NV_FALSE; 893 } 894 895 return rmclientIsCapable(pClient, capability); 896 } 897 898 /** 899 * 900 * Register a client with a user info list 901 * 902 * This function must be protected by a lock (currently the GPUs lock.) 903 * 904 * @param[in] pClient 905 * @param[in] pOSInfo 906 */ 907 static NV_STATUS 908 _registerOSInfo 909 ( 910 RmClient *pClient, 911 void *pOSInfo 912 ) 913 { 914 OsInfoMapSubmap *pSubmap = NULL; 915 RmClient **pInsert = NULL; 916 NvU64 key1 = (NvUPtr)pOSInfo; 917 NvU64 key2 = (NvU64)(staticCast(pClient,RsClient))->hClient; 918 919 if (multimapFindItem(&g_osInfoList, key1, key2) != NULL) 920 return NV_ERR_INSERT_DUPLICATE_NAME; 921 922 if (multimapFindSubmap(&g_osInfoList, key1) == NULL) 923 { 924 pSubmap = multimapInsertSubmap(&g_osInfoList, key1); 925 if (pSubmap == NULL) 926 return NV_ERR_NO_MEMORY; 927 } 928 929 pInsert = multimapInsertItemNew(&g_osInfoList, key1, key2); 930 if (pInsert == NULL) 931 return NV_ERR_NO_MEMORY; 932 933 osAllocatedRmClient(pOSInfo); 934 935 *pInsert = pClient; 936 937 return NV_OK; 938 } 939 940 /** 941 * 942 * Unregister a client from a user info list 943 * 944 * This function must be protected by a lock (currently the GPUs lock.) 945 * 946 * @param[in] pClient 947 * @param[in] pOSInfo 948 */ 949 static NV_STATUS 950 _unregisterOSInfo 951 ( 952 RmClient *pClient, 953 void *pOSInfo 954 ) 955 { 956 NvU64 key1 = (NvUPtr)pOSInfo; 957 NvU64 key2 = (NvU64)(staticCast(pClient, RsClient))->hClient; 958 OsInfoMapSubmap *pSubmap = NULL; 959 RmClient **pFind = NULL; 960 961 pFind = multimapFindItem(&g_osInfoList, key1, key2); 962 if (pFind != NULL) 963 multimapRemoveItem(&g_osInfoList, pFind); 964 965 pSubmap = multimapFindSubmap(&g_osInfoList, key1); 966 if (pSubmap == NULL || multimapCountSubmapItems(&g_osInfoList, pSubmap) > 0) 967 return NV_OK; 968 969 multimapRemoveSubmap(&g_osInfoList, pSubmap); 970 971 return NV_OK; 972 } 973