提交 7ea554a3 编写于 作者: J Jonathan Calmels

Rework capabilities to support more unprivileged use-cases

上级 f06cbbbf
...@@ -173,20 +173,16 @@ configure_command(const struct context *ctx) ...@@ -173,20 +173,16 @@ configure_command(const struct context *ctx)
struct error err = {0}; struct error err = {0};
int rv = EXIT_FAILURE; int rv = EXIT_FAILURE;
if (geteuid() != 0) { if (perm_set_capabilities(&err, CAP_PERMITTED, pcaps, nitems(pcaps)) < 0 ||
warnx("requires root privileges"); perm_set_capabilities(&err, CAP_INHERITABLE, NULL, 0) < 0 ||
return (rv); perm_set_bounds(&err, bcaps, nitems(bcaps)) < 0) {
}
if (perm_set_capabilities(&err, CAP_PERMITTED, permitted_caps, nitems(permitted_caps)) < 0 ||
perm_set_capabilities(&err, CAP_INHERITABLE, inherited_caps, nitems(inherited_caps)) < 0 ||
perm_drop_bounds(&err) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
return (rv); return (rv);
} }
/* Initialize the library and container contexts. */ /* Initialize the library and container contexts. */
int c = ctx->load_kmods ? CAPS_INIT_KMODS : CAPS_INIT; int c = ctx->load_kmods ? NVC_INIT_KMODS : NVC_INIT;
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[c], effective_caps_size(c)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[c], ecaps_size(c)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -204,7 +200,7 @@ configure_command(const struct context *ctx) ...@@ -204,7 +200,7 @@ configure_command(const struct context *ctx)
warnx("initialization error: %s", nvc_error(nvc)); warnx("initialization error: %s", nvc_error(nvc));
goto fail; goto fail;
} }
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_CONTAINER], effective_caps_size(CAPS_CONTAINER)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_CONTAINER], ecaps_size(NVC_CONTAINER)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -215,7 +211,7 @@ configure_command(const struct context *ctx) ...@@ -215,7 +211,7 @@ configure_command(const struct context *ctx)
} }
/* Query the driver and device information. */ /* Query the driver and device information. */
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_INFO], effective_caps_size(CAPS_INFO)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_INFO], ecaps_size(NVC_INFO)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -263,7 +259,7 @@ configure_command(const struct context *ctx) ...@@ -263,7 +259,7 @@ configure_command(const struct context *ctx)
} }
/* Mount the driver and visible devices. */ /* Mount the driver and visible devices. */
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_MOUNT], effective_caps_size(CAPS_MOUNT)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_MOUNT], ecaps_size(NVC_MOUNT)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -279,7 +275,7 @@ configure_command(const struct context *ctx) ...@@ -279,7 +275,7 @@ configure_command(const struct context *ctx)
} }
/* Update the container ldcache. */ /* Update the container ldcache. */
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_LDCACHE], effective_caps_size(CAPS_LDCACHE)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_LDCACHE], ecaps_size(NVC_LDCACHE)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -288,7 +284,7 @@ configure_command(const struct context *ctx) ...@@ -288,7 +284,7 @@ configure_command(const struct context *ctx)
goto fail; goto fail;
} }
if (perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_SHUTDOWN], effective_caps_size(CAPS_SHUTDOWN)) < 0) { if (perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_SHUTDOWN], ecaps_size(NVC_SHUTDOWN)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
......
...@@ -53,27 +53,18 @@ info_command(const struct context *ctx) ...@@ -53,27 +53,18 @@ info_command(const struct context *ctx)
int rv = EXIT_FAILURE; int rv = EXIT_FAILURE;
run_as_root = (geteuid() == 0); run_as_root = (geteuid() == 0);
if (!run_as_root && (ctx->load_kmods || ctx->root != NULL)) {
warnx("requires root privileges");
return (rv);
}
if (run_as_root) { if (run_as_root) {
if (perm_set_capabilities(&err, CAP_PERMITTED, permitted_caps, nitems(permitted_caps)) < 0 || if (perm_set_capabilities(&err, CAP_PERMITTED, pcaps, nitems(pcaps)) < 0 ||
perm_set_capabilities(&err, CAP_INHERITABLE, inherited_caps, nitems(inherited_caps)) < 0 || perm_set_capabilities(&err, CAP_INHERITABLE, NULL, 0) < 0 ||
perm_drop_bounds(&err) < 0) { perm_set_bounds(&err, bcaps, nitems(bcaps)) < 0) {
warnx("permission error: %s", err.msg);
return (rv);
}
} else {
if (perm_set_capabilities(&err, CAP_PERMITTED, NULL, 0) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
return (rv); return (rv);
} }
} }
/* Initialize the library context. */ /* Initialize the library context. */
int c = ctx->load_kmods ? CAPS_INIT_KMODS : CAPS_INIT; int c = ctx->load_kmods ? NVC_INIT_KMODS : NVC_INIT;
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[c], effective_caps_size(c)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[c], ecaps_size(c)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -92,7 +83,7 @@ info_command(const struct context *ctx) ...@@ -92,7 +83,7 @@ info_command(const struct context *ctx)
} }
/* Query the driver and device information. */ /* Query the driver and device information. */
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_INFO], effective_caps_size(CAPS_INFO)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_INFO], ecaps_size(NVC_INFO)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -116,7 +107,7 @@ info_command(const struct context *ctx) ...@@ -116,7 +107,7 @@ info_command(const struct context *ctx)
"Bus Location:", dev->gpus[i].busid, "Architecture:", dev->gpus[i].arch); "Bus Location:", dev->gpus[i].busid, "Architecture:", dev->gpus[i].arch);
} }
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_SHUTDOWN], effective_caps_size(CAPS_SHUTDOWN)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_SHUTDOWN], ecaps_size(NVC_SHUTDOWN)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
......
...@@ -84,27 +84,18 @@ list_command(const struct context *ctx) ...@@ -84,27 +84,18 @@ list_command(const struct context *ctx)
int rv = EXIT_FAILURE; int rv = EXIT_FAILURE;
run_as_root = (geteuid() == 0); run_as_root = (geteuid() == 0);
if (!run_as_root && (ctx->load_kmods || ctx->root != NULL)) {
warnx("requires root privileges");
return (rv);
}
if (run_as_root) { if (run_as_root) {
if (perm_set_capabilities(&err, CAP_PERMITTED, permitted_caps, nitems(permitted_caps)) < 0 || if (perm_set_capabilities(&err, CAP_PERMITTED, pcaps, nitems(pcaps)) < 0 ||
perm_set_capabilities(&err, CAP_INHERITABLE, inherited_caps, nitems(inherited_caps)) < 0 || perm_set_capabilities(&err, CAP_INHERITABLE, NULL, 0) < 0 ||
perm_drop_bounds(&err) < 0) { perm_set_bounds(&err, bcaps, nitems(bcaps)) < 0) {
warnx("permission error: %s", err.msg);
return (rv);
}
} else {
if (perm_set_capabilities(&err, CAP_PERMITTED, NULL, 0) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
return (rv); return (rv);
} }
} }
/* Initialize the library context. */ /* Initialize the library context. */
int c = ctx->load_kmods ? CAPS_INIT_KMODS : CAPS_INIT; int c = ctx->load_kmods ? NVC_INIT_KMODS : NVC_INIT;
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[c], effective_caps_size(c)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[c], ecaps_size(c)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -123,7 +114,7 @@ list_command(const struct context *ctx) ...@@ -123,7 +114,7 @@ list_command(const struct context *ctx)
} }
/* Query the driver and device information. */ /* Query the driver and device information. */
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_INFO], effective_caps_size(CAPS_INFO)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_INFO], ecaps_size(NVC_INFO)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
...@@ -169,7 +160,7 @@ list_command(const struct context *ctx) ...@@ -169,7 +160,7 @@ list_command(const struct context *ctx)
printf("%s\n", drv->ipcs[i]); printf("%s\n", drv->ipcs[i]);
} }
if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, effective_caps[CAPS_SHUTDOWN], effective_caps_size(CAPS_SHUTDOWN)) < 0) { if (run_as_root && perm_set_capabilities(&err, CAP_EFFECTIVE, ecaps[NVC_SHUTDOWN], ecaps_size(NVC_SHUTDOWN)) < 0) {
warnx("permission error: %s", err.msg); warnx("permission error: %s", err.msg);
goto fail; goto fail;
} }
......
...@@ -175,8 +175,15 @@ load_kernel_modules(struct error *err, const char *root) ...@@ -175,8 +175,15 @@ load_kernel_modules(struct error *err, const char *root)
return (-1); return (-1);
} }
if (pid == 0) { if (pid == 0) {
if (chroot(root) < 0 || chdir("/") < 0) { if (!str_equal(root, "/")) {
log_errf("failed to change root directory: %s", strerror(errno)); if (chroot(root) < 0 || chdir("/") < 0) {
log_errf("failed to change root directory: %s", strerror(errno));
log_warn("skipping kernel modules load due to failure");
_exit(EXIT_FAILURE);
}
}
if (perm_set_capabilities(NULL, CAP_INHERITABLE, &(cap_value_t){CAP_SYS_MODULE}, 1) < 0) {
log_warn("failed to set inheritable capabilities");
log_warn("skipping kernel modules load due to failure"); log_warn("skipping kernel modules load due to failure");
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
} }
......
...@@ -54,18 +54,18 @@ struct nvc_container { ...@@ -54,18 +54,18 @@ struct nvc_container {
}; };
enum { enum {
CAPS_INIT, NVC_INIT,
CAPS_INIT_KMODS, NVC_INIT_KMODS,
CAPS_SHUTDOWN, NVC_SHUTDOWN,
CAPS_CONTAINER, NVC_CONTAINER,
CAPS_INFO, NVC_INFO,
CAPS_MOUNT, NVC_MOUNT,
CAPS_LDCACHE, NVC_LDCACHE,
}; };
static const cap_value_t permitted_caps[] = { static const cap_value_t pcaps[] = {
CAP_CHOWN, /* kmods */ CAP_CHOWN, /* kmods */
CAP_DAC_OVERRIDE, /* rhel, cgroups */ CAP_DAC_OVERRIDE, /* rhel userns, cgroups */
CAP_DAC_READ_SEARCH, /* userns */ CAP_DAC_READ_SEARCH, /* userns */
CAP_FOWNER, /* kmods */ CAP_FOWNER, /* kmods */
CAP_KILL, /* privsep */ CAP_KILL, /* privsep */
...@@ -78,30 +78,37 @@ static const cap_value_t permitted_caps[] = { ...@@ -78,30 +78,37 @@ static const cap_value_t permitted_caps[] = {
CAP_SYS_PTRACE, /* procns */ CAP_SYS_PTRACE, /* procns */
}; };
static const cap_value_t effective_caps[][nitems(permitted_caps) + 1] = { static const cap_value_t ecaps[][nitems(pcaps) + 1] = {
[CAPS_INIT] = {CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SYS_CHROOT, -1}, [NVC_INIT] = {CAP_KILL, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT, -1},
[CAPS_INIT_KMODS] = {CAP_KILL, CAP_CHOWN, CAP_FOWNER, CAP_MKNOD, CAP_SETGID, CAP_SETUID, CAP_SYS_CHROOT, -1},
[CAPS_SHUTDOWN] = {CAP_KILL, -1}, [NVC_INIT_KMODS] = {CAP_KILL, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT,
[CAPS_CONTAINER] = {CAP_KILL, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, -1}, CAP_CHOWN, CAP_FOWNER, CAP_MKNOD, CAP_SETPCAP, -1},
[CAPS_INFO] = {CAP_KILL, -1},
[CAPS_MOUNT] = {CAP_KILL, CAP_DAC_READ_SEARCH, CAP_SETGID, CAP_SETUID, CAP_SYS_ADMIN, [NVC_SHUTDOWN] = {CAP_KILL, -1},
CAP_SYS_CHROOT, CAP_SYS_PTRACE, -1},
[CAPS_LDCACHE] = {CAP_KILL, CAP_DAC_READ_SEARCH, CAP_SETGID, CAP_SETPCAP, CAP_SETUID, [NVC_CONTAINER] = {CAP_KILL, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, -1},
CAP_SYS_ADMIN, CAP_SYS_CHROOT, CAP_SYS_PTRACE, -1},
[NVC_INFO] = {CAP_KILL, -1},
[NVC_MOUNT] = {CAP_KILL, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT,
CAP_SYS_ADMIN, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, CAP_DAC_OVERRIDE, -1},
[NVC_LDCACHE] = {CAP_KILL, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT,
CAP_SYS_ADMIN, CAP_DAC_READ_SEARCH, CAP_SYS_PTRACE, CAP_SETPCAP, -1},
}; };
static const cap_value_t inherited_caps[] = { static const cap_value_t bcaps[] = {
CAP_DAC_OVERRIDE, CAP_DAC_OVERRIDE,
CAP_SYS_MODULE, CAP_SYS_MODULE,
}; };
static inline size_t static inline size_t
effective_caps_size(int idx) ecaps_size(int idx)
{ {
size_t i; size_t i;
for (i = 0; i < nitems(*effective_caps); ++i) { for (i = 0; i < nitems(*ecaps); ++i) {
if (effective_caps[idx][i] == -1) if (ecaps[idx][i] == -1)
break; break;
} }
return (i); return (i);
......
...@@ -153,8 +153,6 @@ change_rootfs(struct error *err, const char *rootfs, bool mount_proc, bool *drop ...@@ -153,8 +153,6 @@ change_rootfs(struct error *err, const char *rootfs, bool mount_proc, bool *drop
static int static int
adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig) adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig)
{ {
cap_value_t cap = CAP_DAC_OVERRIDE;
/* /*
* Drop all the inheritable capabilities and the ambient capabilities consequently. * Drop all the inheritable capabilities and the ambient capabilities consequently.
* Don't bother with the other capabilities, execve will take care of it. * Don't bother with the other capabilities, execve will take care of it.
...@@ -168,13 +166,13 @@ adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig) ...@@ -168,13 +166,13 @@ adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig)
* If allowed, set the CAP_DAC_OVERRIDE capability because some distributions rely on it * If allowed, set the CAP_DAC_OVERRIDE capability because some distributions rely on it
* (e.g. https://bugzilla.redhat.com/show_bug.cgi?id=517575). * (e.g. https://bugzilla.redhat.com/show_bug.cgi?id=517575).
*/ */
if (perm_set_capabilities(err, CAP_INHERITABLE, &cap, 1) < 0) { if (perm_set_capabilities(err, CAP_INHERITABLE, &(cap_value_t){CAP_DAC_OVERRIDE}, 1) < 0) {
if (err->code != EPERM) if (err->code != EPERM)
return (-1); return (-1);
if (perm_set_capabilities(err, CAP_INHERITABLE, NULL, 0) < 0) if (perm_set_capabilities(err, CAP_INHERITABLE, NULL, 0) < 0)
return (-1); return (-1);
log_warn("could not set inheritable capabilities, containers may require additional tuning"); log_warn("could not set inheritable capabilities, containers may require additional tuning");
} else if (uid != 0 && perm_set_capabilities(err, CAP_AMBIENT, &cap, 1) < 0) { } else if (uid != 0 && perm_set_capabilities(err, CAP_AMBIENT, &(cap_value_t){CAP_DAC_OVERRIDE}, 1) < 0) {
if (err->code != EPERM) if (err->code != EPERM)
return (-1); return (-1);
log_warn("could not set ambient capabilities, containers may require additional tuning"); log_warn("could not set ambient capabilities, containers may require additional tuning");
...@@ -182,7 +180,7 @@ adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig) ...@@ -182,7 +180,7 @@ adjust_capabilities(struct error *err, uid_t uid, bool host_ldconfig)
} }
/* Drop all the bounding set */ /* Drop all the bounding set */
if (perm_drop_bounds(err) < 0) if (perm_set_bounds(err, NULL, 0) < 0)
return (-1); return (-1);
return (0); return (0);
......
...@@ -918,7 +918,7 @@ perm_drop_privileges(struct error *err, uid_t uid, gid_t gid, bool drop_groups) ...@@ -918,7 +918,7 @@ perm_drop_privileges(struct error *err, uid_t uid, gid_t gid, bool drop_groups)
} }
int int
perm_drop_bounds(struct error *err) perm_set_bounds(struct error *err, const cap_value_t caps[], size_t size)
{ {
uint32_t n; uint32_t n;
cap_value_t last_cap = CAP_LAST_CAP; cap_value_t last_cap = CAP_LAST_CAP;
...@@ -929,10 +929,15 @@ perm_drop_bounds(struct error *err) ...@@ -929,10 +929,15 @@ perm_drop_bounds(struct error *err)
last_cap = (cap_value_t)n; last_cap = (cap_value_t)n;
for (cap_value_t c = 0; c <= last_cap; ++c) { for (cap_value_t c = 0; c <= last_cap; ++c) {
for (size_t i = 0; caps != NULL && i < size; ++i) {
if (caps[i] == c)
goto next;
}
if (prctl(PR_CAPBSET_READ, c) > 0 && prctl(PR_CAPBSET_DROP, c) < 0) { if (prctl(PR_CAPBSET_READ, c) > 0 && prctl(PR_CAPBSET_DROP, c) < 0) {
error_set(err, "capability change failed"); error_set(err, "capability change failed");
return (-1); return (-1);
} }
next:;
} }
return (0); return (0);
} }
...@@ -949,11 +954,9 @@ perm_set_capabilities(struct error *err, cap_flag_t type, const cap_value_t caps ...@@ -949,11 +954,9 @@ perm_set_capabilities(struct error *err, cap_flag_t type, const cap_value_t caps
/* Ambient capabilities are only supported since Linux 4.3 and are not available in libcap. */ /* Ambient capabilities are only supported since Linux 4.3 and are not available in libcap. */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) < 0 && errno != EINVAL) if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0) < 0 && errno != EINVAL)
goto fail; goto fail;
if (caps != NULL && size > 0) { for (size_t i = 0; caps != NULL && i < size; ++i) {
for (size_t i = 0; i < size; ++i) { if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, caps[i], 0, 0) < 0 && errno != EINVAL)
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, caps[i], 0, 0) < 0 && errno != EINVAL) goto fail;
goto fail;
}
} }
return (0); return (0);
} }
...@@ -971,13 +974,11 @@ perm_set_capabilities(struct error *err, cap_flag_t type, const cap_value_t caps ...@@ -971,13 +974,11 @@ perm_set_capabilities(struct error *err, cap_flag_t type, const cap_value_t caps
goto fail; goto fail;
if (cap_clear_flag(state, CAP_EFFECTIVE) < 0) if (cap_clear_flag(state, CAP_EFFECTIVE) < 0)
goto fail; goto fail;
if (caps != NULL && size > 0) { for (size_t i = 0; caps != NULL && i < size; ++i) {
for (size_t i = 0; i < size; ++i) { if (cap_get_flag(tmp, caps[i], CAP_EFFECTIVE, &flag) < 0)
if (cap_get_flag(tmp, caps[i], CAP_EFFECTIVE, &flag) < 0) goto fail;
goto fail; if (cap_set_flag(state, CAP_EFFECTIVE, 1, &caps[i], flag) < 0)
if (cap_set_flag(state, CAP_EFFECTIVE, 1, &caps[i], flag) < 0) goto fail;
goto fail;
}
} }
} }
if (cap_set_proc(state) < 0) if (cap_set_proc(state) < 0)
......
...@@ -81,7 +81,7 @@ int path_resolve(struct error *, char *, const char *, const char *); ...@@ -81,7 +81,7 @@ int path_resolve(struct error *, char *, const char *, const char *);
int path_resolve_full(struct error *, char *, const char *, const char *); int path_resolve_full(struct error *, char *, const char *, const char *);
int perm_drop_privileges(struct error *, uid_t, gid_t, bool); int perm_drop_privileges(struct error *, uid_t, gid_t, bool);
int perm_drop_bounds(struct error *); int perm_set_bounds(struct error *, const cap_value_t [], size_t);
int perm_set_capabilities(struct error *, cap_flag_t, const cap_value_t [], size_t); int perm_set_capabilities(struct error *, cap_flag_t, const cap_value_t [], size_t);
#endif /* HEADER_UTILS_H */ #endif /* HEADER_UTILS_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册