Преглед изворни кода

service: add method to query available container features

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Daniel Golle пре 4 година
родитељ
комит
47a9f0d652
1 измењених фајлова са 97 додато и 0 уклоњено
  1. 97 0
      service/service.c

+ 97 - 0
service/service.c

@@ -14,7 +14,12 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
 #include <unistd.h>
+#include <sched.h>
 
 #include <libubox/blobmsg_json.h>
 #include <libubox/avl-cmp.h>
@@ -297,6 +302,97 @@ static inline bool is_container_obj(struct ubus_object *obj)
 	return (obj && (strcmp(obj->name, "container") == 0));
 }
 
+static inline void put_namespace(struct blob_buf *b, char *name)
+{
+	char nsfname[32];
+	struct stat statbuf;
+
+	snprintf(nsfname, sizeof(nsfname), "/proc/self/ns/%s", name);
+
+	if (!stat(nsfname, &statbuf))
+		blobmsg_add_string(b, NULL, name);
+}
+
+static void put_cgroups(struct blob_buf *b)
+{
+	int fd, ret;
+	static char buf[512] = "";
+	char *t, *z;
+
+	fd = open("/sys/fs/cgroup/cgroup.controllers", O_RDONLY);
+	if (fd == -1)
+		return;
+
+	ret = read(fd, &buf, sizeof(buf));
+	close(fd);
+
+	if (ret < 2)
+		return;
+
+	t = buf;
+	while(t) {
+		z = t;
+		/* replace space with \0 and direct next entry */
+		t = strchr(z, ' ');
+		if (t) {
+			*(t++) = '\0';
+		} else { /* replace trailing new-line with \0 */
+			t = strchr(z, '\n');
+			if (!t) /* shouldn't happen, but don't segfault if it does */
+				break;
+
+			*t = '\0';
+			t = NULL;
+		}
+		blobmsg_add_string(b, NULL, z);
+	}
+}
+
+static int
+container_handle_features(struct ubus_context *ctx, struct ubus_object *obj,
+		    struct ubus_request_data *req, const char *method,
+		    struct blob_attr *msg)
+{
+	struct utsname utsbuf;
+	struct stat statbuf;
+	void *nsarray, *cgarray;
+
+	if (stat("/sbin/ujail", &statbuf))
+		return UBUS_STATUS_NOT_SUPPORTED;
+
+	if (uname(&utsbuf) < 0)
+		return UBUS_STATUS_UNKNOWN_ERROR;
+
+	blob_buf_init(&b, 0);
+	blobmsg_add_string(&b, "machine", utsbuf.machine);
+
+#ifdef SECCOMP_SUPPORT
+	blobmsg_add_u8(&b, "seccomp", true);
+#else
+	blobmsg_add_u8(&b, "seccomp", false);
+#endif
+
+	cgarray = blobmsg_open_array(&b, "cgroup");
+	put_cgroups(&b);
+	blobmsg_close_array(&b, cgarray);
+
+	nsarray = blobmsg_open_array(&b, "namespaces");
+	put_namespace(&b, "cgroup");
+	put_namespace(&b, "ipc");
+	put_namespace(&b, "mnt");
+	put_namespace(&b, "net");
+	put_namespace(&b, "pid");
+#ifdef CLONE_NEWTIME
+	put_namespace(&b, "time");
+#endif
+	put_namespace(&b, "user");
+	put_namespace(&b, "uts");
+	blobmsg_close_array(&b, nsarray);
+	ubus_send_reply(ctx, req, b.head);
+
+	return UBUS_STATUS_OK;
+}
+
 static int
 service_handle_set(struct ubus_context *ctx, struct ubus_object *obj,
 		   struct ubus_request_data *req, const char *method,
@@ -936,6 +1032,7 @@ static struct ubus_method container_object_methods[] = {
 	UBUS_METHOD("list", service_handle_list, service_list_attrs),
 	UBUS_METHOD("delete", service_handle_delete, service_del_attrs),
 	UBUS_METHOD("state", service_handle_state, service_state_attrs),
+	UBUS_METHOD_NOARG("get_features", container_handle_features),
 	UBUS_METHOD("console_set", container_handle_console, container_console_policy),
 	UBUS_METHOD("console_attach", container_handle_console, container_console_policy),
 };