Skip to content

Commit 501d36e

Browse files
committed
basic ICD loader env var support for OCL_ICD_VENDORS
1 parent 467f286 commit 501d36e

5 files changed

Lines changed: 130 additions & 3 deletions

File tree

CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ find_package (Threads REQUIRED)
3333
# advance. Use it with discretion.
3434
option (BUILD_SHARED_LIBS "Build shared libs" ON)
3535

36+
include(CheckFunctionExists)
37+
check_function_exists(secure_getenv HAVE_SECURE_GETENV)
38+
check_function_exists(__secure_getenv HAVE___SECURE_GETENV)
39+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/loader/icd_cmake_config.h.in
40+
${CMAKE_CURRENT_BINARY_DIR}/icd_cmake_config.h)
41+
3642
set (OPENCL_ICD_LOADER_SOURCES
3743
loader/icd.c
3844
loader/icd_dispatch.c)
@@ -108,7 +114,7 @@ endif ()
108114
include_directories (${OPENCL_ICD_LOADER_HEADERS_DIR})
109115
add_definitions (-DCL_TARGET_OPENCL_VERSION=220)
110116

111-
target_include_directories (OpenCL PRIVATE loader)
117+
target_include_directories (OpenCL PRIVATE ${CMAKE_CURRENT_BINARY_DIR} loader)
112118
target_link_libraries (OpenCL ${CMAKE_DL_LIBS})
113119

114120
include (CTest)

loader/icd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#ifndef _ICD_H_
2020
#define _ICD_H_
2121

22+
#include "icd_cmake_config.h"
23+
2224
#ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS
2325
#define CL_USE_DEPRECATED_OPENCL_1_0_APIS
2426
#endif

loader/icd_cmake_config.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#cmakedefine HAVE_SECURE_GETENV
2+
#cmakedefine HAVE___SECURE_GETENV

loader/icd_envvars.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright (c) 2016-2019 The Khronos Group Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
17+
*/
18+
19+
#ifndef _ICD_ENVVARS_H_
20+
#define _ICD_ENVVARS_H_
21+
22+
// Environment variables
23+
#if defined(__linux__) || defined(__APPLE__)
24+
25+
static inline char *khrIcd_getenv(const char *name) {
26+
// No allocation of memory necessary for Linux.
27+
return getenv(name);
28+
}
29+
30+
static inline char *khrIcd_secure_getenv(const char *name) {
31+
#if defined(__APPLE__)
32+
// Apple does not appear to have a secure getenv implementation.
33+
// The main difference between secure getenv and getenv is that secure getenv
34+
// returns NULL if the process is being run with elevated privileges by a normal user.
35+
// The idea is to prevent the reading of malicious environment variables by a process
36+
// that can do damage.
37+
// This algorithm is derived from glibc code that sets an internal
38+
// variable (__libc_enable_secure) if the process is running under setuid or setgid.
39+
return geteuid() != getuid() || getegid() != getgid() ? NULL : khrIcd_getenv(name);
40+
#else
41+
// Linux
42+
#ifdef HAVE_SECURE_GETENV
43+
return secure_getenv(name);
44+
#elif defined(HAVE___SECURE_GETENV)
45+
return __secure_getenv(name);
46+
#else
47+
#pragma message( \
48+
"Warning: Falling back to non-secure getenv for environmental lookups! Consider" \
49+
" updating to a different libc.")
50+
return khrIcd_getenv(name);
51+
#endif
52+
#endif
53+
}
54+
55+
static inline void khrIcd_free_getenv(char *val) {
56+
// No freeing of memory necessary for Linux, but we should at least touch
57+
// val to get rid of compiler warnings.
58+
(void)val;
59+
}
60+
61+
#elif defined(WIN32)
62+
63+
static inline char *khrIcd_getenv(const char *name) {
64+
char *retVal;
65+
DWORD valSize;
66+
67+
valSize = GetEnvironmentVariableA(name, NULL, 0);
68+
69+
// valSize DOES include the null terminator, so for any set variable
70+
// will always be at least 1. If it's 0, the variable wasn't set.
71+
if (valSize == 0) return NULL;
72+
73+
// Allocate the space necessary for the registry entry
74+
retVal = (char *)malloc(valSize);
75+
76+
if (NULL != retVal) {
77+
GetEnvironmentVariableA(name, retVal, valSize);
78+
}
79+
80+
return retVal;
81+
}
82+
83+
static inline char *khrIcd_secure_getenv(const char *name) {
84+
// No secure version for Windows as far as I know
85+
return khrIcd_getenv(name);
86+
}
87+
88+
static inline void khrIcd_free_getenv(char *val) {
89+
free((void *)val);
90+
}
91+
92+
#else
93+
94+
static inline char *khrIcd_getenv(const char *name) {
95+
// stub func
96+
(void)name;
97+
return NULL;
98+
}
99+
static inline void khrIcd_free_getenv(char *val) {
100+
// stub func
101+
(void)val;
102+
}
103+
104+
#endif
105+
106+
#endif

loader/linux/icd_linux.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@
1616
* OpenCL is a trademark of Apple Inc. used under license by Khronos.
1717
*/
1818

19+
// for secure_getenv():
20+
#ifndef _GNU_SOURCE
21+
#define _GNU_SOURCE
22+
#endif
23+
1924
#include "icd.h"
25+
#include "icd_envvars.h"
26+
2027
#include <dlfcn.h>
2128
#include <stdio.h>
2229
#include <string.h>
@@ -38,11 +45,15 @@ void khrIcdOsVendorsEnumerate(void)
3845
{
3946
DIR *dir = NULL;
4047
struct dirent *dirEntry = NULL;
48+
char* vendorPath = khrIcd_secure_getenv("OCL_ICD_VENDORS");
49+
if (vendorPath == NULL)
50+
{
4151
#ifdef __ANDROID__
42-
char *vendorPath = "/system/vendor/Khronos/OpenCL/vendors/";
52+
vendorPath = "/system/vendor/Khronos/OpenCL/vendors/";
4353
#else
44-
char *vendorPath = "/etc/OpenCL/vendors/";
54+
vendorPath = "/etc/OpenCL/vendors/";
4555
#endif // ANDROID
56+
}
4657

4758
// open the directory
4859
dir = opendir(vendorPath);

0 commit comments

Comments
 (0)