Skip to content

Commit 019fdc1

Browse files
committed
Add support for custom driver root directory
1 parent 3d77524 commit 019fdc1

19 files changed

+385
-274
lines changed

src/cli/cli.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct context {
2525
/* main */
2626
uid_t uid;
2727
gid_t gid;
28+
char *root;
2829
char *ldcache;
2930
bool load_kmods;
3031
char *init_flags;

src/cli/configure.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ static error_t configure_parser(int, char *, struct argp_state *);
1313
static int check_cuda_version(const struct dsl_data *, enum dsl_comparator, const char *);
1414
static int check_driver_version(const struct dsl_data *, enum dsl_comparator, const char *);
1515
static int check_device_arch(const struct dsl_data *, enum dsl_comparator, const char *);
16-
static bool is_root_dir(const char *);
1716

1817
const struct argp configure_usage = {
1918
(const struct argp_option[]){
@@ -104,7 +103,7 @@ configure_parser(int key, char *arg, struct argp_state *state)
104103
case ARGP_KEY_ARG:
105104
if (state->arg_num > 0)
106105
argp_usage(state);
107-
if (is_root_dir(arg)) {
106+
if (arg[0] != '/' || !strcmp(arg, "/")) {
108107
error_setx(&err, "invalid rootfs directory");
109108
goto fatal;
110109
}
@@ -155,19 +154,6 @@ check_device_arch(const struct dsl_data *data, enum dsl_comparator cmp, const ch
155154
return (dsl_compare_version(data->dev->arch, cmp, arch));
156155
}
157156

158-
static bool
159-
is_root_dir(const char *path)
160-
{
161-
bool rv = false;
162-
char *p;
163-
164-
p = realpath(path, NULL);
165-
if (p != NULL && !strcmp(p, "/"))
166-
rv = true;
167-
free(p);
168-
return (rv);
169-
}
170-
171157
int
172158
configure_command(const struct context *ctx)
173159
{
@@ -207,6 +193,7 @@ configure_command(const struct context *ctx)
207193
}
208194
nvc_cfg->uid = ctx->uid;
209195
nvc_cfg->gid = ctx->gid;
196+
nvc_cfg->root = ctx->root;
210197
nvc_cfg->ldcache = ctx->ldcache;
211198
if (nvc_init(nvc, nvc_cfg, ctx->init_flags) < 0) {
212199
warnx("initialization error: %s", nvc_error(nvc));

src/cli/info.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ info_command(const struct context *ctx)
5151
int rv = EXIT_FAILURE;
5252

5353
run_as_root = (geteuid() == 0);
54-
if (!run_as_root && ctx->load_kmods) {
54+
if (!run_as_root && (ctx->load_kmods || ctx->root != NULL)) {
5555
warnx("requires root privileges");
5656
return (rv);
5757
}
@@ -82,6 +82,7 @@ info_command(const struct context *ctx)
8282
}
8383
nvc_cfg->uid = (!run_as_root && ctx->uid == (uid_t)-1) ? geteuid() : ctx->uid;
8484
nvc_cfg->gid = (!run_as_root && ctx->gid == (gid_t)-1) ? getegid() : ctx->gid;
85+
nvc_cfg->root = ctx->root;
8586
nvc_cfg->ldcache = ctx->ldcache;
8687
if (nvc_init(nvc, nvc_cfg, ctx->init_flags) < 0) {
8788
warnx("initialization error: %s", nvc_error(nvc));

src/cli/list.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ list_command(const struct context *ctx)
8484
int rv = EXIT_FAILURE;
8585

8686
run_as_root = (geteuid() == 0);
87-
if (!run_as_root && ctx->load_kmods) {
87+
if (!run_as_root && (ctx->load_kmods || ctx->root != NULL)) {
8888
warnx("requires root privileges");
8989
return (rv);
9090
}
@@ -115,6 +115,7 @@ list_command(const struct context *ctx)
115115
}
116116
nvc_cfg->uid = (!run_as_root && ctx->uid == (uid_t)-1) ? geteuid() : ctx->uid;
117117
nvc_cfg->gid = (!run_as_root && ctx->gid == (gid_t)-1) ? getegid() : ctx->gid;
118+
nvc_cfg->root = ctx->root;
118119
nvc_cfg->ldcache = ctx->ldcache;
119120
if (nvc_init(nvc, nvc_cfg, ctx->init_flags) < 0) {
120121
warnx("initialization error: %s", nvc_error(nvc));

src/cli/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static struct argp usage = {
2929
{"debug", 'd', "FILE", 0, "Log debug information", -1},
3030
{"load-kmods", 'k', NULL, 0, "Load kernel modules", -1},
3131
{"user", 'u', "UID[:GID]", OPTION_ARG_OPTIONAL, "User and group to use for privilege separation", -1},
32+
{"root", 'r', "PATH", 0, "Path to the driver root directory", -1},
3233
{"ldcache", 'l', "FILE", 0, "Path to the system's DSO cache", -1},
3334
{NULL, 0, NULL, 0, "Commands:", 0},
3435
{"info", 0, NULL, OPTION_DOC|OPTION_NO_USAGE, "Report information about the driver and devices", 0},
@@ -100,6 +101,9 @@ parser(int key, char *arg, struct argp_state *state)
100101
ctx->gid = getegid();
101102
}
102103
break;
104+
case 'r':
105+
ctx->root = arg;
106+
break;
103107
case 'l':
104108
ctx->ldcache = arg;
105109
break;

src/common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define PROC_SELF "/proc/self"
1212
#define PROC_MOUNTS_PATH(proc) proc "/mountinfo"
1313
#define PROC_CGROUP_PATH(proc) proc "/cgroup"
14+
#define PROC_ROOT_PATH(proc) proc "/root/" /* XXX Leading slash is required */
1415
#define PROC_NS_PATH(proc) proc "/ns/%s"
1516
#define PROC_SETGROUPS_PATH(proc) proc "/setgroups"
1617
#define PROC_UID_MAP_PATH(proc) proc "/uid_map"

src/driver.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
static int reset_cuda_environment(struct error *);
3939
static int setup_rpc_client(struct driver *);
40-
static noreturn void setup_rpc_service(struct driver *, uid_t, gid_t, pid_t);
40+
static noreturn void setup_rpc_service(struct driver *, const char *, uid_t, gid_t, pid_t);
4141
static int reap_process(struct error *, pid_t, int, bool);
4242

4343
static struct driver_device {
@@ -129,8 +129,10 @@ setup_rpc_client(struct driver *ctx)
129129
}
130130

131131
static void
132-
setup_rpc_service(struct driver *ctx, uid_t uid, gid_t gid, pid_t ppid)
132+
setup_rpc_service(struct driver *ctx, const char *root, uid_t uid, gid_t gid, pid_t ppid)
133133
{
134+
int rv = EXIT_FAILURE;
135+
134136
log_info("starting driver service");
135137
prctl(PR_SET_NAME, (unsigned long)"nvc:[driver]", 0, 0, 0);
136138

@@ -143,6 +145,18 @@ setup_rpc_service(struct driver *ctx, uid_t uid, gid_t gid, pid_t ppid)
143145
if (getppid() != ppid)
144146
kill(getpid(), SIGTERM);
145147

148+
if (strcmp(root, "/")) {
149+
if (chroot(root) < 0 || chdir("/") < 0) {
150+
error_set(ctx->err, "change root failed");
151+
goto fail;
152+
}
153+
}
154+
155+
if ((ctx->cuda_dl = xdlopen(ctx->err, SONAME_LIBCUDA, RTLD_NOW)) == NULL)
156+
goto fail;
157+
if ((ctx->nvml_dl = xdlopen(ctx->err, SONAME_LIBNVML, RTLD_NOW)) == NULL)
158+
goto fail;
159+
146160
/*
147161
* Drop privileges and capabilities for security reasons.
148162
*
@@ -167,14 +181,16 @@ setup_rpc_service(struct driver *ctx, uid_t uid, gid_t gid, pid_t ppid)
167181
svc_run();
168182

169183
log_info("terminating driver service");
170-
svc_destroy(ctx->rpc_svc);
171-
_exit(EXIT_SUCCESS);
184+
rv = EXIT_SUCCESS;
172185

173186
fail:
174-
log_errf("could not start driver service: %s", ctx->err->msg);
187+
if (rv != EXIT_SUCCESS)
188+
log_errf("could not start driver service: %s", ctx->err->msg);
189+
xdlclose(NULL, ctx->cuda_dl);
190+
xdlclose(NULL, ctx->nvml_dl);
175191
if (ctx->rpc_svc != NULL)
176192
svc_destroy(ctx->rpc_svc);
177-
_exit(EXIT_FAILURE);
193+
_exit(rv);
178194
}
179195

180196
static int
@@ -217,26 +233,21 @@ driver_program_1_freeresult(maybe_unused SVCXPRT *svc, xdrproc_t xdr_result, cad
217233
}
218234

219235
int
220-
driver_init(struct driver *ctx, struct error *err, uid_t uid, gid_t gid)
236+
driver_init(struct driver *ctx, struct error *err, const char *root, uid_t uid, gid_t gid)
221237
{
222238
int ret;
223239
pid_t pid;
224240
struct driver_init_res res = {0};
225241

226242
*ctx = (struct driver){err, NULL, NULL, {-1, -1}, -1, NULL, NULL};
227243

228-
if ((ctx->cuda_dl = xdlopen(err, SONAME_LIBCUDA, RTLD_NOW)) == NULL)
229-
goto fail;
230-
if ((ctx->nvml_dl = xdlopen(err, SONAME_LIBNVML, RTLD_NOW)) == NULL)
231-
goto fail;
232-
233244
pid = getpid();
234245
if (socketpair(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, ctx->fd) < 0 || (ctx->pid = fork()) < 0) {
235246
error_set(err, "process creation failed");
236247
goto fail;
237248
}
238249
if (ctx->pid == 0)
239-
setup_rpc_service(ctx, uid, gid, pid);
250+
setup_rpc_service(ctx, root, uid, gid, pid);
240251
if (setup_rpc_client(ctx) < 0)
241252
goto fail;
242253

@@ -255,8 +266,6 @@ driver_init(struct driver *ctx, struct error *err, uid_t uid, gid_t gid)
255266

256267
xclose(ctx->fd[SOCK_CLT]);
257268
xclose(ctx->fd[SOCK_SVC]);
258-
xdlclose(NULL, ctx->cuda_dl);
259-
xdlclose(NULL, ctx->nvml_dl);
260269
return (-1);
261270
}
262271

@@ -294,11 +303,6 @@ driver_shutdown(struct driver *ctx)
294303

295304
xclose(ctx->fd[SOCK_CLT]);
296305
xclose(ctx->fd[SOCK_SVC]);
297-
if (xdlclose(ctx->err, ctx->cuda_dl) < 0)
298-
return (-1);
299-
if (xdlclose(ctx->err, ctx->nvml_dl) < 0)
300-
return (-1);
301-
302306
*ctx = (struct driver){NULL, NULL, NULL, {-1, -1}, -1, NULL, NULL};
303307
return (0);
304308
}

src/driver.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct driver {
3535

3636
void driver_program_1(struct svc_req *, register SVCXPRT *);
3737

38-
int driver_init(struct driver *, struct error *, uid_t, gid_t);
38+
int driver_init(struct driver *, struct error *, const char *, uid_t, gid_t);
3939
int driver_shutdown(struct driver *);
4040
int driver_get_rm_version(struct driver *, char **);
4141
int driver_get_cuda_version(struct driver *, char **);

src/ldcache.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ ldcache_close(struct ldcache *ctx)
107107
}
108108

109109
int
110-
ldcache_resolve(struct ldcache *ctx, uint32_t arch, const char * const libs[],
110+
ldcache_resolve(struct ldcache *ctx, uint32_t arch, const char *root, const char * const libs[],
111111
char *paths[], size_t size, ldcache_select_fn select, void *select_ctx)
112112
{
113113
char path[PATH_MAX];
@@ -128,11 +128,11 @@ ldcache_resolve(struct ldcache *ctx, uint32_t arch, const char * const libs[],
128128
for (size_t j = 0; j < size; ++j) {
129129
if (strpcmp(key, libs[j]))
130130
continue;
131-
if (xrealpath(ctx->err, value, path) == NULL)
131+
if (path_resolve(ctx->err, path, root, value) < 0)
132132
return (-1);
133133
if (paths[j] != NULL && !strcmp(paths[j], path))
134134
continue;
135-
if ((override = select(ctx->err, select_ctx, paths[j], path)) < 0)
135+
if ((override = select(ctx->err, select_ctx, root, paths[j], path)) < 0)
136136
return (-1);
137137
if (override) {
138138
free(paths[j]);

src/ldcache.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ enum {
4444
LD_MIPS64_LIBN64_NAN2008 = 0x0e00,
4545
};
4646

47-
typedef int (*ldcache_select_fn)(struct error *, void *, const char *, const char *);
47+
typedef int (*ldcache_select_fn)(struct error *, void *, const char *, const char *, const char *);
4848

4949
void ldcache_init(struct ldcache *, struct error *, const char *);
5050
int ldcache_open(struct ldcache *);
5151
int ldcache_close(struct ldcache *);
52-
int ldcache_resolve(struct ldcache *, uint32_t, const char * const [],
52+
int ldcache_resolve(struct ldcache *, uint32_t, const char *, const char * const [],
5353
char *[], size_t, ldcache_select_fn, void *);
5454

5555
#endif /* HEADER_LDCACHE_H */

0 commit comments

Comments
 (0)