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