Skip to content

Commit

Permalink
src/*: implement features
Browse files Browse the repository at this point in the history
Fixes: #1177
Signed-off-by: Sohan Kunkerkar <sohank2602@gmail.com>
  • Loading branch information
sohankunkerkar committed Jun 20, 2023
1 parent 7da99fb commit 33cb00b
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ dist-luarock: $(LUACRUN_ROCK)
endif

crun_CFLAGS = -I $(abs_top_builddir)/libocispec/src -I $(abs_top_srcdir)/libocispec/src -D CRUN_LIBDIR="\"$(CRUN_LIBDIR)\""
crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/spec.c \
crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/features.c src/spec.c \
src/exec.c src/list.c src/create.c src/start.c src/state.c src/update.c src/ps.c \
src/checkpoint.c src/restore.c src/libcrun/cloned_binary.c

Expand All @@ -143,7 +143,7 @@ endif

EXTRA_DIST = COPYING COPYING.libcrun README.md NEWS SECURITY.md rpm/crun.spec.in autogen.sh \
src/crun.h src/list.h src/run.h src/delete.h src/kill.h src/pause.h src/unpause.h \
src/create.h src/start.h src/state.h src/exec.h src/spec.h src/update.h src/ps.h \
src/create.h src/start.h src/state.h src/exec.h src/features.h src/spec.h src/update.h src/ps.h \
src/checkpoint.h src/restore.h src/libcrun/seccomp_notify.h src/libcrun/seccomp_notify_plugin.h \
src/libcrun/container.h src/libcrun/seccomp.h src/libcrun/ebpf.h \
src/libcrun/cgroup.h src/libcrun/cgroup-cgroupfs.h \
Expand Down
4 changes: 4 additions & 0 deletions src/crun.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "spec.h"
#include "pause.h"
#include "unpause.h"
#include "features.h"
#include "ps.h"
#include "checkpoint.h"
#include "restore.h"
Expand Down Expand Up @@ -137,6 +138,7 @@ enum
COMMAND_UPDATE,
COMMAND_PAUSE,
COMMAND_UNPAUSE,
COMMAND_FEATURES,
COMMAND_PS,
COMMAND_CHECKPOINT,
COMMAND_RESTORE,
Expand All @@ -155,6 +157,7 @@ struct commands_s commands[] = { { COMMAND_CREATE, "create", crun_command_create
{ COMMAND_UPDATE, "update", crun_command_update },
{ COMMAND_PAUSE, "pause", crun_command_pause },
{ COMMAND_UNPAUSE, "resume", crun_command_unpause },
{ COMMAND_FEATURES, "features", crun_command_features },
#if HAVE_CRIU && HAVE_DLOPEN
{ COMMAND_CHECKPOINT, "checkpoint", crun_command_checkpoint },
{ COMMAND_RESTORE, "restore", crun_command_restore },
Expand All @@ -170,6 +173,7 @@ static char doc[] = "\nCOMMANDS:\n"
"\tcreate - create a container\n"
"\tdelete - remove definition for a container\n"
"\texec - exec a command in a running container\n"
"\tfeatures - show the enabled features\n"
"\tlist - list known containers\n"
"\tkill - send a signal to the container init process\n"
"\tps - show the processes in the container\n"
Expand Down
171 changes: 171 additions & 0 deletions src/features.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* crun - OCI runtime written in C
*
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* crun 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with crun. If not, see <http://www.gnu.org/licenses/>.
*/

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <argp.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <yajl/yajl_tree.h>
#include <yajl/yajl_gen.h>

#include "crun.h"
#include "libcrun/container.h"
#include "libcrun/utils.h"

static char doc[] = "OCI runtime";

static struct argp_option options[] = { {0} };

static char args_doc[] = "features";

static error_t
parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused)
{
if (key != ARGP_KEY_NO_ARGS) {
return ARGP_ERR_UNKNOWN;
}

return 0;
}

static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL };

void
addStringToJSON(yajl_gen jsonGen, const char *key, const char *value) {
yajl_gen_string(jsonGen, (const unsigned char *) key, strlen(key));
yajl_gen_string(jsonGen, (const unsigned char *) value, strlen(value));
}

void
addBoolToJSON(yajl_gen jsonGen, const char *key, int value) {
yajl_gen_string(jsonGen, (const unsigned char *) key, strlen(key));
yajl_gen_bool(jsonGen, value);
}

