Merge pull request #90 from laijs/user

enable the user config
This commit is contained in:
Lai Jiangshan
2016-05-16 22:31:19 +08:00
6 changed files with 249 additions and 1 deletions
+5
View File
@@ -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
View File
@@ -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;
+5
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+5
View File
@@ -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