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