[lxc-devel] [patch 1/5] Add capability interface

Andrian Nord nightnord at gmail.com
Tue Nov 17 22:35:21 UTC 2009


This adds capabilities.c and capabilities.h files.

Interface consists of three functions:

* initialising function - lxc_capabilities_init:
	this function runs though hardoded capability name-to-index
	mapping array, checking 'initial_state' field, and builds
	initial mask according to this array.

	Having defaults is a most untrivial question - current default
	let container to boot normally and operate properly enough in
	most of cases, but restricts all dangerous operations like
	module inserting and time changing. But probably this should be
	left on system admin's decision (it will also reduce startup
	overhead)

* modification functions - lxc_capabilities_change:
	this function rather simple. Usage of bit-mask field instead of
	say lxc_list is because lxc_list will consume more memory, while
	there is not way of removing static array and looking up through
	it - we still need mapping from name to mask, so it will also
	slower due to additional overhead on comparsions in list (even
	if only dropped values whould be kept).

* apply function - lxc_capabilities_apply:
	this is most problematic function - as I've failed to found a
	way of using libcap (I dunno why it's not working, I'll have
	more time to investigate some time later) or raw syscalls, here
	I'm checking if capability is dropped and then dropping it with
	prctl. Usage of direct mask setting would be, of course,
	preffered

Signed-off-by: Andrian Nord <NightNord at gmail.com>