void
addArrayToJSON(yajl_gen jsonGen, const char *key, const char **array) {
yajl_gen_string(jsonGen, (const unsigned char *) key, strlen(key));
yajl_gen_array_open(jsonGen);

for (size_t i = 0; array[i] != NULL; i++) {
yajl_gen_string(jsonGen, (const unsigned char *) array[i], strlen(array[i]));
}

yajl_gen_array_close(jsonGen);
}

int
crun_command_features(struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) {
argp_parse(&run_argp, argc, argv, 0, 0, &options);

// Call the function in features.c to gather the feature information
struct features_info_s info;
int result = libcrun_container_print_features(&info);
if (result != 0) {
libcrun_make_error(err, result, "Failed to gather features information.");
return result;
}

// Prepare the JSON output
yajl_gen jsonGen = yajl_gen_alloc(NULL);
yajl_gen_status status;

yajl_gen_config(jsonGen, yajl_gen_beautify, 1); // Optional: Enable pretty formatting

// Start building the JSON
yajl_gen_map_open(jsonGen);

// Add ociVersionMin field
yajl_gen_string(jsonGen, (const unsigned char *) "ociVersionMin", strlen("ociVersionMin"));
yajl_gen_string(jsonGen, (const unsigned char *) info.ociVersionMin, strlen(info.ociVersionMin));

// Add ociVersionMax field
yajl_gen_string(jsonGen, (const unsigned char *) "ociVersionMax", strlen("ociVersionMax"));
yajl_gen_string(jsonGen, (const unsigned char *) info.ociVersionMax, strlen(info.ociVersionMax));

// Add hooks array
addArrayToJSON(jsonGen, "hooks", info.hooks);
// Add mountOptions array
addArrayToJSON(jsonGen, "mountOptions", info.mountOptions);

yajl_gen_string(jsonGen, (const unsigned char *) "linux", strlen("linux"));
yajl_gen_map_open(jsonGen);

// Add namespaces array
addArrayToJSON(jsonGen, "namespaces", info.linux.namespaces);
// Add capabilities array
addArrayToJSON(jsonGen, "capabilities", info.linux.capabilities);

// Generate the "cgroup" field
yajl_gen_string(jsonGen, (const unsigned char *) "cgroup", strlen("cgroup"));
yajl_gen_map_open(jsonGen);

addBoolToJSON(jsonGen, "v1", info.linux.cgroup.v1);
addBoolToJSON(jsonGen, "v2", info.linux.cgroup.v2);
addBoolToJSON(jsonGen, "systemd", info.linux.cgroup.systemd);
addBoolToJSON(jsonGen, "systemdUser", info.linux.cgroup.systemdUser);

// Close the map for cgroup
yajl_gen_map_close(jsonGen);

// Add seccomp field with TODO comment
yajl_gen_string(jsonGen, (const unsigned char *) "seccomp", strlen("seccomp"));
yajl_gen_map_open(jsonGen);

yajl_gen_string(jsonGen, (const unsigned char *) "/* TODO: */", strlen("/* TODO: */"));

// Close the map for seccomp
yajl_gen_map_close(jsonGen);

// Generate "apparmor" field
yajl_gen_string(jsonGen, (const unsigned char *) "apparmor", strlen("apparmor"));
yajl_gen_map_open(jsonGen);

addBoolToJSON(jsonGen, "enabled", info.linux.apparmor.enabled);

// Close the map for apparmor
yajl_gen_map_close(jsonGen);

// Generate "selinux" field
yajl_gen_string(jsonGen, (const unsigned char *) "selinux", strlen("selinux"));
yajl_gen_map_open(jsonGen);

addBoolToJSON(jsonGen, "enabled", info.linux.selinux.enabled);

// Close the map for selinux
yajl_gen_map_close(jsonGen);

// Close the map for linux
yajl_gen_map_close(jsonGen);

// End building the JSON
yajl_gen_map_close(jsonGen);

const unsigned char *jsonString;
size_t jsonLength;
yajl_gen_get_buf(jsonGen, &jsonString, &jsonLength);

printf("%s", (const char *) jsonString);

yajl_gen_free(jsonGen);

return 0;
}
25 changes: 25 additions & 0 deletions src/features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* crun - OCI runtime written in C
*
* Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano <giuseppe@scrivano.org>
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* crun 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with crun. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FEATURES_H
#define FEATURES_H

#include "crun.h"

int crun_command_features (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error);

