#define __KERNEL__ #include #undef __KERNEL__ #include #include #include #include #include #include #include #include #include #include #include "constable.h" #include "language.h" #include "runtime.h" #include "events.h" extern int conv_err; files_t *root = NULL; void zzz(int i) { printf("zzz %d) %p\n", i, root->patterns); } int init_files(fentry_t * e, files_t * base, char *s); int is_pattern(char *what, int len) { while (*what && len) { switch (*what) { case '(': case ')': case '[': case ']': case '^': case '$': case '.': case '*': case '+': case '?': case '{': case '}': case '|': return 1; case '\\': if ( (what[1] >= 'A' && what[1] <= 'Z') || (what[1] >= 'a' && what[1] <= 'z') ) return 1; what++; len--; if (!what[1] || !len) return 1; default: what++; len--; } } return 0; } int match_pattern(fpattern_t * p, char *s) { //printf("match_pattern(xxx/%s,\"%s\")\n",p->path,s); //fflush(stdout); if (regexec(&(p->reg), s, 0, NULL, 0) == 0) return 1; return 0; } int apply_match_to_files(files_t * f, fpattern_t * p) { fentry_t *e; if ((e = malloc(sizeof(fentry_t))) == NULL) return -1; memcpy(e, p->ent, sizeof(fentry_t)); return init_files(e, f, p->path); } int insert_pattern(fentry_t * e, files_t * base, char *s, int i) { fpattern_t *p; files_t *f; static char tmp[1024]; if ((p = malloc(sizeof(fpattern_t))) == NULL) return -1; p->next = base->patterns; base->patterns = p; e->next = NULL; p->ent = e; if (s[i] == 0) { p->path = ""; } else { if ((p->path = malloc(strlen(s + i)+1)) == NULL) return -1; strcpy(p->path, s + i + 1); } if (i > 1020) return -1; tmp[0] = '^'; strncpy(tmp + 1, s, i); tmp[i + 1] = '$'; tmp[i + 2] = 0; if (regcomp(&(p->reg), tmp, REG_EXTENDED | REG_NOSUB) != 0) { fprintf(stderr, "%s: Error in regexp '%s'\n", me, s); return -1; } f = base->child; while (f != NULL) { if (f->name != NULL && match_pattern(p, f->name)) { if (apply_match_to_files(f, p) < 0) return -1; } f = f->next; } return 0; } files_t *add_new_node(files_t * base, char *name, int len, struct m_inode_inf * inode) { files_t *p; fpattern_t *a; //printf("add %s\n",name); if ((p = malloc(sizeof(files_t))) == NULL) return NULL; p->patterns = NULL; p->parent = base; p->child = NULL; p->ent = NULL; if (inode != NULL) { p->inode.dev = inode->dev; p->inode.ino = inode->ino; } else { p->inode.dev = 0; /* finding out real values would be probably better */ p->inode.ino = 0; } if ((p->name = malloc(len + 1)) == NULL) { free(p); return NULL; } memcpy(p->name, name, len); p->name[len] = 0; if ((p->child = malloc(sizeof(files_t))) == NULL) { free(p); return NULL; } p->child->patterns = NULL; p->child->parent = p; p->child->child = NULL; p->child->next = NULL; p->child->ent = NULL; p->child->inode.dev = 0; p->child->inode.ino = 0; p->child->name = NULL; p->next = base->child; base->child = p; //print_info(0,root); //printf("XXX base=%p p=%p\n",base,p); a = base->patterns; while (a != NULL) { if (match_pattern(a, p->name)) { if (apply_match_to_files(p, a) < 0) { printlog ("This application caused Error #2357 in module fs.o at address %d and will not be terminated.", 0); } //printf("something added\n"); } a = a->next; } return p; } int init_files(fentry_t * e, files_t * base, char *s) { int i, j; files_t *p; static char tmp[1024]; /* printf("init_files(\"%s\",\"%s\")\n",base->name,s); */ while (*s == '/') s++; for (j = i = 0; s[i] != 0 && s[i] != '/';) { if (s[i] == '\\' && s[i + 1] != 0 && s[i + 1] != '/') i++; tmp[j++] = s[i]; i++; } tmp[j] = 0; if (i == 0) { //print_info(0,root); if (base->ent == NULL) { e->next = base->ent; base->ent = e; } else { fentry_t *a; a = base->ent; while (a->next != NULL) a = a->next; e->next = NULL; a->next = e; } //printf("add ent(%p) %04x to %s\n",e,e->act,base->name); //print_info(0,root); return 0; } p = base->child; while (p != NULL) { if ((p->name == NULL && i == 1 && s[0] == '*') || (p->name != NULL && strlen(p->name) == i && !memcmp(p->name, s, i))) { return init_files(e, p, s + i); } else p = p->next; } //printf ("is_pattern(\"%s\",%d) =", s, i); fflush(stdout); if (is_pattern(s, i)) return insert_pattern(e, base, s, i); if ((p = add_new_node(base, tmp, j, NULL)) == NULL) return -1; return init_files(e, p, s + i); } int init_root(void) { struct stat st; if (root != NULL) return 0; if (stat("/", &st) < 0) exit(-1); if ((root = malloc(sizeof(files_t))) == NULL) { return -1; } root->parent = NULL; if ((root->child = malloc(sizeof(files_t))) == NULL) { return -1; } root->patterns = NULL; root->next = NULL; root->name = NULL; root->ent = NULL; root->inode.dev = st.st_dev; root->inode.ino = st.st_ino; root->child->parent = root; root->child->child = NULL; root->child->next = NULL; root->child->ent = NULL; root->child->inode.dev = 0; root->child->inode.ino = 0; root->child->name = NULL; return 0; } void add_fsentry(udata act, udata recursive, char *subor, udata * prog, int proglen) { fentry_t *e; init_root(); if ((e = malloc(sizeof(fentry_t))) == NULL) fatal(OUTMEM); e->act = (__u16) act; if (recursive) e->act |= MIACT_RECURSIVE; e->program = prog; e->proglen = proglen; //printf("adding %04x for file %s\n",e->act,file); if (init_files(e, root, subor) < 0) fatal("Can't add fsentry to tree!"); free(subor); } static int apply_one(int sibl, int pid, struct med_s *orig, udata * prog) { struct med_s med; struct medusa_packet msg; int child; med.inode = NULL; med.target = NULL; if (pid == orig->proc.pid) return 0; /* not itself */ msg.cmd = MED_GET_PROC; msg.u.r_cmd.proc.pid = pid; med_cmd(&msg, NULL); if (msg.answer != MED_YES) return -1; med = *orig; med.proc = msg.u.a_cmd.proc; pid = med.proc.sibling_pid; child = med.proc.child_pid; if (pid != orig->proc.pid) { /* don't modify itself */ exec_program(prog, &med); msg.u.r_cmd.proc = med.proc; msg.cmd = MED_SET_PROC; med_cmd(&msg, NULL); } if (sibl > 0 && pid > 0) apply_one(1, pid, orig, prog); if (sibl >= 0 && child > 0) apply_one(1, child, orig, prog); return 0; } int apply(int mode, struct med_s *orig, udata * prog) { struct medusa_packet msg; int pid, cpid; cpid = orig->proc.pid; pid = orig->proc.parent_pid; if (mode == APPLY_FOR_LOGIN) { while (pid > 1) { msg.cmd = MED_GET_PROC; msg.u.r_cmd.proc.pid = pid; med_cmd(&msg, NULL); if (msg.answer != MED_YES) break; if (msg.u.a_cmd.proc.luid == (uid_t) - 1) break; cpid = pid; pid = msg.u.a_cmd.proc.parent_pid; } pid = cpid; } if (pid == 0) return 0; if (mode == APPLY_PARENT) apply_one(-1, pid, orig, prog); if (mode == APPLY_FOR_PARENT) apply_one(0, pid, orig, prog); if (mode == APPLY_FOR_LOGIN) apply_one(0, pid, orig, prog); return 0; } int print_info(int level, files_t * f) { int i; files_t *par; fentry_t *e; par = f->parent; while (f != NULL) { if (f->parent != par) fprintf(stderr, "%s: PARENT Error!\n", me); for (i = 0; i < level; i++) printf(" "); printf("%s\n", f->name); e = f->ent; while (e != NULL) { for (i = 0; i < level; i++) printf(" "); printf(". 0x%04x\n", e->act); e = e->next; } if (f->child != NULL) { if (f->child->parent != f) fprintf(stderr, "%s: PARENT ERROR!\n", me); print_info(level + 2, f->child); } f = f->next; } return 0; } int print_name(char *s, files_t * f) { int i = 0; if (f->parent != NULL) i = print_name(s, f->parent); s[i] = '/'; if (f->name != NULL) strcpy(s + i + 1, f->name); else if (f->parent != NULL) strcpy(s + i + 1, "*"); else s[i] = 0; i += strlen(s + i); return i; } files_t *files_find_ino(files_t * f, unsigned long dev, unsigned long ino) { files_t *g; while (f != NULL) { if (f->inode.ino == ino && f->inode.dev == dev) return f; if (f->child != NULL) { if ((g = files_find_ino(f->child, dev, ino)) != NULL) return g; } f = f->next; } return NULL; } files_t *files_find_pattern_name(files_t * base, char *name, struct m_inode_inf * inode) { fpattern_t *p; files_t *f = NULL; p = base->patterns; while (p != NULL) { if (match_pattern(p, name)) { f = add_new_node(base, name, strlen(name), inode); break; } p = p->next; } if (f == NULL) return base; return f; } files_t *files_find_name(files_t * base, char *name, struct m_inode_inf * inode) { files_t *f, *def; if (name[0] == '.' && name[1] == 0) return base; if (name[0] == '.' && name[1] == '.' && name[2] == 0) { if (base->parent == NULL) return base; if (base->name != NULL) return base->parent; if (inode->ino == base->parent->inode.ino && inode->dev == base->parent->inode.dev) return base->parent; if (base->parent->inode.ino == 0 && base->parent->inode.dev == 0) printf("%s: Can't identify '..'\n", me); return base; } def = NULL; if ((f = base->child) == NULL) { if (base->name == NULL) return files_find_pattern_name(base, name, inode); printf("%s: Error: Bad internal file table (no child)!\n", me); return base; } while (f != NULL) { if (f->name != NULL && !strcmp(name, f->name)) { if (f->inode.ino == 0 && f->inode.dev == 0) { f->inode.ino = inode->ino; f->inode.dev = inode->dev; } #if 0 if (f->inode.ino != inode->ino || f->inode.dev != inode->dev) printf ("%s: Bad inode number: f:[%04x]:%ld " "i:[%04x]:%ld\n", me, f->inode.dev, f->inode.ino, inode->dev, inode->ino); #endif return f; } if (f->name == NULL) def = f; f = f->next; } f = files_find_pattern_name(base, name, inode); if (f != base) return f; if (def != NULL) return def; printf("%s: Error: Bad internal file table (no *)!\n", me); return base; } fentry_t *files_find_entry(files_t * start, int act) { static fentry_t *e = NULL; static files_t *f = NULL; static int recurse = 0; if (start != NULL) { f = start; recurse = 0; e = NULL; } else if (e != NULL) goto Cont; while (f != NULL) { if (e == NULL) e = f->ent; while (e != NULL) { if ((!recurse && !(e->act & MIACT_RECURSIVE)) || (recurse && (e->act & MIACT_RECURSIVE))) { if ((e->act & act) || (e->act == 0 && (act == 0 || act == ~0))) return e; } Cont:e = e->next; } if (!recurse) recurse = 1; else f = f->parent; } return NULL; } int files_iget(struct medusa_packet *msg, char *data, struct medusa_packet *ans, char **outdata) { files_t *f; fentry_t *e; struct med_inode *mi; __u16 act; int vs_valid; struct med_s meds; meds.inode = NULL; meds.target = NULL; if (msg->cmd != MED_IGET) return 0; /* not for me */ if (data == NULL) return -1; if (!med_c_valid(&(msg->u.r_iget.parent.mi))) { #if 0 f = files_find_ino(root, msg->u.r_iget.parent.dev, msg->u.r_iget.parent.ino); #else f=NULL; if( msg->u.r_iget.parent.dev==msg->u.r_iget.inode.dev && msg->u.r_iget.parent.ino==msg->u.r_iget.inode.ino ) f=root; //else printf("[%d:%d]->[%d:%d]\n",msg->u.r_iget.parent.dev,msg->u.r_iget.parent.ino,msg->u.r_iget.inode.dev,msg->u.r_iget.inode.ino); #endif if (f == NULL) return -1; msg->u.r_iget.parent.mi.cinfo = (u_long) f; } f = (files_t *) msg->u.r_iget.parent.mi.cinfo; if (msg->u.r_iget.parent.dev != msg->u.r_iget.inode.dev || msg->u.r_iget.parent.ino != msg->u.r_iget.inode.ino) f = files_find_name(f, data, &(msg->u.r_iget.inode)); if (f == NULL) return -1; /* print_name( buf, f ); // printf("sending info %ld/ [%04x]:%ld %s (%s)\n", printf("sending info [%04x]:%ld %s (%s)\n", // msg->u.r_iget.parent.mi.cinfo, msg->u.r_iget.inode.dev,msg->u.r_iget.inode.ino, data,buf); */ meds.inode = &(msg->u.r_iget.inode); msg->u.r_iget.inode.mi.cinfo = (u_long) f; meds.data = data; meds.proc.mp.med_vs = 0xffff; #ifdef CONFIG_MEDUSA_FILE_CAPABILITIES // if( (med.inode->mode & S_ISUID) && med.inode->uid=0 ) // meds.proc.cap_permitted= 0xffffffff; // else meds.proc.cap_permitted= 0x00000000; meds.proc.cap_inheritable=0xffffffff; meds.proc.cap_effective= 0xffffffff; #endif meds.answer = MED_OK; meds.action = (__u32) MIACT_IGET; ans->answer = MED_OK; mi = &(ans->u.a_iget.inode.mi); mi->med_vs = 0xffff; #ifdef CONFIG_MEDUSA_FILE_CAPABILITIES // if( (med.inode->mode & S_ISUID) && med.inode->uid=0 ) // mi->pcap = 0xffffffff; // else mi->pcap = 0x00000000; mi->icap = 0xffffffff; mi->ecap = 0xffffffff; #endif vs_valid = 0; mi->med_act = MIACT_VALID; if (f->child == NULL && f->name == NULL) mi->med_act |= MIACT_INHERIT; mi->cinfo = (u_long) f; e = files_find_entry(f, ~0); while (e != NULL) { act = e->act & ~MIACT_RECURSIVE; if (act == MIACT_IGET) { meds.proc.mp.med_vs = mi->med_vs; #ifdef CONFIG_MEDUSA_FILE_CAPABILITIES meds.proc.cap_inheritable = mi->icap; meds.proc.cap_permitted = mi->pcap; meds.proc.cap_effective = mi->ecap; #endif meds.proc.mp.med_iact = mi->med_act; exec_program(e->program, &meds); if (!vs_valid) { mi->med_vs = meds.proc.mp.med_vs; #ifdef CONFIG_MEDUSA_FILE_CAPABILITIES mi->icap = meds.proc.cap_inheritable; mi->pcap = meds.proc.cap_permitted; mi->ecap = meds.proc.cap_effective; #endif vs_valid = 1; } } else mi->med_act |= act; e = files_find_entry(NULL, ~0); } return 1; /* OK */ } int files_iact(struct medusa_packet *msg, char *data, struct medusa_packet *ans, char **outdata) { files_t *f; fentry_t *e; struct med_s meds; int default_answer; meds.inode = NULL; meds.target = NULL; if (msg->cmd == MED_IACT && (msg->u.r_iact.pact == MPACT_IOP || msg->u.r_iact.pact == MPACT_EXEC)) { meds.inode = &(msg->u.r_iact.inode); meds.data = data; meds.proc = msg->u.r_iact.proc; meds.info1 = msg->u.r_iact.info1; meds.info2 = msg->u.r_iact.info2; meds.action = (__u32) (msg->u.r_iact.act); meds.redirect = NULL; if (msg->u.r_iact.pact == MPACT_IOP) evdo_fsact(&meds); else evdo_exec(&meds); ans->u.a_iact.proc = meds.proc; ans->answer = meds.answer; *outdata = meds.redirect; return 1; /* OK */ } if (msg->cmd != MED_IACT || msg->u.r_iact.pact != 0) return 0; /* not for me */ f = (files_t *) msg->u.r_iact.inode.mi.cinfo; if (f == NULL) return 0; /* print_name( buf, f ); printf("access to %s\n",buf); */ meds.inode = &(msg->u.r_iact.inode); meds.data = data; meds.proc = msg->u.r_iact.proc; meds.info1 = msg->u.r_iact.info1; meds.info2 = msg->u.r_iact.info2; meds.answer = MED_NONE; default_answer = MED_ERR; meds.action = (__u32) (msg->u.r_iact.act); meds.redirect = NULL; e = files_find_entry(f, msg->u.r_iact.act); while (e != NULL) { meds.apply_mode = 0; runtime_cmd = 0; exec_program(e->program, &meds); if (runtime_cmd) { default_answer = MED_OK; if (meds.apply_mode != 0) apply(meds.apply_mode, &meds, e->program); } e = files_find_entry(NULL, msg->u.r_iact.act); } ans->u.a_iact.proc = meds.proc; if (meds.answer == MED_NONE) meds.answer = default_answer; ans->answer = meds.answer; *outdata = meds.redirect; return 1; /* OK */ } void alarm_handle(int sig) { print_info(0, root); fflush(stdout); signal(sig, alarm_handle); } int fs_init(void) { init_root(); add_module(files_iact); add_module(files_iget); //print_info(0,root); signal(SIGUSR1, alarm_handle); return 0; }