X-Git-Url: http://git.megacz.com/?p=nestedvm.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fnestedvm%2Fsupport_aux.c;h=54181e9834bc77d6e4dfd192fa6ac1b9952f4536;hp=97be5d971d90c7b1179d2860ca68dc13a9298432;hb=937f88333dca3f622bd9e2669e17e7473a447dd9;hpb=18f9d34628d03afdf74b95ccd96e6e2e8441fb54 diff --git a/src/org/ibex/nestedvm/support_aux.c b/src/org/ibex/nestedvm/support_aux.c index 97be5d9..54181e9 100644 --- a/src/org/ibex/nestedvm/support_aux.c +++ b/src/org/ibex/nestedvm/support_aux.c @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include @@ -20,28 +24,6 @@ int _syscall_set_errno(struct _reent *ptr, int err) { return -1; } -extern int _stat_r(struct _reent *, const char *, struct stat *); -int _access_r(struct _reent *ptr, const char *pathname, int mode) { - struct stat statbuf; - if(_stat_r(ptr,pathname,&statbuf) < 0) return -1; - return 0; -} - -/* NestedVM doesn't, and probably never will, support this security related stuff */ -uid_t getuid() { return 0; } -gid_t getgid() { return 0; } -uid_t geteuid() { return 0; } -gid_t getegid() { return 0; } -int getgroups(int gidsetlen, gid_t *gidset) { - if(gidsetlen) *gidset = 0; - return 1; -} -mode_t umask(mode_t new) { return 0022; } -int _chmod_r(struct _reent *ptr, const char *f, mode_t mode) { return 0; } -int _fchmod_r(struct _reent *ptr, int fd, mode_t mode) { return 0; } -int _chown_r(struct _reent *ptr, const char *f, uid_t uid, gid_t gid) { return 0; } -int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid) { return 0; } - #define REENT_WRAPPER0R(f,rt) \ extern rt _##f##_r(struct _reent *ptr); \ rt f() { return _##f##_r(_REENT); } @@ -114,6 +96,7 @@ REENT_WRAPPER3(setpriority,int,int,int) REENT_WRAPPER3(connect,int,const struct sockaddr *,socklen_t) REENT_WRAPPER3(socket,int,int,int) REENT_WRAPPER3(_resolve_hostname,const char *,char*,size_t*) +REENT_WRAPPER3(_resolve_ip,int,char*,size_t) REENT_WRAPPER3(accept,int,struct sockaddr *,socklen_t*) REENT_WRAPPER5(getsockopt,int,int,int,void*,socklen_t*) REENT_WRAPPER5(setsockopt,int,int,int,const void*,socklen_t) @@ -123,6 +106,18 @@ REENT_WRAPPER2(shutdown,int,int) REENT_WRAPPER6(sendto,int,const void*,size_t,int,const struct sockaddr*,socklen_t) REENT_WRAPPER6(recvfrom,int,void*,size_t,int,struct sockaddr*,socklen_t*) REENT_WRAPPER5(select,int,fd_set*,fd_set*,fd_set*,struct timeval*) +REENT_WRAPPER4(send,int,const void*,size_t,int) +REENT_WRAPPER4(recv,int,void*,size_t,int) +REENT_WRAPPER2(getgroups,int,gid_t*) +REENT_WRAPPER3(getsockname,int,struct sockaddr*,int*) +REENT_WRAPPER3(getpeername,int,struct sockaddr*,int*) +REENT_WRAPPER1(setuid,uid_t) +REENT_WRAPPER1(seteuid,uid_t) +REENT_WRAPPER1(setgid,gid_t) +REENT_WRAPPER1(setegid,gid_t) +REENT_WRAPPER2(setgroups,int,const gid_t *) +REENT_WRAPPER0R(setsid,pid_t) +REENT_WRAPPER1(fsync,int) extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]); int _execve(const char *path, char *const argv[], char *const envp[]) { @@ -176,11 +171,6 @@ void sync() { /* do nothing*/ } -int fsync(int fd) { - /* do nothing */ - return 0; -} - char *ttyname(int fd) { return isatty(fd) ? "/dev/console" : NULL; } @@ -203,16 +193,6 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { return 0; } -int sigfillset(sigset_t *set) { - *set = ~((sigset_t)0); - return 0; -} - -int sigemptyset(sigset_t *set) { - *set = (sigset_t) 0; - return 0; -} - DIR *opendir(const char *path) { struct stat sb; int fd; @@ -296,6 +276,33 @@ void herror(const char *string) { fprintf(stderr,"%s: %s\n",string,hstrerror(h_errno)); } +extern int _resolve_ip(int addr, char *buf, size_t size); + +struct hostent *gethostbyaddr(const char *addr, int len, int type) { + static struct hostent hostent; + static char name[128]; + static char *aliases[1]; + static char *addr_list[1]; + static char addr_list_buf[4]; + int err,i; + + if(type != AF_INET || len != 4) return NULL; + memcpy(&i,addr,4); + memcpy(addr_list_buf,addr,4); + err = _resolve_ip(i,name,sizeof(name)); + if(err != 0) { h_errno = err; return NULL; } + + hostent.h_name = name; + hostent.h_aliases = aliases; + aliases[0] = NULL; + hostent.h_addrtype = AF_INET; + hostent.h_length = sizeof(struct in_addr); + hostent.h_addr_list = addr_list; + addr_list[0] = addr_list_buf; + + return &hostent; +} + extern int _resolve_hostname(const char *, char *buf, size_t *size); struct hostent *gethostbyname(const char *hostname) { @@ -328,6 +335,194 @@ struct hostent *gethostbyname(const char *hostname) { return &hostent; } +static struct passwd pw_passwd; +static struct group gr_group; +static FILE *passwd_fp; +static FILE *group_fp; +static char pw_name[1024]; +static char pw_password[1024]; +static char pw_gecos[1024]; +static char pw_dir[1024]; +static char pw_shell[1024]; +static char gr_name[1024]; +static char gr_passwd[1024]; +static char *gr_mem[1]; + +static int gr_parse_body(const char *buf) { + if(sscanf(buf,"%[^:]:%[^:]:%hu",gr_name,gr_passwd,&gr_group.gr_gid) < 3) return -1; + gr_group.gr_name = gr_name; + gr_group.gr_passwd = gr_passwd; + gr_group.gr_mem = gr_mem; + gr_mem[0] = NULL; + return 0; +} + +static int pw_parse_body(const char *buf) { + int pos; + if(sscanf(buf,"%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%s\n",pw_name,pw_password,&pw_passwd.pw_uid,&pw_passwd.pw_gid,pw_gecos,pw_dir,pw_shell) < 7) return -1; + pw_passwd.pw_name = pw_name; + pw_passwd.pw_passwd = pw_password; + pw_passwd.pw_gecos = pw_gecos; + pw_passwd.pw_dir = pw_dir; + pw_passwd.pw_shell = pw_shell; + pw_passwd.pw_comment = ""; + return 0; +} + +struct group *getgrnam(const char *name) { + FILE *fp; + char buf[1024]; + + if((fp=fopen("/etc/group","r"))==NULL) return NULL; + while(fgets(buf,sizeof(buf),fp)) { + if(buf[0] == '#') continue; + if(gr_parse_body(buf) < 0) { + fclose(fp); + return NULL; + } + if(strcmp(name,gr_name)==0) { + fclose(fp); + return &gr_group; + } + } + fclose(fp); + return NULL; +} + +struct group *getgrgid(gid_t gid) { + FILE *fp; + char buf[1024]; + + if((fp=fopen("/etc/group","r"))==NULL) return NULL; + while(fgets(buf,sizeof(buf),fp)) { + if(buf[0] == '#') continue; + if(gr_parse_body(buf) < 0) { + fclose(fp); + return NULL; + } + if(gid == gr_group.gr_gid) { + fclose(fp); + return &gr_group; + } + } + fclose(fp); + return NULL; +} + +struct group *getgrent() { + char buf[1024]; + if(group_fp == NULL) return NULL; + if(fgets(buf,sizeof(buf),group_fp) == NULL) return NULL; + if(buf[0] == '#') return getgrent(); + if(gr_parse_body(buf) < 0) return NULL; + return &gr_group; +} + +void setgrent() { + if(group_fp != NULL) fclose(group_fp); + group_fp = fopen("/etc/group","r"); +} + +void endgrent() { + if(group_fp != NULL) fclose(group_fp); + group_fp = NULL; +} + +struct passwd *getpwnam(const char *name) { + FILE *fp; + char buf[1024]; + + if((fp=fopen("/etc/passwd","r"))==NULL) return NULL; + while(fgets(buf,sizeof(buf),fp)) { + if(buf[0] == '#') continue; + if(pw_parse_body(buf) < 0) { + fclose(fp); + return NULL; + } + if(strcmp(name,pw_name)==0) { + fclose(fp); + return &pw_passwd; + } + } + fclose(fp); + return NULL; +} + +struct passwd *getpwuid(uid_t uid) { + FILE *fp; + char buf[1024]; + + if((fp=fopen("/etc/passwd","r"))==NULL) return NULL; + while(fgets(buf,sizeof(buf),fp)) { + if(buf[0] == '#') continue; + if(pw_parse_body(buf) < 0) { + fclose(fp); + return NULL; + } + if(uid == pw_passwd.pw_uid) { + fclose(fp); + return &pw_passwd; + } + } + fclose(fp); + return NULL; +} + +struct passwd *getpwent() { + char buf[1024]; + if(passwd_fp == NULL) return NULL; + if(fgets(buf,sizeof(buf),passwd_fp) == NULL) return NULL; + if(buf[0] == '#') return getpwent(); + if(pw_parse_body(buf) < 0) return NULL; + return &pw_passwd; +} + +void setpwent() { + if(passwd_fp != NULL) fclose(passwd_fp); + passwd_fp = fopen("/etc/group","r"); +} + +void endpwent() { + if(passwd_fp != NULL) fclose(passwd_fp); + passwd_fp = NULL; +} + +char *getpass(const char *prompt) { + static char buf[1024]; + int len = 0; + fputs(prompt,stderr); + fflush(stdout); + if(fgets(buf,sizeof(buf),stdin)!=NULL) { + len = strlen(buf); + if(buf[len-1] == '\n') len--; + } + fputc('\n',stderr); + buf[len] = '\0'; + return buf; +} + +/* Argh... newlib's asprintf is totally broken... */ +int vasprintf(char **ret, const char *fmt, va_list ap) { + int n; + char *p; + *ret = malloc(128); /* just guess for now */ + if(!*ret) return -1; + n = vsnprintf(*ret,128,fmt,ap); + if(n < 128) { + return n; + } else { + p = realloc(*ret,n+1); + if(!p) { free(*ret); return -1; } + return vsprintf(*ret = p,fmt,ap); + } +} + +// FIXME: This needs to be in a header +char *getlogin() { + return getenv("USER"); +} + + /* * Other People's Code */ @@ -525,6 +720,23 @@ struct utsname *name; return (rval); } +/* FreeBSD's gethostname */ +int +gethostname(name, namelen) +char *name; +int namelen; +{ + int mib[2]; + size_t size; + + mib[0] = CTL_KERN; + mib[1] = KERN_HOSTNAME; + size = namelen; + if (sysctl(mib, 2, name, &size, NULL, 0) == -1) + return (-1); + return (0); +} + /* FreeBSD's daemon() - modified for nestedvm */ int daemon(nochdir, noclose) @@ -541,8 +753,8 @@ int nochdir, noclose; _exit(0); } - /*if (setsid() == -1) - return (-1);*/ + if (setsid() == -1) + return (-1); if (!nochdir) (void)chdir("/"); @@ -556,3 +768,184 @@ int nochdir, noclose; } return (0); } + +/* FreeBSD's inet_addr/inet_aton */ + +/* +* Check whether "cp" is a valid ASCII representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(cp, addr) +register const char *cp; +struct in_addr *addr; +{ + u_long parts[4]; + in_addr_t val; + char *c; + char *endptr; + int gotend, n; + + c = (char *)cp; + n = 0; + /* + * Run through the string, grabbing numbers until + * the end of the string, or some error + */ + gotend = 0; + while (!gotend) { + errno = 0; + val = strtoul(c, &endptr, 0); + + if (errno == ERANGE) /* Fail completely if it overflowed. */ + return (0); + + /* + * If the whole string is invalid, endptr will equal + * c.. this way we can make sure someone hasn't + * gone '.12' or something which would get past + * the next check. + */ + if (endptr == c) + return (0); + parts[n] = val; + c = endptr; + + /* Check the next character past the previous number's end */ + switch (*c) { + case '.' : + /* Make sure we only do 3 dots .. */ + if (n == 3) /* Whoops. Quit. */ + return (0); + n++; + c++; + break; + + case '\0': + gotend = 1; + break; + + default: + if (isspace((unsigned char)*c)) { + gotend = 1; + break; + } else + return (0); /* Invalid character, so fail */ + } + + } + + /* + * Concoct the address according to + * the number of parts specified. + */ + + switch (n) { + case 0: /* a -- 32 bits */ + /* + * Nothing is necessary here. Overflow checking was + * already done in strtoul(). + */ + break; + case 1: /* a.b -- 8.24 bits */ + if (val > 0xffffff || parts[0] > 0xff) + return (0); + val |= parts[0] << 24; + break; + + case 2: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 3: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff || + parts[2] > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + + if (addr != NULL) + addr->s_addr = htonl(val); + return (1); +} + +/* + * ASCII internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t /* XXX should be struct in_addr :( */ +inet_addr(cp) +register const char *cp; +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} + +int +getgrouplist(uname, agroup, groups, grpcnt) +const char *uname; +gid_t agroup; +register gid_t *groups; +int *grpcnt; +{ + register struct group *grp; + register int i, ngroups; + int ret, maxgroups; + + ret = 0; + ngroups = 0; + maxgroups = *grpcnt; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + groups[ngroups++] = agroup; + if (maxgroups > 1) + groups[ngroups++] = agroup; + /* + * Scan the group file to find additional groups. + */ + setgrent(); + while ((grp = getgrent())) { + for (i = 0; i < ngroups; i++) { + if (grp->gr_gid == groups[i]) + goto skip; + } + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], uname)) { + if (ngroups >= maxgroups) { + ret = -1; + break; + } + groups[ngroups++] = grp->gr_gid; + break; + } + } +skip: ; + } + endgrent(); + *grpcnt = ngroups; + return (ret); +} + +int +initgroups(uname, agroup) +const char *uname; +gid_t agroup; +{ + gid_t groups[32], ngroups; + + ngroups = 32; + getgrouplist(uname, agroup, groups, &ngroups); + return (setgroups(ngroups, groups)); +}