]>
Commit | Line | Data |
---|---|---|
b3357a6f DL |
1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
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. | |
13 | * | |
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. | |
18 | * | |
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #define _GNU_SOURCE | |
25 | #include <unistd.h> | |
26 | #include <sys/prctl.h> | |
27 | #include <sys/capability.h> | |
28 | ||
29 | #include "log.h" | |
30 | ||
31 | lxc_log_define(lxc_caps, lxc); | |
32 | ||
05cda563 DL |
33 | int lxc_caps_reset(void) |
34 | { | |
35 | cap_t cap = cap_init(); | |
36 | int ret = 0; | |
37 | ||
38 | if (!cap) { | |
39 | ERROR("cap_init() failed : %m"); | |
40 | return -1; | |
41 | } | |
42 | ||
43 | if (cap_set_proc(cap)) { | |
44 | ERROR("cap_set_proc() failed : %m"); | |
45 | ret = -1; | |
46 | } | |
47 | ||
48 | cap_free(cap); | |
49 | return ret; | |
50 | } | |
51 | ||
b3357a6f DL |
52 | int lxc_caps_down(void) |
53 | { | |
54 | cap_t caps; | |
55 | int ret; | |
56 | ||
57 | caps = cap_get_proc(); | |
58 | if (!caps) { | |
59 | ERROR("failed to cap_get_proc: %m"); | |
60 | return -1; | |
61 | } | |
62 | ||
63 | ret = cap_clear_flag(caps, CAP_EFFECTIVE); | |
64 | if (ret) { | |
65 | ERROR("failed to cap_clear_flag: %m"); | |
66 | goto out; | |
67 | } | |
68 | ||
69 | ret = cap_set_proc(caps); | |
70 | if (ret) { | |
71 | ERROR("failed to cap_set_proc: %m"); | |
72 | goto out; | |
73 | } | |
74 | ||
75 | out: | |
76 | cap_free(caps); | |
77 | return 0; | |
78 | } | |
79 | ||
80 | int lxc_caps_up(void) | |
81 | { | |
82 | cap_t caps; | |
83 | cap_value_t cap; | |
84 | int ret; | |
85 | ||
86 | caps = cap_get_proc(); | |
87 | if (!caps) { | |
88 | ERROR("failed to cap_get_proc: %m"); | |
89 | return -1; | |
90 | } | |
91 | ||
92 | for (cap = 0; cap <= CAP_LAST_CAP; cap++) { | |
93 | ||
94 | cap_flag_value_t flag; | |
95 | ||
96 | ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag); | |
97 | if (ret) { | |
98 | ERROR("failed to cap_get_flag: %m"); | |
99 | goto out; | |
100 | } | |
101 | ||
102 | ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag); | |
103 | if (ret) { | |
104 | ERROR("failed to cap_set_flag: %m"); | |
105 | goto out; | |
106 | } | |
107 | } | |
108 | ||
109 | ret = cap_set_proc(caps); | |
110 | if (ret) { | |
111 | ERROR("failed to cap_set_proc: %m"); | |
112 | goto out; | |
113 | } | |
114 | ||
115 | out: | |
116 | cap_free(caps); | |
117 | return 0; | |
118 | } | |
119 | ||
120 | int lxc_caps_init(void) | |
121 | { | |
122 | uid_t uid = getuid(); | |
123 | gid_t gid = getgid(); | |
124 | uid_t euid = geteuid(); | |
125 | ||
126 | if (!uid) { | |
127 | INFO("command is run as 'root'"); | |
128 | return 0; | |
129 | } | |
130 | ||
131 | if (uid && !euid) { | |
132 | INFO("command is run as setuid root (uid : %d)", uid); | |
133 | ||
134 | if (prctl(PR_SET_KEEPCAPS, 1)) { | |
135 | ERROR("failed to 'PR_SET_KEEPCAPS': %m"); | |
136 | return -1; | |
137 | } | |
138 | ||
139 | if (setresgid(gid, gid, gid)) { | |
140 | ERROR("failed to change gid to '%d': %m", gid); | |
141 | return -1; | |
142 | } | |
143 | ||
144 | if (setresuid(uid, uid, uid)) { | |
145 | ERROR("failed to change uid to '%d': %m", uid); | |
146 | return -1; | |
147 | } | |
148 | ||
149 | if (lxc_caps_up()) { | |
150 | ERROR("failed to restore capabilities: %m"); | |
151 | return -1; | |
152 | } | |
153 | } | |
154 | ||
155 | if (uid == euid) | |
156 | INFO("command is run as user '%d'", uid); | |
157 | ||
158 | return 0; | |
159 | } |