Skip to content
This repository was archived by the owner on Jan 9, 2020. It is now read-only.

Commit 52fa4c8

Browse files
authored
Merge pull request #22 from vishvananda/caps
Fixes for docker 17.06
2 parents fc17a96 + 1fb2475 commit 52fa4c8

File tree

6 files changed

+354
-102
lines changed

6 files changed

+354
-102
lines changed

oci/src/lib.rs

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ pub enum LinuxCapabilityType {
123123
CAP_AUDIT_READ,
124124
}
125125

126+
#[derive(Serialize, Deserialize, Debug)]
127+
pub struct LinuxCapabilities {
128+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
129+
pub bounding: Vec<LinuxCapabilityType>,
130+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
131+
pub effective: Vec<LinuxCapabilityType>,
132+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
133+
pub inheritable: Vec<LinuxCapabilityType>,
134+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
135+
pub permitted: Vec<LinuxCapabilityType>,
136+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
137+
pub ambient: Vec<LinuxCapabilityType>,
138+
}
139+
126140
#[derive(Serialize, Deserialize, Debug)]
127141
pub struct Process {
128142
#[serde(default, skip_serializing_if = "is_false")]
@@ -136,8 +150,9 @@ pub struct Process {
136150
pub env: Vec<String>,
137151
#[serde(default, skip_serializing_if = "String::is_empty")]
138152
pub cwd: String,
139-
#[serde(default, skip_serializing_if = "Vec::is_empty")]
140-
pub capabilities: Vec<LinuxCapabilityType>,
153+
#[serde(default, deserialize_with = "deserialize_capabilities",
154+
skip_serializing_if = "Option::is_none")]
155+
pub capabilities: Option<LinuxCapabilities>,
141156
#[serde(default, skip_serializing_if = "Vec::is_empty")]
142157
pub rlimits: Vec<LinuxRlimit>,
143158
#[serde(default, skip_serializing_if = "is_false",
@@ -151,6 +166,84 @@ pub struct Process {
151166
pub selinux_label: String,
152167
}
153168

