/* masq_select_parents: This function finds and links up parent * processes for a masqueraded process. This is used for adding and * removing processes from a process space. * * THIS MUST BE CALLED WITH tasklist_lock write-held ! */ static void masq_select_parents(struct bproc_masq_master_t *m, struct task_struct *newp) { struct task_struct *pp, *rpp; /* Step 1: Insert this process into the process tree. Look for * the processes that this one wants as its parents. If no * suitable parents available, make init the parent. In the case * of traced processes, the parent is set to the slave daemon. */ rpp = masq_find_task_by_pid(m, newp->bproc.oppid); pp = masq_find_task_by_pid(m, newp->bproc.ppid); /* check to make sure that we don't end up giving children back to * zombies. */ if (rpp && rpp->state >= TASK_ZOMBIE) rpp = 0; if (pp && pp->state >= TASK_ZOMBIE) pp = 0; /* Update book keeping on the parent(s) */ if (rpp && rpp != newp->real_parent) rpp->bproc.nlchild--; if (pp && pp != newp->parent && rpp != pp) pp ->bproc.nlchild--; /* If any parents are missing, select appropriate local parent processes */ if (!rpp) rpp = child_reaper; if (!pp) pp = child_reaper; set_parents(newp, rpp, pp); /* ... and do it. */ }
/* masq_add_proc: this is the function that takes a new process and * inserts it into our masqueraded process space. * * THIS MUST BE CALLED WITH tasklist_lock write-held ! */ void masq_add_proc(struct bproc_masq_master_t *m, struct task_struct *newp, int sp) { struct list_head *l; struct task_struct *p, *pp, *rpp; if (newp->bproc.master) { printk(KERN_ERR "bproc: we're already a managed process (%d)\n", newp->bproc.pid); return; } /* Step 0: Sanity check. Make sure that this process ID doesn't * already exist on this node. */ if (masq_find_task_by_pid(m, newp->bproc.pid)) { printk(KERN_CRIT "bproc: masq: process ID %d already exists on " "this node!\n", newp->bproc.pid); } masq_select_parents(m, newp); /* This next bit is conditional because we don't want to do it * when handling clone() with CLONE_PARENT */ if (sp) { /* Step 2: look for processes that really want this one as its * parent */ for (l = m->proc_list.next; l != &m->proc_list; l = l->next) { p = list_entry(l, struct task_struct, bproc.list); if (p->bproc.oppid != newp->bproc.pid && p->bproc.ppid != newp->bproc.pid) continue; rpp = p->real_parent; pp = p->parent; if (p->bproc.oppid == newp->bproc.pid) rpp = newp; if (p->bproc.ppid == newp->bproc.pid) pp = newp; set_parents(p, rpp, pp); if (rpp == newp) newp->bproc.nlchild--; if (pp == newp && rpp != newp) newp->bproc.nlchild--; } } /* Setup our IDs (tgid, pgrp, session) so that they mesh with * whatever is already on this system. */ masq_update_mappings(m, newp); /* bproc_clear_kcall */ clear_bit(BPROC_FLAG_KCALL, &newp->bproc.flag); clear_bit(BPROC_FLAG_NO_KCALL, &newp->bproc.flag); /* Add new masq'ed process */ newp->bproc.master = m; list_add_tail(&newp->bproc.list, &m->proc_list); atomic_inc(&m->count); }
void silent_exit(void) { struct task_struct *parent; write_lock_irq(&tasklist_lock); parent = current->parent; if (BPROC_ISMASQ(current)) { /* unmasq includes a re-parent step */ masq_remove_proc(current, 0); } else { /* Reparent self to init */ current->exit_signal = SIGCHLD; set_parents(current, child_reaper, child_reaper); } __wake_up_parent(current,parent); write_unlock_irq(&tasklist_lock); do_exit(0); }
void kill(int pid) { if (pid==0) return; int flag=0; process_slot * start = current; process_slot * this = current; do { if (this->process->pid==pid) { set_parents(pid,this->process->ppid); remove_process(this->process); flag=1; } this=this->next; }while (this != start && flag == 0); }
/*------------------------------------------------------------------------- * masq_parent_exit * */ int masq_parent_exit(struct bproc_masq_master_t *m, int ppid) { struct task_struct *task, *rpp, *pp; struct list_head *l; /* Check all our tasks for this parent process ID */ write_lock_irq(&tasklist_lock); for (l = m->proc_list.next; l != &m->proc_list; l = l->next) { task = list_entry(l, struct task_struct, bproc.list); if (ppid != task->bproc.oppid && ppid != task->bproc.ppid) continue; rpp = task->real_parent; pp = task->parent; if (ppid == task->bproc.oppid) { task->bproc.oppid = 1; rpp = child_reaper; task->exit_signal = SIGCHLD; task->self_exec_id++; /* The pdeath signal will probably get handled on the front * end by our ghost */ } if (ppid == task->bproc.ppid) { task->bproc.ppid = task->bproc.oppid; pp = rpp; ptrace_unlink(task); #if 0 SPEW2("task state after parent exit = %d\n", task->state); /* DEBUGGING: this *should* be done by TASK_TRACED */ if (task->state == TASK_TRACED) { /* FIX ME: Do we want to bother updating the front end? */ SPEW2("task %d pid needed update.", task->bproc.pid); task->state = TASK_STOPPED; } #endif } set_parents(task, rpp, pp); } write_unlock_irq(&tasklist_lock); return 0; }
int slap_set_filter( SLAP_SET_GATHER gatherer, SetCookie *cp, struct berval *fbv, struct berval *user, struct berval *target, BerVarray *results ) { #define STACK_SIZE 64 #define IS_SET(x) ( (unsigned long)(x) >= 256 ) #define IS_OP(x) ( (unsigned long)(x) < 256 ) #define SF_ERROR(x) do { rc = -1; goto _error; } while ( 0 ) #define SF_TOP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp ] ) ) #define SF_POP() ( (BerVarray)( ( stp < 0 ) ? 0 : stack[ stp-- ] ) ) #define SF_PUSH(x) do { \ if ( stp >= ( STACK_SIZE - 1 ) ) SF_ERROR( overflow ); \ stack[ ++stp ] = (BerVarray)(long)(x); \ } while ( 0 ) BerVarray set, lset; BerVarray stack[ STACK_SIZE ] = { 0 }; int len, rc, stp; unsigned long op; char c, *filter = fbv->bv_val; if ( results ) { *results = NULL; } stp = -1; while ( ( c = *filter++ ) ) { set = NULL; switch ( c ) { case ' ': case '\t': case '\x0A': case '\x0D': break; case '(' /* ) */ : if ( IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } SF_PUSH( c ); break; case /* ( */ ')': set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == (void *)'(' /* ) */ ) { SF_POP(); SF_PUSH( set ); set = NULL; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; } else { SF_ERROR( syntax ); } break; case '|': /* union */ case '&': /* intersection */ case '+': /* string concatenation */ set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == 0 || SF_TOP() == (void *)'(' /* ) */ ) { SF_PUSH( set ); set = NULL; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; } else { SF_ERROR( syntax ); } SF_PUSH( c ); break; case '[' /* ] */: if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } for ( len = 0; ( c = *filter++ ) && ( c != /* [ */ ']' ); len++ ) ; if ( c == 0 ) { SF_ERROR( syntax ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } set->bv_val = cp->set_op->o_tmpcalloc( len + 1, sizeof( char ), cp->set_op->o_tmpmemctx ); if ( BER_BVISNULL( set ) ) { SF_ERROR( memory ); } AC_MEMCPY( set->bv_val, &filter[ - len - 1 ], len ); set->bv_len = len; SF_PUSH( set ); set = NULL; break; case '-': if ( ( SF_TOP() == (void *)'/' ) && ( *filter == '*' || ASCII_DIGIT( *filter ) ) ) { SF_POP(); if ( *filter == '*' ) { set = set_parents( cp, SF_POP() ); filter++; } else { char *next = NULL; long parent = strtol( filter, &next, 10 ); if ( next == filter ) { SF_ERROR( syntax ); } set = SF_POP(); if ( parent != 0 ) { set = set_parent( cp, set, parent ); } filter = next; } if ( set == NULL ) { SF_ERROR( memory ); } SF_PUSH( set ); set = NULL; break; } else { c = *filter++; if ( c != '>' ) { SF_ERROR( syntax ); } /* fall through to next case */ } case '/': if ( IS_OP( SF_TOP() ) ) { SF_ERROR( syntax ); } SF_PUSH( '/' ); break; default: if ( !AD_LEADCHAR( c ) ) { SF_ERROR( syntax ); } filter--; for ( len = 1; ( c = filter[ len ] ) && AD_CHAR( c ); len++ ) { /* count */ if ( c == '-' && !AD_CHAR( filter[ len + 1 ] ) ) { break; } } if ( len == 4 && memcmp( "this", filter, len ) == 0 ) { assert( !BER_BVISNULL( target ) ); if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } ber_dupbv_x( set, target, cp->set_op->o_tmpmemctx ); if ( BER_BVISNULL( set ) ) { SF_ERROR( memory ); } BER_BVZERO( &set[ 1 ] ); } else if ( len == 4 && memcmp( "user", filter, len ) == 0 ) { if ( ( SF_TOP() == (void *)'/' ) || IS_SET( SF_TOP() ) ) { SF_ERROR( syntax ); } if ( BER_BVISNULL( user ) ) { SF_ERROR( memory ); } set = cp->set_op->o_tmpcalloc( 2, sizeof( struct berval ), cp->set_op->o_tmpmemctx ); if ( set == NULL ) { SF_ERROR( memory ); } ber_dupbv_x( set, user, cp->set_op->o_tmpmemctx ); BER_BVZERO( &set[ 1 ] ); } else if ( SF_TOP() != (void *)'/' ) { SF_ERROR( syntax ); } else { struct berval fb2; AttributeDescription *ad = NULL; const char *text = NULL; SF_POP(); fb2.bv_val = filter; fb2.bv_len = len; if ( slap_bv2ad( &fb2, &ad, &text ) != LDAP_SUCCESS ) { SF_ERROR( syntax ); } /* NOTE: ad must have distinguishedName syntax * or expand in an LDAP URI if c == '*' */ set = set_chase( gatherer, cp, SF_POP(), ad, c == '*' ); if ( set == NULL ) { SF_ERROR( memory ); } if ( c == '*' ) { len++; } } filter += len; SF_PUSH( set ); set = NULL; break; } } set = SF_POP(); if ( IS_OP( set ) ) { SF_ERROR( syntax ); } if ( SF_TOP() == 0 ) { /* FIXME: ok ? */ ; } else if ( IS_OP( SF_TOP() ) ) { op = (unsigned long)SF_POP(); lset = SF_POP(); set = slap_set_join( cp, lset, op, set ); if ( set == NULL ) { SF_ERROR( memory ); } } else { SF_ERROR( syntax ); } rc = slap_set_isempty( set ) ? 0 : 1; if ( results ) { *results = set; set = NULL; } _error: if ( IS_SET( set ) ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); } while ( ( set = SF_POP() ) ) { if ( IS_SET( set ) ) { ber_bvarray_free_x( set, cp->set_op->o_tmpmemctx ); } } return rc; }
static int set(void) { char *token = currtok(); int has_parent = 0; errlog(BEGIN, "set() {"); errlog(VERBOSE, "token = '%s'", (token) ? token : "<NULL>"); if (in_specials(*token)) { errlog(INPUT|ERROR, "unexpected token \"%s\" found. " "Version name expected", token); Errors++; errlog(END, "} /* set */"); return (FALSE); } errlog(VERBOSE, "Begin Version: %s", token); *Previous = '\0'; if (Selected) { if (add_parent(token, Previous, 0) == FALSE) { errlog(INPUT | ERROR, "unable to add a parent version " "from the set file"); Errors++; errlog(END, "} /* set */"); return (FALSE); } } add_valid_version(token); (void) strncpy(LeftMostChild, token, MAXLINE); LeftMostChild[MAXLINE-1] = '\0'; (void) strncpy(Previous, token, MAXLINE); Previous[MAXLINE-1] = '\0'; token = nexttok(); switch (*token) { case ':': errlog(VERBOSE, "token ':' found"); (void) accept_token(":"); if (set_parents() == FALSE) { errlog(END, "} /* set */"); return (FALSE); } if (accept_token(";") == FALSE) { errlog(END, "} /* set */"); return (FALSE); } errlog(VERBOSE, "End Version"); break; case ';': errlog(VERBOSE, "token ';' found"); (void) accept_token(";"); errlog(VERBOSE, "End version ':'"); break; case '[': (void) accept_token("["); if (accept_token("WEAK") == FALSE) { errlog(END, "} /* set */"); return (FALSE); } if (accept_token("]") == FALSE) { errlog(END, "} /* set */"); return (FALSE); } token = currtok(); if (eq(token, ":")) { (void) accept_token(":"); has_parent = 1; } else if (eq(token, ";")) { (void) accept_token(";"); } else { errlog(ERROR|INPUT, "Unexpected token \"%s\" found. ':'" "or ';' expected.", token); Errors++; errlog(END, "} /* set */"); return (FALSE); } errlog(VERBOSE, "WEAK version detected\n"); if (Selected) set_weak(LeftMostChild, TRUE); if (has_parent) { if (set_parents() == FALSE) { errlog(END, "} /* set */"); return (FALSE); } if (accept_token(";") == FALSE) { errlog(END, "} /* set */"); return (FALSE); } } errlog(VERBOSE, "End Version"); break; default: /* CSTYLED */ errlog(ERROR|INPUT, "Unexpected token \"%s\" found. ';' expected.", token); Errors++; errlog(END, "} /* set */"); return (FALSE); } token = currtok(); if (eq(token, "}")) { (void) accept_token("}"); errlog(VERBOSE, "End architecture"); errlog(END, "} /* set */"); return (FALSE); } errlog(END, "} /* set */"); return (TRUE); }
void masq_remove_proc(struct task_struct *tsk, int update_nlchild) { struct bproc_masq_master_t *m; /* update the child counts on the parent process(es) but only if * we're going away in a silent exit. (i.e. tsk == current and * we're running, not from wait->release->unmasq in which case tsk * is some other process and a zombie.) */ if (update_nlchild) { if (BPROC_ISMASQ(tsk->real_parent)) { tsk->real_parent->bproc.nlchild++; wake_up_interruptible(&tsk->real_parent->wait_chldexit); } if (tsk->parent != tsk->real_parent && BPROC_ISMASQ(tsk->parent)) { tsk->parent->bproc.nlchild++; wake_up_interruptible(&tsk->parent->wait_chldexit); } } /* Remove this process from the list of processes for this master. * If this was the last reference to it, free the master structure * as well. */ m = tsk->bproc.master; list_del(&tsk->bproc.list); tsk->bproc.master = 0; if (atomic_dec_and_test(&m->count)) kfree(m); /*ptrace_disable ? */ if (tsk->state < TASK_ZOMBIE) { /* Since we're trying to disappear silently, we should * reparent ourselves to init which will do the wait() on * us. */ ptrace_unlink(tsk); tsk->exit_signal = SIGCHLD; set_parents(tsk, child_reaper, child_reaper); } #if 0 /* Shed child processes - we just have them re-select parents. If * this is being called from release() we shouldn't have any * children... */ while (!list_empty(&tsk->children)) { struct task_struct *child; child = list_entry(tsk->children.next, struct task_struct, sibling); if (!BPROC_ISMASQ(child) || child->bproc.master != m) printk(KERN_ERR "bproc: masq_remove_proc: child isn't in my" " process space!\n"); masq_select_parents(child->bproc.master, child); if (child->parent == tsk || child->real_parent == tsk) { printk(KERN_CRIT "bproc: masq: child is still mine! me=%d child=%d\n", tsk->pid, child->pid); } } while (!list_empty(&tsk->ptrace_children)) { struct task_struct *child; child = list_entry(tsk->ptrace_children.next, struct task_struct, ptrace_list); if (!BPROC_ISMASQ(child) || child->bproc.master != m) printk(KERN_ERR "bproc: masq_remove_proc: child isn't in my" " process space!\n"); masq_select_parents(child->bproc.master, child); if (child->parent == tsk || child->real_parent == tsk) { printk(KERN_CRIT "bproc: masq: child is still mine! me=%d child=%d\n", tsk->pid, child->pid); } } #endif }