mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-06 08:39:22 +00:00
Merge pull request #2332 from brauner/2018-05-16/use_ambient_capabilities
capabilities: raise ambient capabilities
This commit is contained in:
commit
23cf184dae
130
src/lxc/caps.c
130
src/lxc/caps.c
@ -42,6 +42,27 @@ lxc_log_define(lxc_caps, lxc);
|
||||
#define PR_CAPBSET_READ 23
|
||||
#endif
|
||||
|
||||
/* Control the ambient capability set */
|
||||
#ifndef PR_CAP_AMBIENT
|
||||
#define PR_CAP_AMBIENT 47
|
||||
#endif
|
||||
|
||||
#ifndef PR_CAP_AMBIENT_IS_SET
|
||||
#define PR_CAP_AMBIENT_IS_SET 1
|
||||
#endif
|
||||
|
||||
#ifndef PR_CAP_AMBIENT_RAISE
|
||||
#define PR_CAP_AMBIENT_RAISE 2
|
||||
#endif
|
||||
|
||||
#ifndef PR_CAP_AMBIENT_LOWER
|
||||
#define PR_CAP_AMBIENT_LOWER 3
|
||||
#endif
|
||||
|
||||
#ifndef PR_CAP_AMBIENT_CLEAR_ALL
|
||||
#define PR_CAP_AMBIENT_CLEAR_ALL 4
|
||||
#endif
|
||||
|
||||
int lxc_caps_down(void)
|
||||
{
|
||||
cap_t caps;
|
||||
@ -126,6 +147,115 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_ambient_caps_up(void)
|
||||
{
|
||||
int ret;
|
||||
cap_t caps;
|
||||
cap_value_t cap;
|
||||
int last_cap = CAP_LAST_CAP;
|
||||
char *cap_names = NULL;
|
||||
|
||||
/* When we are run as root, we don't want to play with the capabilities. */
|
||||
if (!getuid())
|
||||
return 0;
|
||||
|
||||
caps = cap_get_proc();
|
||||
if (!caps) {
|
||||
SYSERROR("Failed to retrieve capabilities");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
|
||||
cap_flag_value_t flag;
|
||||
|
||||
ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
|
||||
if (ret < 0) {
|
||||
if (errno == EINVAL) {
|
||||
last_cap = (cap - 1);
|
||||
INFO("Last supported cap was %d", last_cap);
|
||||
break;
|
||||
}
|
||||
|
||||
SYSERROR("Failed to retrieve capability flag");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, flag);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to set capability flag");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = cap_set_proc(caps);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to set capabilities");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (cap = 0; cap <= last_cap; cap++) {
|
||||
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0);
|
||||
if (ret < 0) {
|
||||
WARN("%s - Failed to raise ambient capability %d",
|
||||
strerror(errno), cap);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
cap_names = cap_to_text(caps, NULL);
|
||||
if (!cap_names)
|
||||
goto out;
|
||||
|
||||
TRACE("Raised %s in inheritable and ambient capability set", cap_names);
|
||||
|
||||
out:
|
||||
|
||||
cap_free(cap_names);
|
||||
cap_free(caps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_ambient_caps_down(void)
|
||||
{
|
||||
int ret;
|
||||
cap_t caps;
|
||||
cap_value_t cap;
|
||||
|
||||
/* When we are run as root, we don't want to play with the capabilities. */
|
||||
if (!getuid())
|
||||
return 0;
|
||||
|
||||
ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to clear ambient capability set");
|
||||
return -1;
|
||||
}
|
||||
|
||||
caps = cap_get_proc();
|
||||
if (!caps) {
|
||||
SYSERROR("Failed to retrieve capabilities");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
|
||||
ret = cap_set_flag(caps, CAP_INHERITABLE, 1, &cap, CAP_CLEAR);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to remove capability from inheritable set");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = cap_set_proc(caps);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to set capabilities");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
cap_free(caps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_caps_init(void)
|
||||
{
|
||||
uid_t uid = getuid();
|
||||
|
@ -27,70 +27,91 @@
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#if HAVE_LIBCAP
|
||||
#include <linux/types.h> /* workaround for libcap < 2.17 bug */
|
||||
#include <sys/capability.h>
|
||||
|
||||
extern int lxc_caps_down(void);
|
||||
extern int lxc_caps_up(void);
|
||||
extern int lxc_ambient_caps_up(void);
|
||||
extern int lxc_ambient_caps_down(void);
|
||||
extern int lxc_caps_init(void);
|
||||
|
||||
extern int lxc_caps_last_cap(void);
|
||||
|
||||
extern bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag);
|
||||
extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag);
|
||||
extern bool lxc_file_cap_is_set(const char *path, cap_value_t cap,
|
||||
cap_flag_t flag);
|
||||
#else
|
||||
static inline int lxc_caps_down(void) {
|
||||
return 0;
|
||||
}
|
||||
static inline int lxc_caps_up(void) {
|
||||
return 0;
|
||||
}
|
||||
static inline int lxc_caps_init(void) {
|
||||
static inline int lxc_caps_down(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lxc_caps_last_cap(void) {
|
||||
static inline int lxc_caps_up(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lxc_ambient_caps_up(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lxc_ambient_caps_down(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lxc_caps_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lxc_caps_last_cap(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int cap_value_t;
|
||||
typedef int cap_flag_t;
|
||||
static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag) {
|
||||
static inline bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag) {
|
||||
static inline bool lxc_file_cap_is_set(const char *path, cap_value_t cap,
|
||||
cap_flag_t flag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define lxc_priv(__lxc_function) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
int __ret, __ret2, ___errno = 0; \
|
||||
__ret = lxc_caps_up(); \
|
||||
if (__ret) \
|
||||
goto out; \
|
||||
__ret = __lxc_function; \
|
||||
if (__ret) \
|
||||
___errno = errno; \
|
||||
__ret2 = lxc_caps_down(); \
|
||||
out: __ret ? errno = ___errno,__ret : __ret2; \
|
||||
#define lxc_priv(__lxc_function) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
int __ret, __ret2, ___errno = 0; \
|
||||
__ret = lxc_caps_up(); \
|
||||
if (__ret) \
|
||||
goto out; \
|
||||
__ret = __lxc_function; \
|
||||
if (__ret) \
|
||||
___errno = errno; \
|
||||
__ret2 = lxc_caps_down(); \
|
||||
out: \
|
||||
__ret ? errno = ___errno, __ret : __ret2; \
|
||||
})
|
||||
|
||||
#define lxc_unpriv(__lxc_function) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
int __ret, __ret2, ___errno = 0; \
|
||||
__ret = lxc_caps_down(); \
|
||||
if (__ret) \
|
||||
goto out; \
|
||||
__ret = __lxc_function; \
|
||||
if (__ret) \
|
||||
___errno = errno; \
|
||||
__ret2 = lxc_caps_up(); \
|
||||
out: __ret ? errno = ___errno,__ret : __ret2; \
|
||||
#define lxc_unpriv(__lxc_function) \
|
||||
({ \
|
||||
__label__ out; \
|
||||
int __ret, __ret2, ___errno = 0; \
|
||||
__ret = lxc_caps_down(); \
|
||||
if (__ret) \
|
||||
goto out; \
|
||||
__ret = __lxc_function; \
|
||||
if (__ret) \
|
||||
___errno = errno; \
|
||||
__ret2 = lxc_caps_up(); \
|
||||
out: \
|
||||
__ret ? errno = ___errno, __ret : __ret2; \
|
||||
})
|
||||
#endif
|
||||
|
@ -1049,6 +1049,12 @@ static int do_start(void *data)
|
||||
goto out_warn_father;
|
||||
}
|
||||
|
||||
ret = lxc_ambient_caps_up();
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to raise ambient capabilities");
|
||||
goto out_warn_father;
|
||||
}
|
||||
|
||||
ret = sigprocmask(SIG_SETMASK, &handler->oldmask, NULL);
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to set signal mask");
|
||||
@ -1081,7 +1087,7 @@ static int do_start(void *data)
|
||||
*/
|
||||
ret = lxc_sync_barrier_parent(handler, LXC_SYNC_CONFIGURE);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
goto out_error;
|
||||
|
||||
ret = lxc_network_recv_veth_names_from_parent(handler);
|
||||
if (ret < 0) {
|
||||
@ -1348,6 +1354,12 @@ static int do_start(void *data)
|
||||
if (ret < 0)
|
||||
goto out_warn_father;
|
||||
|
||||
ret = lxc_ambient_caps_down();
|
||||
if (ret < 0) {
|
||||
SYSERROR("Failed to clear ambient capabilities");
|
||||
goto out_warn_father;
|
||||
}
|
||||
|
||||
/* After this call, we are in error because this ops should not return
|
||||
* as it execs.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user