]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/caps.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
11 #include <sys/prctl.h>
15 #include "file_utils.h"
18 #include "memory_utils.h"
20 lxc_log_define(caps
, lxc
);
24 define_cleanup_function(cap_t
, cap_free
);
26 int lxc_caps_down(void)
28 call_cleaner(cap_free
) cap_t caps
= NULL
;
31 /* When we are root, we don't want to play with capabilities. */
35 caps
= cap_get_proc();
37 return log_error_errno(ret
, errno
, "Failed to retrieve capabilities");
39 ret
= cap_clear_flag(caps
, CAP_EFFECTIVE
);
41 return log_error_errno(ret
, errno
, "Failed to clear effective capabilities");
43 ret
= cap_set_proc(caps
);
45 return log_error_errno(ret
, errno
, "Failed to change effective capabilities");
52 call_cleaner(cap_free
) cap_t caps
= NULL
;
56 /* When we are root, we don't want to play with capabilities. */
60 caps
= cap_get_proc();
62 return log_error_errno(ret
, errno
, "Failed to retrieve capabilities");
64 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
65 cap_flag_value_t flag
;
67 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
69 if (errno
== EINVAL
) {
70 INFO("Last supported cap was %d", cap
- 1);
73 return log_error_errno(ret
, errno
, "Failed to retrieve setting for permitted capability %d", cap
- 1);
77 ret
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, &cap
, flag
);
79 return log_error_errno(ret
, errno
, "Failed to set effective capability %d", cap
- 1);
82 ret
= cap_set_proc(caps
);
84 return log_error_errno(ret
, errno
, "Failed to change effective capabilities");
89 int lxc_ambient_caps_up(void)
91 call_cleaner(cap_free
) cap_t caps
= NULL
;
92 __do_free
char *cap_names
= NULL
;
95 int last_cap
= CAP_LAST_CAP
;
97 if (!getuid() || geteuid())
100 caps
= cap_get_proc();
102 return log_error_errno(-1, errno
, "Failed to retrieve capabilities");
104 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
105 cap_flag_value_t flag
;
107 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
109 if (errno
== EINVAL
) {
110 last_cap
= (cap
- 1);
111 INFO("Last supported cap was %d", last_cap
);
115 return log_error_errno(ret
, errno
, "Failed to retrieve capability flag");
118 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, flag
);
120 return log_error_errno(ret
, errno
, "Failed to set capability flag");
123 ret
= cap_set_proc(caps
);
125 return log_error_errno(ret
, errno
, "Failed to set capabilities");
127 for (cap
= 0; cap
<= last_cap
; cap
++) {
128 ret
= prctl(PR_CAP_AMBIENT
, prctl_arg(PR_CAP_AMBIENT_RAISE
),
129 prctl_arg(cap
), prctl_arg(0), prctl_arg(0));
131 return log_warn_errno(ret
, errno
, "Failed to raise ambient capability %d", cap
);
134 cap_names
= cap_to_text(caps
, NULL
);
136 return log_warn_errno(0, errno
, "Failed to convert capabilities %d", cap
);
138 TRACE("Raised %s in inheritable and ambient capability set", cap_names
);
142 int lxc_ambient_caps_down(void)
144 call_cleaner(cap_free
) cap_t caps
= NULL
;
148 if (!getuid() || geteuid())
151 ret
= prctl(PR_CAP_AMBIENT
, prctl_arg(PR_CAP_AMBIENT_CLEAR_ALL
),
152 prctl_arg(0), prctl_arg(0), prctl_arg(0));
154 return log_error_errno(-1, errno
, "Failed to clear ambient capability set");
156 caps
= cap_get_proc();
158 return log_error_errno(-1, errno
, "Failed to retrieve capabilities");
160 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
161 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, CAP_CLEAR
);
163 return log_error_errno(-1, errno
, "Failed to clear capability");
166 ret
= cap_set_proc(caps
);
168 return log_error_errno(ret
, errno
, "Failed to set capabilities");
173 int lxc_caps_init(void)
186 INFO("Command is run as setuid root (uid: %d)", uid
);
188 ret
= prctl(PR_SET_KEEPCAPS
, prctl_arg(1));
190 return log_error_errno(-1, errno
, "Failed to set PR_SET_KEEPCAPS");
193 ret
= setresgid(gid
, gid
, gid
);
195 return log_error_errno(-1, errno
, "Failed to change rgid, egid, and sgid to %d", gid
);
197 ret
= setresuid(uid
, uid
, uid
);
199 return log_error_errno(-1, errno
, "Failed to change ruid, euid, and suid to %d", uid
);
203 return log_error_errno(-1, errno
, "Failed to restore capabilities");
207 INFO("Command is run with uid %d", uid
);
212 static long int _real_caps_last_cap(void)
216 /* Try to get the maximum capability over the kernel interface
217 * introduced in v3.2.
219 fd
= open("/proc/sys/kernel/cap_last_cap", O_RDONLY
| O_CLOEXEC
);
223 char buf
[INTTYPE_TO_STRLEN(int)] = {0};
225 n
= lxc_read_nointr(fd
, buf
, STRARRAYLEN(buf
));
228 result
= strtol(buf
, &ptr
, 10);
229 if (!ptr
|| (*ptr
!= '\0' && *ptr
!= '\n') || errno
!= 0)
237 /* Try to get it manually by trying to get the status of each
238 * capability individually from the kernel.
240 while (prctl(PR_CAPBSET_READ
, prctl_arg(cap
)) >= 0)
249 int lxc_caps_last_cap(void)
251 static long int last_cap
= -1;
254 last_cap
= _real_caps_last_cap();
255 if (last_cap
< 0 || last_cap
> INT_MAX
)
262 static bool lxc_cap_is_set(cap_t caps
, cap_value_t cap
, cap_flag_t flag
)
265 cap_flag_value_t flagval
;
267 ret
= cap_get_flag(caps
, cap
, flag
, &flagval
);
269 return log_error_errno(false, errno
, "Failed to retrieve current setting for capability %d", cap
);
271 return flagval
== CAP_SET
;
274 bool lxc_file_cap_is_set(const char *path
, cap_value_t cap
, cap_flag_t flag
)
276 #if LIBCAP_SUPPORTS_FILE_CAPABILITIES
277 call_cleaner(cap_free
) cap_t caps
= NULL
;
279 caps
= cap_get_file(path
);
281 /* This is undocumented in the manpage but the source code show
282 * that cap_get_file() may return NULL when successful for the
283 * case where it didn't detect any file capabilities. In this
284 * case errno will be set to ENODATA.
286 if (errno
!= ENODATA
)
287 SYSERROR("Failed to retrieve capabilities for file %s", path
);
292 return lxc_cap_is_set(caps
, cap
, flag
);
299 bool lxc_proc_cap_is_set(cap_value_t cap
, cap_flag_t flag
)
301 call_cleaner(cap_free
) cap_t caps
= NULL
;
303 caps
= cap_get_proc();
305 return log_error_errno(false, errno
, "Failed to retrieve capabilities");
307 return lxc_cap_is_set(caps
, cap
, flag
);