169+
use serde::Deserialize;
170+
171+
fn cap_from_array<D>(
172+
a: &[serde_json::Value],
173+
) -> Result<Vec<LinuxCapabilityType>, D::Error>
174+
where
175+
D: serde::Deserializer,
176+
{
177+
let mut caps = Vec::new();
178+
for c in a {
179+
match LinuxCapabilityType::deserialize(c) {
180+
Ok(val) => caps.push(val),
181+
Err(_) => {
182+
let msg = format!("Capability '{}' is not valid", c);
183+
return Err(serde::de::Error::custom(msg));
184+
}
185+
}
186+
}
187+
Ok(caps)
188+
}
189+
190+
fn cap_from_object<D>(
191+
o: &serde_json::Map<String, serde_json::Value>,
192+
key: &str,
193+
) -> Result<Vec<LinuxCapabilityType>, D::Error>
194+
where
195+
D: serde::Deserializer,
196+
{
197+
if let Some(v) = o.get(key) {
198+
match *v {
199+
serde_json::Value::Null => Ok(Vec::new()),
200+
serde_json::Value::Array(ref a) => cap_from_array::<D>(a),
201+
_ => Err(serde::de::Error::custom(
202+
"Unexpected value in capability set",
203+
)),
204+
}
205+
} else {
206+
Ok(Vec::new())
207+
}
208+
}
209+
210+
// handle the old case where caps was just a list of caps
211+
fn deserialize_capabilities<D>(
212+
de: D,
213+
) -> Result<Option<LinuxCapabilities>, D::Error>
214+
where
215+
D: serde::Deserializer,
216+
{
217+
let r: serde_json::Value = serde::Deserialize::deserialize(de)?;
218+
match r {
219+
serde_json::Value::Null => Ok(None),
220+
serde_json::Value::Array(a) => {
221+
let caps = cap_from_array::<D>(&a)?;
222+
let capabilities = LinuxCapabilities {
223+
bounding: caps.clone(),
224+
effective: caps.clone(),
225+
inheritable: caps.clone(),
226+
permitted: caps.clone(),
227+
ambient: caps.clone(),
228+
};
229+
230+
Ok(Some(capabilities))
231+
}
232+
serde_json::Value::Object(o) => {
233+
let capabilities = LinuxCapabilities{
234+
bounding: cap_from_object::<D>(&o, "bounding")?,
235+
effective: cap_from_object::<D>(&o, "effective")?,
236+
inheritable: cap_from_object::<D>(&o, "inheritable")?,
237+
permitted: cap_from_object::<D>(&o, "permitted")?,
238+
ambient: cap_from_object::<D>(&o, "ambient")?,
239+
};
240+
241+
Ok(Some(capabilities))
242+
}
243+
_ => Err(serde::de::Error::custom("Unexpected value in capabilites")),
244+
}
245+
}
246+
154247
#[derive(Serialize, Deserialize, Debug)]
155248
pub struct Root {
156249
#[serde(default)]
@@ -467,8 +560,11 @@ pub struct LinuxSeccompArg {
467560

468561
#[derive(Serialize, Deserialize, Debug)]
469562
pub struct LinuxSyscall {
563+
// old version used name
470564
#[serde(default, skip_serializing_if = "String::is_empty")]
471565
pub name: String,
566+
#[serde(default, skip_serializing_if = "Vec::is_empty")]
567+
pub names: Vec<String>,
472568
pub action: LinuxSeccompAction,
473569
#[serde(default, skip_serializing_if = "Vec::is_empty")]
474570
pub args: Vec<LinuxSeccompArg>,

src/capabilities.rs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use caps::*;
2-
use oci::LinuxCapabilityType;
2+
use oci::{LinuxCapabilities, LinuxCapabilityType};
33

44
fn to_cap(cap: LinuxCapabilityType) -> Capability {
55
unsafe { ::std::mem::transmute(cap) }
66
}
77

8-
const ALL_CAP_SETS: &'static [CapSet] = &[
9-
CapSet::Effective,
10-
CapSet::Permitted,
11-
CapSet::Inheritable,
12-
CapSet::Ambient,
13-
];
8+
fn to_set(caps: &[LinuxCapabilityType]) -> CapsHashSet {
9+
let mut capabilities = CapsHashSet::new();
10+
for c in caps {
11+
capabilities.insert(to_cap(*c));
12+
}
13+
capabilities
14+
}
1415

1516
pub fn reset_effective() -> ::Result<()> {
1617
let mut all = CapsHashSet::new();
@@ -21,22 +22,20 @@ pub fn reset_effective() -> ::Result<()> {
2122
Ok(())
2223
}
2324

24-
pub fn drop_privileges(cs: &[LinuxCapabilityType]) -> ::Result<()> {
25+
pub fn drop_privileges(cs: &LinuxCapabilities) -> ::Result<()> {
2526
let mut all = CapsHashSet::new();
2627
for c in Capability::iter_variants() {
2728
all.insert(c);
2829
}
29-
let mut capabilities = CapsHashSet::new();
30-
for c in cs {
31-
capabilities.insert(to_cap(*c));
32-
}
30+
debug!("dropping bounding capabilities to {:?}", cs.bounding);
3331
// drop excluded caps from the bounding set
34-
for c in all.difference(&capabilities) {
32+
for c in all.difference(&to_set(&cs.bounding)) {
3533
drop(None, CapSet::Bounding, *c)?;
3634
}
37-
// set all sets for current process
38-
for capset in ALL_CAP_SETS {
39-
set(None, *capset, capabilities.clone())?;
40-
}
35+
// set other sets for current process
36+
set(None, CapSet::Effective, to_set(&cs.effective))?;
37+
set(None, CapSet::Permitted, to_set(&cs.permitted))?;
38+
set(None, CapSet::Inheritable, to_set(&cs.inheritable))?;
39+
set(None, CapSet::Ambient, to_set(&cs.ambient))?;
4140
Ok(())
4241
}

src/cgroups.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub fn init() {
1212
// initialize lazy_static maps
1313
initialize(&PATHS);
1414
initialize(&MOUNTS);
15+
initialize(&DEFAULT_ALLOWED_DEVICES);
1516
initialize(&APPLIES);
1617
}
1718

@@ -242,6 +243,59 @@ lazy_static! {
242243
};
243244
}
244245

246+
lazy_static! {
247+
static ref DEFAULT_ALLOWED_DEVICES: Vec<LinuxDeviceCgroup> = {
248+
let mut v = Vec::new();
249+
// mknod any device
250+
v.push(LinuxDeviceCgroup{
251+
allow: true,
252+
typ: LinuxDeviceType::c,
253+
major: None,
254+
minor: None,
255+
access: "m".to_string(),
256+
});
257+
v.push(LinuxDeviceCgroup{
258+
allow: true,
259+
typ: LinuxDeviceType::b,
260+
major: None,
261+
minor: None,
262+
access: "m".to_string(),
263+
});
264+
// /dev/console
265+
v.push(LinuxDeviceCgroup{
266+
allow: true,
267+
typ: LinuxDeviceType::c,
268+
major: Some(5),
269+
minor: Some(1),
270+
access: "rwm".to_string(),
271+
});
272+
// /dev/pts
273+
v.push(LinuxDeviceCgroup{
274+
allow: true,
275+
typ: LinuxDeviceType::c,
276+
major: Some(136),
277+
minor: None,
278+
access: "rwm".to_string(),
279+
});
280+
v.push(LinuxDeviceCgroup{
281+
allow: true,
282+
typ: LinuxDeviceType::c,
283+
major: Some(5),
284+
minor: Some(2),
285+
access: "rwm".to_string(),
286+
});
287+
// tun/tap
288+
v.push(LinuxDeviceCgroup{
289+
allow: true,
290+
typ: LinuxDeviceType::c,
291+
major: Some(10),
292+
minor: Some(200),
293+
access: "rwm".to_string(),
294+
});
295+
v
296+
};
297+
}
298+
245299
type Apply = fn(&LinuxResources, &str) -> Result<()>;
246300

247301
lazy_static! {
@@ -468,5 +522,9 @@ fn devices_apply(r: &LinuxResources, dir: &str) -> Result<()> {
468522

469523
write_device(&ld, dir)?;
470524
}
525+
for ld in DEFAULT_ALLOWED_DEVICES.iter() {
526+
write_device(ld, dir)?;
527+
}
528+
471529
Ok(())
472530
}

0 commit comments

Comments
 (0)