mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-08-23 23:48:14 +00:00
@@ -610,6 +610,11 @@ static int hyper_container_init(void *data)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hyper_setup_exec_user(&container->exec) < 0) {
|
||||
fprintf(stderr, "setup exec user failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (container_setup_tty(arg->pipe[1], container) < 0) {
|
||||
|
||||
+97
@@ -14,6 +14,8 @@
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "hyper.h"
|
||||
#include "util.h"
|
||||
@@ -185,6 +187,96 @@ struct hyper_event_ops err_ops = {
|
||||
/* don't need write buff, the stderr data is one way */
|
||||
};
|
||||
|
||||
int hyper_setup_exec_user(struct hyper_exec *exec)
|
||||
{
|
||||
char *user = exec->user == NULL || strlen(exec->user) == 0 ? NULL : exec->user;
|
||||
char *group = exec->group == NULL || strlen(exec->group) == 0 ? NULL : exec->group;
|
||||
|
||||
// check the config
|
||||
if (!user) {
|
||||
if (group || exec->nr_additional_groups > 0) {
|
||||
fprintf(stderr, "group or additional groups can only be set when user is set\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get uid
|
||||
fprintf(stdout, "try to find the user: %s\n", user);
|
||||
struct passwd *pwd = hyper_getpwnam(user);
|
||||
if (pwd == NULL) {
|
||||
perror("can't find the user");
|
||||
return -1;
|
||||
}
|
||||
uid_t uid = pwd->pw_uid;
|
||||
|
||||
// get gid
|
||||
gid_t gid = pwd->pw_gid;
|
||||
if (group) {
|
||||
fprintf(stdout, "try to find the group: %s\n", group);
|
||||
struct group *gr = hyper_getgrnam(group);
|
||||
if (gr == NULL) {
|
||||
perror("can't find the group");
|
||||
return -1;
|
||||
}
|
||||
gid = gr->gr_gid;
|
||||
}
|
||||
|
||||
// get all gids
|
||||
int i, ngroups = 10;
|
||||
gid_t *reallocgroups, *groups = malloc(sizeof(gid_t) * ngroups);
|
||||
if (groups == NULL)
|
||||
goto fail;
|
||||
if (hyper_getgrouplist(pwd->pw_name, gid, groups, &ngroups) < 0) {
|
||||
reallocgroups = realloc(groups, sizeof(gid_t) * ngroups);
|
||||
if (reallocgroups == NULL)
|
||||
goto fail;
|
||||
groups = reallocgroups;
|
||||
if (hyper_getgrouplist(pwd->pw_name, gid, groups, &ngroups) < 0)
|
||||
goto fail;
|
||||
}
|
||||
reallocgroups = realloc(groups, sizeof(gid_t) * (ngroups + exec->nr_additional_groups));
|
||||
if (reallocgroups == NULL)
|
||||
goto fail;
|
||||
groups = reallocgroups;
|
||||
for (i = 0; i < exec->nr_additional_groups; i++) {
|
||||
fprintf(stdout, "try to find the group: %s\n", exec->additional_groups[i]);
|
||||
struct group *gr = hyper_getgrnam(exec->additional_groups[i]);
|
||||
if (gr == NULL) {
|
||||
perror("can't find the group");
|
||||
goto fail;
|
||||
}
|
||||
groups[ngroups] = gr->gr_gid;
|
||||
ngroups++;
|
||||
}
|
||||
|
||||
// setup the owner of tty
|
||||
if (exec->tty) {
|
||||
char ptmx[512];
|
||||
sprintf(ptmx, "/dev/pts/%d", exec->ptyno);
|
||||
chown(ptmx, uid, gid);
|
||||
}
|
||||
|
||||
// apply
|
||||
if (setgroups(ngroups, groups) < 0) {
|
||||
perror("setgroups() fails");
|
||||
goto fail;
|
||||
}
|
||||
if (setgid(gid) < 0) {
|
||||
perror("setgid() fails");
|
||||
goto fail;
|
||||
}
|
||||
if (setuid(uid) < 0) {
|
||||
perror("setuid() fails");
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
free(groups);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int hyper_setup_exec_notty(struct hyper_exec *e)
|
||||
{
|
||||
if (e->errseq == 0)
|
||||
@@ -502,6 +594,11 @@ static int hyper_do_exec_cmd(void *data)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hyper_setup_exec_user(exec) < 0) {
|
||||
fprintf(stderr, "setup exec user failed\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hyper_dup_exec_tty(pipe[1], exec) < 0) {
|
||||
fprintf(stderr, "dup pts to exec stdio failed\n");
|
||||
goto exit;
|
||||
|
||||
@@ -28,6 +28,10 @@ struct hyper_exec {
|
||||
|
||||
// configs
|
||||
char *id;
|
||||
char *user;
|
||||
char *group;
|
||||
char **additional_groups;
|
||||
int nr_additional_groups;
|
||||
struct env *envs;
|
||||
int envs_num;
|
||||
char **argv;
|
||||
@@ -47,6 +51,7 @@ int hyper_setup_exec_tty(struct hyper_exec *e);
|
||||
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
|
||||
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
||||
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
||||
int hyper_setup_exec_user(struct hyper_exec *e);
|
||||
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
|
||||
int hyper_watch_exec_pty(struct hyper_exec *exec, struct hyper_pod *pod);
|
||||
void hyper_cleanup_exec(struct hyper_pod *pod);
|
||||
|
||||
+49
-1
@@ -130,6 +130,31 @@ int json_token_streq(char *js, jsmntok_t *t, char *s)
|
||||
strlen(s) == (size_t)(t->end - t->start));
|
||||
}
|
||||
|
||||
static int container_parse_additional_groups(struct hyper_exec *exec, char *json, jsmntok_t *toks)
|
||||
{
|
||||
int i = 0, j;
|
||||
|
||||
if (toks[i].type != JSMN_ARRAY) {
|
||||
fprintf(stdout, "additional groups need array");
|
||||
return -1;
|
||||
}
|
||||
|
||||
exec->nr_additional_groups = toks[i].size;
|
||||
exec->additional_groups = calloc(exec->nr_additional_groups, sizeof(*exec->additional_groups));
|
||||
if (exec->additional_groups == NULL) {
|
||||
fprintf(stderr, "allocate memory for additional groups failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i++;
|
||||
for (j = 0; j < exec->nr_additional_groups; j++, i++) {
|
||||
exec->additional_groups[j] = (json_token_str(json, &toks[i]));
|
||||
fprintf(stdout, "container process additional group %d %s\n", j, exec->additional_groups[j]);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int container_parse_argv(struct hyper_exec *exec, char *json, jsmntok_t *toks)
|
||||
{
|
||||
int i = 0, j;
|
||||
@@ -164,6 +189,16 @@ static void container_cleanup_exec(struct hyper_exec *exec)
|
||||
free(exec->id);
|
||||
exec->id = NULL;
|
||||
|
||||
free(exec->user);
|
||||
exec->user = NULL;
|
||||
free(exec->group);
|
||||
exec->group = NULL;
|
||||
for (i = 0; i < exec->nr_additional_groups; i++) {
|
||||
free(exec->additional_groups[i]);
|
||||
}
|
||||
free(exec->additional_groups);
|
||||
exec->additional_groups = NULL;
|
||||
|
||||
free(exec->workdir);
|
||||
exec->workdir = NULL;
|
||||
|
||||
@@ -440,7 +475,20 @@ static int hyper_parse_process(struct hyper_exec *exec, char *json, jsmntok_t *t
|
||||
for (j = 0; j < toks_size; j++) {
|
||||
t = &toks[i];
|
||||
fprintf(stdout, "%d name %s\n", i, json_token_str(json, t));
|
||||
if (json_token_streq(json, t, "terminal") && t->size == 1) {
|
||||
if (json_token_streq(json, t, "user") && t->size == 1) {
|
||||
exec->user = (json_token_str(json, &toks[++i]));
|
||||
fprintf(stdout, "container process user %s\n", exec->user);
|
||||
i++;
|
||||
} else if (json_token_streq(json, t, "group") && t->size == 1) {
|
||||
exec->group = (json_token_str(json, &toks[++i]));
|
||||
fprintf(stdout, "container process group %s\n", exec->group);
|
||||
i++;
|
||||
} else if (json_token_streq(json, t, "additionalGroups") && t->size == 1) {
|
||||
next = container_parse_additional_groups(exec, json, &toks[++i]);
|
||||
if (next < 0)
|
||||
return -1;
|
||||
i += next;
|
||||
} else if (json_token_streq(json, t, "terminal") && t->size == 1) {
|
||||
if (!json_token_streq(json, &toks[++i], "false")) {
|
||||
exec->tty = 1;
|
||||
fprintf(stdout, "container uses terminal\n");
|
||||
|
||||
+88
@@ -16,6 +16,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
@@ -145,6 +147,92 @@ int hyper_find_sd(char *addr, char **dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long id_or_max(const char *name)
|
||||
{
|
||||
char *ptr;
|
||||
long id = strtol(name, &ptr, 10);
|
||||
if (name == ptr || id < 0 || (errno != 0 && id == 0) || *ptr != '\0')
|
||||
return ~0UL;
|
||||
return id;
|
||||
}
|
||||
|
||||
// the same as getpwnam(), but it only parses /etc/passwd and allows name to be id string
|
||||
struct passwd *hyper_getpwnam(const char *name)
|
||||
{
|
||||
uid_t uid = (uid_t)id_or_max(name);
|
||||
FILE *file = fopen("/etc/passwd", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/passwd");
|
||||
return NULL;
|
||||
}
|
||||
for (;;) {
|
||||
struct passwd *pwd = fgetpwent(file);
|
||||
if (!pwd)
|
||||
break;
|
||||
if (!strcmp(pwd->pw_name, name) || pwd->pw_uid == uid) {
|
||||
fclose(file);
|
||||
return pwd;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the same as getgrnam(), but it only parses /etc/group and allows the name to be id string
|
||||
struct group *hyper_getgrnam(const char *name)
|
||||
{
|
||||
gid_t gid = (gid_t)id_or_max(name);
|
||||
FILE *file = fopen("/etc/group", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/group");
|
||||
return NULL;
|
||||
}
|
||||
for (;;) {
|
||||
struct group *gr = fgetgrent(file);
|
||||
if (!gr)
|
||||
break;
|
||||
if (!strcmp(gr->gr_name, name) || gr->gr_gid == gid) {
|
||||
fclose(file);
|
||||
return gr;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the same as getgrouplist(), but it only parses /etc/group
|
||||
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
|
||||
{
|
||||
int nr = 0, ret;
|
||||
FILE *file = fopen("/etc/group", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/group");
|
||||
return -1;
|
||||
}
|
||||
for (;;) {
|
||||
struct group *gr = fgetgrent(file);
|
||||
if (!gr)
|
||||
break;
|
||||
int j;
|
||||
for (j = 0; gr->gr_mem && gr->gr_mem[j]; j++) {
|
||||
if (!strcmp(gr->gr_mem[j], user)) {
|
||||
if (nr + 1 < *ngroups)
|
||||
groups[nr] = gr->gr_gid;
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
if (nr == 0) {
|
||||
if (nr + 1 < *ngroups)
|
||||
groups[nr] = group;
|
||||
nr++;
|
||||
}
|
||||
ret = nr <= *ngroups ? nr : -1;
|
||||
*ngroups = nr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_mkdir(char *hyper_path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include "../config.h"
|
||||
|
||||
struct hyper_pod;
|
||||
@@ -31,4 +33,7 @@ int hyper_setfd_nonblock(int fd);
|
||||
int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
|
||||
void hyper_shutdown(void);
|
||||
int hyper_insmod(char *module);
|
||||
struct passwd *hyper_getpwnam(const char *name);
|
||||
struct group *hyper_getgrnam(const char *name);
|
||||
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user