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