]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/caps.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #include <sys/prctl.h>
36 #include "file_utils.h"
40 lxc_log_define(caps
, lxc
);
44 int lxc_caps_down(void)
49 /* When we are root, we don't want to play with capabilities. */
53 caps
= cap_get_proc();
55 SYSERROR("Failed to retrieve capabilities");
59 ret
= cap_clear_flag(caps
, CAP_EFFECTIVE
);
61 SYSERROR("Failed to clear effective capabilities");
65 ret
= cap_set_proc(caps
);
67 SYSERROR("Failed to change effective capabilities");
85 /* When we are root, we don't want to play with capabilities. */
89 caps
= cap_get_proc();
91 SYSERROR("Failed to retrieve capabilities");
95 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
96 cap_flag_value_t flag
;
98 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
100 if (errno
== EINVAL
) {
101 INFO("Last supported cap was %d", cap
- 1);
104 SYSERROR("Failed to retrieve setting for "
105 "permitted capability %d", cap
- 1);
110 ret
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, &cap
, flag
);
112 SYSERROR("Failed to set effective capability %d", cap
- 1);
117 ret
= cap_set_proc(caps
);
119 SYSERROR("Failed to change effective capabilities");
131 int lxc_ambient_caps_up(void)
136 int last_cap
= CAP_LAST_CAP
;
137 char *cap_names
= NULL
;
139 /* When we are root, we don't want to play with capabilities. */
143 caps
= cap_get_proc();
145 SYSERROR("Failed to retrieve capabilities");
149 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
150 cap_flag_value_t flag
;
152 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
154 if (errno
== EINVAL
) {
155 last_cap
= (cap
- 1);
156 INFO("Last supported cap was %d", last_cap
);
160 SYSERROR("Failed to retrieve capability flag");
164 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, flag
);
166 SYSERROR("Failed to set capability flag");
171 ret
= cap_set_proc(caps
);
173 SYSERROR("Failed to set capabilities");
177 for (cap
= 0; cap
<= last_cap
; cap
++) {
178 ret
= prctl(PR_CAP_AMBIENT
, prctl_arg(PR_CAP_AMBIENT_RAISE
),
179 prctl_arg(cap
), prctl_arg(0), prctl_arg(0));
181 SYSWARN("Failed to raise ambient capability %d", cap
);
186 cap_names
= cap_to_text(caps
, NULL
);
188 SYSWARN("Failed to convert capabilities %d", cap
);
192 TRACE("Raised %s in inheritable and ambient capability set", cap_names
);
201 int lxc_ambient_caps_down(void)
207 /* When we are root, we don't want to play with capabilities. */
211 ret
= prctl(PR_CAP_AMBIENT
, prctl_arg(PR_CAP_AMBIENT_CLEAR_ALL
),
212 prctl_arg(0), prctl_arg(0), prctl_arg(0));
214 SYSERROR("Failed to clear ambient capability set");
218 caps
= cap_get_proc();
220 SYSERROR("Failed to retrieve capabilities");
224 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
225 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, CAP_CLEAR
);
227 SYSERROR("Failed to remove capability from inheritable set");
232 ret
= cap_set_proc(caps
);
234 SYSERROR("Failed to set capabilities");
243 int lxc_caps_init(void)
256 INFO("Command is run as setuid root (uid: %d)", uid
);
258 ret
= prctl(PR_SET_KEEPCAPS
, prctl_arg(1));
260 SYSERROR("Failed to set PR_SET_KEEPCAPS");
265 ret
= setresgid(gid
, gid
, gid
);
267 SYSERROR("Failed to change rgid, egid, and sgid to %d", gid
);
271 ret
= setresuid(uid
, uid
, uid
);
273 SYSERROR("Failed to change ruid, euid, and suid to %d", uid
);
279 SYSERROR("Failed to restore capabilities");
285 INFO("Command is run with uid %d", uid
);
290 static long int _real_caps_last_cap(void)
294 /* Try to get the maximum capability over the kernel interface
295 * introduced in v3.2.
297 fd
= open("/proc/sys/kernel/cap_last_cap", O_RDONLY
| O_CLOEXEC
);
301 char buf
[INTTYPE_TO_STRLEN(int)] = {0};
303 n
= lxc_read_nointr(fd
, buf
, STRARRAYLEN(buf
));
306 result
= strtol(buf
, &ptr
, 10);
307 if (!ptr
|| (*ptr
!= '\0' && *ptr
!= '\n') || errno
!= 0)
315 /* Try to get it manually by trying to get the status of each
316 * capability individually from the kernel.
318 while (prctl(PR_CAPBSET_READ
, prctl_arg(cap
)) >= 0)
327 int lxc_caps_last_cap(void)
329 static long int last_cap
= -1;
332 last_cap
= _real_caps_last_cap();
333 if (last_cap
< 0 || last_cap
> INT_MAX
)
340 static bool lxc_cap_is_set(cap_t caps
, cap_value_t cap
, cap_flag_t flag
)
343 cap_flag_value_t flagval
;
345 ret
= cap_get_flag(caps
, cap
, flag
, &flagval
);
347 SYSERROR("Failed to retrieve current setting for capability %d", cap
);
351 return flagval
== CAP_SET
;
354 bool lxc_file_cap_is_set(const char *path
, cap_value_t cap
, cap_flag_t flag
)
356 #if LIBCAP_SUPPORTS_FILE_CAPABILITIES
360 caps
= cap_get_file(path
);
362 /* This is undocumented in the manpage but the source code show
363 * that cap_get_file() may return NULL when successful for the
364 * case where it didn't detect any file capabilities. In this
365 * case errno will be set to ENODATA.
367 if (errno
!= ENODATA
)
368 SYSERROR("Failed to retrieve capabilities for file %s", path
);
373 cap_is_set
= lxc_cap_is_set(caps
, cap
, flag
);
382 bool lxc_proc_cap_is_set(cap_value_t cap
, cap_flag_t flag
)
387 caps
= cap_get_proc();
389 SYSERROR("Failed to retrieve capabilities");
393 cap_is_set
= lxc_cap_is_set(caps
, cap
, flag
);