From owner-freebsd-audit Mon Nov 26 8:34:54 2001 Delivered-To: freebsd-audit@freebsd.org Received: from bazooka.trit.org (bazooka.trit.org [63.198.170.138]) by hub.freebsd.org (Postfix) with ESMTP id 7443D37B419; Mon, 26 Nov 2001 08:34:45 -0800 (PST) Received: by bazooka.trit.org (Postfix, from userid 1000) id 24CC43EC8; Mon, 26 Nov 2001 16:34:45 +0000 (UTC) Received: from bazooka (localhost [127.0.0.1]) by bazooka.trit.org (Postfix) with ESMTP id 235173C12F; Mon, 26 Nov 2001 16:34:45 +0000 (UTC) To: audit@freebsd.org Cc: jhb@freebsd.org Subject: DDB 'kill' command Date: Mon, 26 Nov 2001 16:34:40 +0000 From: Dima Dorfman Message-Id: <20011126163445.24CC43EC8@bazooka.trit.org> Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG The attached patch implements a 'kill' command in DDB. Previously, it was possible to do `call psignal(xxx,yyy)` and have it DTRT. (This was very useful when you accidently got your system so deep in the hole that spawning kill(1) takes forever and even then possibly doesn't succeed.) However, psignal() doesn't respect locking by itself, so trying that now leads to all kinds of badness. This patch basically wraps the psignal() call in a 'kill' command that respects all necessary locks. Actually, it isn't very clear exactly which locks it should respect. The debugger is a special case in this way. This patch uses the PROC_TRYLOCK macro; if it fails, the command bails out. Thus, it can't use pfind()--the latter automatically does a PROC_LOCK--so it has to walk the allproc list manually. It does *not* attempt to get a shared lock on the allproc list. There is similar code in db_trace.c, and it doesn't call sx_slock(), either; I asked jhb about this a while ago, and all he said was that it is intentional. Please review. Thanks. Index: db_command.c =================================================================== RCS file: /ref/cvsf/src/sys/ddb/db_command.c,v retrieving revision 1.40 diff -u -r1.40 db_command.c --- db_command.c 2001/11/05 21:50:55 1.40 +++ db_command.c 2001/11/26 00:52:40 @@ -36,7 +36,11 @@ */ #include #include +#include +#include +#include #include +#include #include #include @@ -63,6 +67,7 @@ static db_cmdfcn_t db_fncall; static db_cmdfcn_t db_gdb; +static db_cmdfcn_t db_kill; static db_cmdfcn_t db_reset; /* XXX this is actually forward-static. */ @@ -418,6 +423,7 @@ { "ps", db_ps, 0, 0 }, { "gdb", db_gdb, 0, 0 }, { "reset", db_reset, 0, 0 }, + { "kill", db_kill, CS_OWN, 0 }, { (char *)0, } }; @@ -571,6 +577,59 @@ db_printf("Next trap will enter %s\n", boothowto & RB_GDB ? "GDB remote protocol mode" : "DDB debugger"); +} + +static void +db_kill(dummy1, dummy2, dummy3, dummy4) + db_expr_t dummy1; + boolean_t dummy2; + db_expr_t dummy3; + char * dummy4; +{ + db_expr_t old_radix, pid, sig; + struct proc *p; + +#define DB_ERROR(f) do { db_printf f; db_flush_lex(); goto out; } while (0) + + /* + * PIDs and signal numbers are typically represented in base + * 10, so make that the default here. It can, of course, be + * overridden by specifying a prefix. + */ + old_radix = db_radix; + db_radix = 10; + /* Retrieve arguments. */ + if (!db_expression(&sig)) + DB_ERROR(("Missing signal number\n")); + if (!db_expression(&pid)) + DB_ERROR(("Missing process ID\n")); + db_skip_to_eol(); + if (sig < 0 || sig > _SIG_MAXSIG) + DB_ERROR(("Signal number out of range\n")); + + /* + * Find the process in question. allproc_lock is not needed + * since we're in DDB. + */ + /* sx_slock(&allproc_lock); */ + LIST_FOREACH(p, &allproc, p_list) + if (p->p_pid == pid) + break; + /* sx_sunlock(&allproc_lock); */ + if (p == NULL) + DB_ERROR(("Can't find process with pid %d\n", pid)); + + /* If it's already locked, bail; otherwise, do the deed. */ + if (PROC_TRYLOCK(p) == 0) + DB_ERROR(("Can't lock process with pid %d\n", pid)); + else { + psignal(p, sig); + PROC_UNLOCK(p); + } + +out: + db_radix = old_radix; +#undef DB_ERROR } static void To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message