#endif
126 changes: 126 additions & 0 deletions src/libcrun/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <string.h>
#include <fcntl.h>
#include "status.h"
#include "mount_flags.h"
#include "linux.h"
#include "terminal.h"
#include "io_priority.h"
Expand Down Expand Up @@ -3706,6 +3707,131 @@ libcrun_container_update_from_values (libcrun_context_t *context, const char *id
return ret;
}

void populate_array_field(const char*** field, const char* array[], size_t numElements){
*field = malloc(numElements * sizeof(char *));
size_t i;
for (i = 0; i < numElements; i++) {
(*field)[i] = strdup(array[i]);
}

(*field)[i] = NULL; // Terminate the array with NULL
}

int libcrun_container_print_features(struct features_info_s *info)
{
// Hardcoded feature information
info->ociVersionMin = "1.0.0";
info->ociVersionMax = "1.0.2-dev";

// Hardcoded hooks
const char *hooks[] = {
"prestart",
"createRuntime",
"createContainer",
"startContainer",
"poststart",
"poststop"
};

// Hardcode the values for namespaces
static const char *namespaces[] = {
"cgroup",
"ipc",
"mount",
"network",
"pid",
"user",
"uts"
};

// Hardcode the values for capabilities
static const char *capabilities[] = {
"CAP_CHOWN",
"CAP_DAC_OVERRIDE",
"CAP_DAC_READ_SEARCH",
"CAP_FOWNER",
"CAP_FSETID",
"CAP_KILL",
"CAP_SETGID",
"CAP_SETUID",
"CAP_SETPCAP",
"CAP_LINUX_IMMUTABLE",
"CAP_NET_BIND_SERVICE",
"CAP_NET_BROADCAST",
"CAP_NET_ADMIN",
"CAP_NET_RAW",
"CAP_IPC_LOCK",
"CAP_IPC_OWNER",
"CAP_SYS_MODULE",
"CAP_SYS_RAWIO",
"CAP_SYS_CHROOT",
"CAP_SYS_PTRACE",
"CAP_SYS_PACCT",
"CAP_SYS_ADMIN",
"CAP_SYS_BOOT",
"CAP_SYS_NICE",
"CAP_SYS_RESOURCE",
"CAP_SYS_TIME",
"CAP_SYS_TTY_CONFIG",
"CAP_MKNOD",
"CAP_LEASE",
"CAP_AUDIT_WRITE",
"CAP_AUDIT_CONTROL",
"CAP_SETFCAP",
"CAP_MAC_OVERRIDE",
"CAP_MAC_ADMIN",
"CAP_SYSLOG",
"CAP_WAKE_ALARM",
"CAP_BLOCK_SUSPEND",
"CAP_AUDIT_READ",
"CAP_PERFMON",
"CAP_BPF",
"CAP_CHECKPOINT_RESTORE"
};

// Populate hooks
size_t numHooks = sizeof(hooks) / sizeof(hooks[0]);
populate_array_field(&(info->hooks), hooks, numHooks);

// Retrieve mount options from wordlist
size_t numMountOptions;
const struct propagation_flags_s* mountOptionsList = get_mount_flags_from_wordlist();

// Calculate the number of mount options
size_t count = 0;
while (mountOptionsList[count].name != NULL) {
count++;
}

// Allocate memory for mount options in info struct
info->mountOptions = malloc(count * sizeof(char *));

// Copy mount options to info struct
for (size_t i = 0; i < count; i++) {
info->mountOptions[i] = strdup(mountOptionsList[i].name);
}

// Populate namespaces
size_t numNamspaces = sizeof(namespaces) / sizeof(namespaces[0]);
populate_array_field(&(info->linux.namespaces), namespaces, numNamspaces);

// Populate capabilities
size_t numCapabilities = sizeof(capabilities) / sizeof(capabilities[0]);
populate_array_field(&(info->linux.capabilities), capabilities, numCapabilities);

// Hardcode the values for cgroup
info->linux.cgroup.v1= true;
info->linux.cgroup.v2 = true;
info->linux.cgroup.systemd = true;
info->linux.cgroup.systemdUser = true;

// Put values for apparmor and selinux
info->linux.apparmor.enabled = true;
info->linux.selinux.enabled = true;

return 0;
}

int
libcrun_container_spec (bool root, FILE *out, libcrun_error_t *err arg_unused)
{
Expand Down
Loading

0 comments on commit 33cb00b

Please sign in to comment.