From: Marc Fiuczynski Date: Wed, 24 Aug 2005 11:46:19 +0000 (+0000) Subject: Resource limit information is not kept in the kernel for contexts that do not have X-Git-Tag: after-util-vserver-0_30_208-revert~129 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;ds=sidebyside;h=f922f3535ed5b5b3ffd0965600a1e835dc4425a2;p=util-vserver.git Resource limit information is not kept in the kernel for contexts that do not have any processes. These limits need to be reinstantiated. For this reason, I have modified vsh to read in CPULIMIT, MEMLIMIT, and TASKLIMIT from /etc/vservers/xyz.conf and set these limits if the context does not exist. When NM takes over this role, the get_limits() function of vsh will need to be modified to obtain those limits from NM rather than these conf files. --- diff --git a/src/vsh.c b/src/vsh.c index 5f1f9a3..1cb0522 100644 --- a/src/vsh.c +++ b/src/vsh.c @@ -198,7 +198,75 @@ static int sandbox_chroot(uid_t uid) return 0; } -static int sandbox_processes(xid_t xid) +#define WHITESPACE(buffer,index,len) \ + while(isspace((int)buffer[index])) \ + if (index < len) index++; else goto out; + +struct resources { + char *name; + int *limit; +}; + +#define VSERVERCONF "/etc/vservers/" +static void get_limits(char *context, int *cpu, int *mem, int *task) { + FILE *fb; + size_t len = strlen(VSERVERCONF) + strlen(context) + strlen(".conf") + NULLBYTE_SIZE; + char *conf = (char *)malloc(len); + struct resources list[] = + {{"MEMLIMIT", mem}, + {"CPULIMIT", cpu}, + {"TASKLIMIT", task}, + {0,0}}; + struct resources *r; + + sprintf(conf, "%s%s.conf", VSERVERCONF, context); + + /* open the conf file for reading */ + fb = fopen(conf,"r"); + if (fb != NULL) { + size_t index; + char *buffer = malloc(1000); + char *p; + + /* the conf file exist */ + while((p=fgets(buffer,1000-1,fb))!=NULL) { + index = 0; + len = strnlen(buffer,1000); + WHITESPACE(buffer,index,len); + if (buffer[index] == '#') + continue; + + for (r=list; r->name; r++) + if ((p=strstr(&buffer[index],r->name))!=NULL) { + /* adjust index into buffer */ + index+= (p-&buffer[index])+strlen(r->name); + + /* skip over whitespace */ + WHITESPACE(buffer,index,len); + + /* expecting to see = sign */ + if (buffer[index++]!='=') goto out; + + /* skip over whitespace */ + WHITESPACE(buffer,index,len); + + /* expecting to see a digit for number */ + if (!isdigit((int)buffer[index])) goto out; + + *r->limit = atoi(&buffer[index]); + break; + } + } + out: + free(buffer); + } else { + fprintf(stderr,"cannot open %s\n",conf); + } + free(conf); +} + + +static int sandbox_processes(xid_t xid, char *context) { #ifdef CONFIG_VSERVER_LEGACY int flags; @@ -218,6 +286,11 @@ static int sandbox_processes(xid_t xid) #else struct vc_ctx_caps caps; struct vc_ctx_flags flags; + int cpu = VC_LIM_KEEP; + int mem = VC_LIM_KEEP; + int task = VC_LIM_KEEP; + get_limits(context,&cpu, &mem, &task); + (void) (sandbox_chroot(xid)); caps.ccaps = ~vc_get_insecureccaps(); caps.cmask = ~0ull; @@ -227,11 +300,35 @@ static int sandbox_processes(xid_t xid) flags.flagword = VC_VXF_INFO_LOCK; flags.mask = VC_VXF_STATE_SETUP | VC_VXF_INFO_LOCK; + errno = 0; if ((vc_ctx_create(xid) == VC_NOCTX) && (errno != EEXIST)) { PERROR("vc_ctx_create(%d)", xid); exit(1); } + if (errno != EEXIST) { + struct vc_rlimit limits; + /* The context did not exist before, which requires that we set the various limit */ + + /* CPU */ + /* not yet */ + + /* MEM */ + limits.min = VC_LIM_KEEP; + limits.soft = VC_LIM_KEEP; + limits.hard = mem; + if (vc_set_rlimit(xid, 5, &limits)) { + } + + /* TASK */ + limits.min = VC_LIM_KEEP; + limits.soft = VC_LIM_KEEP; + limits.hard = task; + if (vc_set_rlimit(xid, 6, &limits)) { + /* setting limit failed */ + } + } + if (vc_set_ccaps(xid, &caps) == -1) { PERROR("vc_set_ccaps(%d, 0x%16ullx/0x%16ullx, 0x%16ullx/0x%16ullx)\n", xid, caps.ccaps, caps.cmask, caps.bcaps, caps.bmask); @@ -347,7 +444,6 @@ void slice_enter(char *context) struct passwd pwdd, *pwd = &pwdd, *result; char *pwdBuffer; long pwdBuffer_len; - unsigned remove_cap; uid_t uid; pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX); @@ -367,27 +463,18 @@ void slice_enter(char *context) PERROR("getpwnam_r(%s)", context); exit(2); } - - context = (char*)malloc(strlen(pwd->pw_name)+NULLBYTE_SIZE); - if (!context) { - PERROR("malloc(%d)"); - exit(2); - } - strcpy(context,pwd->pw_name); + uid = pwd->pw_uid; if (setuidgid_root() < 0) { /* For chroot, new_s_context */ fprintf(stderr, "vsh: Could not become root, check that SUID flag is set on binary\n"); exit(2); } - uid = pwd->pw_uid; - - if (sandbox_chroot(uid) < 0) { - fprintf(stderr, "vsh: Could not chroot\n"); - exit(2); - } +#ifdef CONFIG_VSERVER_LEGACY + (void) (sandbox_chroot(uid)); +#endif - if (sandbox_processes((xid_t) uid) < 0) { + if (sandbox_processes((xid_t) uid, context) < 0) { fprintf(stderr, "vsh: Could not change context to %d\n", uid); exit(2); }