]>
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>
37 lxc_log_define(lxc_caps
, lxc
);
41 #ifndef PR_CAPBSET_READ
42 #define PR_CAPBSET_READ 23
45 /* Control the ambient capability set */
46 #ifndef PR_CAP_AMBIENT
47 #define PR_CAP_AMBIENT 47
50 #ifndef PR_CAP_AMBIENT_IS_SET
51 #define PR_CAP_AMBIENT_IS_SET 1
54 #ifndef PR_CAP_AMBIENT_RAISE
55 #define PR_CAP_AMBIENT_RAISE 2
58 #ifndef PR_CAP_AMBIENT_LOWER
59 #define PR_CAP_AMBIENT_LOWER 3
62 #ifndef PR_CAP_AMBIENT_CLEAR_ALL
63 #define PR_CAP_AMBIENT_CLEAR_ALL 4
66 int lxc_caps_down(void)
71 /* when we are run as root, we don't want to play
72 * with the capabilities */
76 caps
= cap_get_proc();
78 ERROR("failed to cap_get_proc: %s", strerror(errno
));
82 ret
= cap_clear_flag(caps
, CAP_EFFECTIVE
);
84 ERROR("failed to cap_clear_flag: %s", strerror(errno
));
88 ret
= cap_set_proc(caps
);
90 ERROR("failed to cap_set_proc: %s", strerror(errno
));
105 /* when we are run as root, we don't want to play
106 * with the capabilities */
110 caps
= cap_get_proc();
112 ERROR("failed to cap_get_proc: %s", strerror(errno
));
116 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
118 cap_flag_value_t flag
;
120 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
122 if (errno
== EINVAL
) {
123 INFO("Last supported cap was %d", cap
-1);
126 ERROR("failed to cap_get_flag: %s",
132 ret
= cap_set_flag(caps
, CAP_EFFECTIVE
, 1, &cap
, flag
);
134 ERROR("failed to cap_set_flag: %s", strerror(errno
));
139 ret
= cap_set_proc(caps
);
141 ERROR("failed to cap_set_proc: %s", strerror(errno
));
150 int lxc_ambient_caps_up(void)
155 int last_cap
= CAP_LAST_CAP
;
156 char *cap_names
= NULL
;
158 /* When we are run as root, we don't want to play with the capabilities. */
162 caps
= cap_get_proc();
164 SYSERROR("Failed to retrieve capabilities");
168 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
169 cap_flag_value_t flag
;
171 ret
= cap_get_flag(caps
, cap
, CAP_PERMITTED
, &flag
);
173 if (errno
== EINVAL
) {
174 last_cap
= (cap
- 1);
175 INFO("Last supported cap was %d", last_cap
);
179 SYSERROR("Failed to retrieve capability flag");
183 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, flag
);
185 SYSERROR("Failed to set capability flag");
190 ret
= cap_set_proc(caps
);
192 SYSERROR("Failed to set capabilities");
196 for (cap
= 0; cap
<= last_cap
; cap
++) {
197 ret
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_RAISE
, cap
, 0, 0);
199 SYSWARN("Failed to raise ambient capability %d", cap
);
204 cap_names
= cap_to_text(caps
, NULL
);
208 TRACE("Raised %s in inheritable and ambient capability set", cap_names
);
217 int lxc_ambient_caps_down(void)
223 /* When we are run as root, we don't want to play with the capabilities. */
227 ret
= prctl(PR_CAP_AMBIENT
, PR_CAP_AMBIENT_CLEAR_ALL
, 0, 0, 0);
229 SYSERROR("Failed to clear ambient capability set");
233 caps
= cap_get_proc();
235 SYSERROR("Failed to retrieve capabilities");
239 for (cap
= 0; cap
<= CAP_LAST_CAP
; cap
++) {
240 ret
= cap_set_flag(caps
, CAP_INHERITABLE
, 1, &cap
, CAP_CLEAR
);
242 SYSERROR("Failed to remove capability from inheritable set");
247 ret
= cap_set_proc(caps
);
249 SYSERROR("Failed to set capabilities");
258 int lxc_caps_init(void)
260 uid_t uid
= getuid();
261 gid_t gid
= getgid();
262 uid_t euid
= geteuid();
265 INFO("command is run as 'root'");
270 INFO("command is run as setuid root (uid : %d)", uid
);
272 if (prctl(PR_SET_KEEPCAPS
, 1)) {
273 ERROR("failed to 'PR_SET_KEEPCAPS': %s",
278 if (setresgid(gid
, gid
, gid
)) {
279 ERROR("failed to change gid to '%d': %s", gid
,
284 if (setresuid(uid
, uid
, uid
)) {
285 ERROR("failed to change uid to '%d': %s", uid
,
291 ERROR("failed to restore capabilities: %s",
298 INFO("command is run as user '%d'", uid
);
303 static int _real_caps_last_cap(void)
308 /* try to get the maximum capability over the kernel
309 * interface introduced in v3.2 */
310 fd
= open("/proc/sys/kernel/cap_last_cap", O_RDONLY
);
316 if ((n
= read(fd
, buf
, 31)) >= 0) {
319 result
= strtol(buf
, &ptr
, 10);
320 if (!ptr
|| (*ptr
!= '\0' && *ptr
!= '\n') || errno
!= 0)
327 /* try to get it manually by trying to get the status of
328 * each capability indiviually from the kernel */
331 while (prctl(PR_CAPBSET_READ
, cap
) >= 0) cap
++;
338 int lxc_caps_last_cap(void)
340 static int last_cap
= -1;
341 if (last_cap
< 0) last_cap
= _real_caps_last_cap();
346 static bool lxc_cap_is_set(cap_t caps
, cap_value_t cap
, cap_flag_t flag
)
349 cap_flag_value_t flagval
;
351 ret
= cap_get_flag(caps
, cap
, flag
, &flagval
);
353 ERROR("Failed to perform cap_get_flag(): %s.", strerror(errno
));
357 return flagval
== CAP_SET
;
360 bool lxc_file_cap_is_set(const char *path
, cap_value_t cap
, cap_flag_t flag
)
362 #if LIBCAP_SUPPORTS_FILE_CAPABILITIES
366 caps
= cap_get_file(path
);
368 /* This is undocumented in the manpage but the source code show
369 * that cap_get_file() may return NULL when successful for the
370 * case where it didn't detect any file capabilities. In this
371 * case errno will be set to ENODATA.
373 if (errno
!= ENODATA
)
374 ERROR("Failed to perform cap_get_file(): %s.\n", strerror(errno
));
378 cap_is_set
= lxc_cap_is_set(caps
, cap
, flag
);
387 bool lxc_proc_cap_is_set(cap_value_t cap
, cap_flag_t flag
)
392 caps
= cap_get_proc();
394 ERROR("Failed to perform cap_get_proc(): %s.\n", strerror(errno
));
398 cap_is_set
= lxc_cap_is_set(caps
, cap
, flag
);