diff --git a/src/lxc/capability.c b/src/lxc/capability.c
new file mode 100644
index 0000000..b5fa924
--- /dev/null
+++ b/src/lxc/capability.c
@@ -0,0 +1,167 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * File by:
+ * Andrian Nord <nightnord at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#undef _GNU_SOURCE
+#include <errno.h>
+#include <linux/types.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+
+#include "capability.h"
+
+#include <lxc/log.h>
+
+#if !HAVE_DECL_PR_CAPBSET_DROP
+#define PR_CAPBSET_DROP 24
+#endif
+
+lxc_log_define(lxc_capability, lxc);
+
+struct capability {
+	char		*name;
+	__u32		code;
+	lxc_cap_state	initial_state;
+};
+
+static struct capability capabilities[] = {
+	{ "chown",		CAP_CHOWN,		LXC_CAP_KEEP	},
+
+	{ "dac_override",	CAP_DAC_OVERRIDE,	LXC_CAP_KEEP	},
+	{ "dac_read_search",	CAP_DAC_READ_SEARCH,	LXC_CAP_KEEP	},
+
+	{ "fowner",		CAP_FOWNER,		LXC_CAP_KEEP	},
+	{ "fsetid",		CAP_FSETID,		LXC_CAP_KEEP	},
+
+	{ "kill",		CAP_KILL,		LXC_CAP_KEEP	},
+
+	{ "setgid",		CAP_SETGID,		LXC_CAP_KEEP	},
+	{ "setuid",		CAP_SETUID,		LXC_CAP_KEEP	},
+
+	{ "setpcap",		CAP_SETPCAP,		LXC_CAP_KEEP	},
+	{ "linux_immutable",	CAP_LINUX_IMMUTABLE,	LXC_CAP_KEEP	},
+
+	{ "net_bind_service",	CAP_NET_BIND_SERVICE,	LXC_CAP_KEEP	},
+	{ "net_broadcast",	CAP_NET_BROADCAST,	LXC_CAP_KEEP	},
+	{ "net_admin",		CAP_NET_ADMIN,		LXC_CAP_KEEP	},
+	{ "net_raw",		CAP_NET_RAW,		LXC_CAP_KEEP	},
+
+	{ "ipc_lock",		CAP_IPC_LOCK,		LXC_CAP_KEEP	},
+	{ "ipc_owner",		CAP_IPC_OWNER,		LXC_CAP_KEEP	},
+
+	{ "sys_module",		CAP_SYS_MODULE,		LXC_CAP_DROP	},
+
+	{ "sys_rawio",		CAP_SYS_RAWIO,		LXC_CAP_DROP	},
+
+	{ "sys_chroot",		CAP_SYS_CHROOT,		LXC_CAP_KEEP	},
+
+	{ "sys_ptrace",		CAP_SYS_PTRACE,		LXC_CAP_KEEP	},
+	{ "sys_pacct",		CAP_SYS_PACCT,		LXC_CAP_DROP	},
+
+	{ "sys_admin",		CAP_SYS_ADMIN,		LXC_CAP_KEEP	},
+	{ "sys_boot",		CAP_SYS_BOOT,		LXC_CAP_DROP	},
+	{ "sys_nice",		CAP_SYS_NICE,		LXC_CAP_KEEP	},
+	{ "sys_resource",	CAP_SYS_RESOURCE,	LXC_CAP_KEEP	},
+	{ "sys_time",		CAP_SYS_TIME,		LXC_CAP_DROP	},
+
+	{ "sys_tty_config",	CAP_SYS_TTY_CONFIG,	LXC_CAP_KEEP	},
+	{ "mknod",		CAP_MKNOD,		LXC_CAP_KEEP	},
+	{ "lease",		CAP_LEASE,		LXC_CAP_KEEP	},
+
+	{ "audit_write",	CAP_AUDIT_WRITE,	LXC_CAP_DROP	},
+	{ "audit_control",	CAP_AUDIT_CONTROL,	LXC_CAP_DROP	},
+
+	{ "setfcap",		CAP_SETFCAP,		LXC_CAP_KEEP	}
+};
+
+static const size_t cap_count = sizeof(capabilities)/sizeof(struct capability);
+
+static struct capability *find_name(const char *cap_name)
+{
+	int i;
+
+	for (i = 0; i < cap_count; i++) {
+		if (!strncmp(capabilities[i].name, cap_name, strlen(cap_name)))
+			return &capabilities[i];
+	}
+
+	return NULL;
+}
+
+int lxc_capabilities_init(__u32 *mask)
+{
+	int i;
+	*mask = 0;
+
+	for (i = 0; i < cap_count; i++) {
+		if(capabilities[i].initial_state == LXC_CAP_KEEP)
+			*mask |= CAP_TO_MASK(capabilities[i].code);
+	}
+
+	return 0;
+}
+
+int lxc_capabilities_change(__u32 *mask, const char *cap_name,
+							lxc_cap_state state)
+{
+	struct capability *cap_spec;
+
+	cap_spec = find_name(cap_name);
+
+	if (!cap_spec) {
+		ERROR("capability '%s' not found", cap_name);
+		return -1;
+	}
+
+	if (state == LXC_CAP_DROP)
+		*mask &= ~CAP_TO_MASK(cap_spec->code);
+	else if (state == LXC_CAP_KEEP)
+		*mask |= CAP_TO_MASK(cap_spec->code);
+
+	return 0;
+}
+
+
+int lxc_capabilities_apply(__u32 mask)
+{
+	int i;
+	struct capability *cur_cap;
+
+	for (i = 0; i < cap_count; i++) {
+		cur_cap = &capabilities[i];
+
+		if (lxc_capabilities_check(mask, cur_cap->code))
+			continue;
+
+		DEBUG("dropping capability '%s'", cur_cap->name);
+
+	 	if (!prctl(PR_CAPBSET_DROP, cur_cap->code, 0, 0, 0))
+			continue;
+
+		SYSERROR("failed to remove '%s' capability", cur_cap->name);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/src/lxc/capability.h b/src/lxc/capability.h
new file mode 100644
index 0000000..401ad2a
--- /dev/null
+++ b/src/lxc/capability.h
@@ -0,0 +1,44 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <dlezcano at fr.ibm.com>
+ * File by:
+ * Andrian Nord <nightnord at gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _capability_h
+#define _capability_h
+
+#include <linux/types.h>
+
+#define lxc_capabilities_check(mask, code) (mask & CAP_TO_MASK(code))
+
+typedef enum {
+	LXC_CAP_DROP	= 0,
+	LXC_CAP_KEEP	= 1
+} lxc_cap_state;
+
+int lxc_capabilities_init(__u32 *mask);
+
+int lxc_capabilities_change(__u32 *mask, const char *cap_name,
+							lxc_cap_state state);
+
+int lxc_capabilities_apply(__u32 mask);
+
+#endif




More information about the lxc-devel mailing list