| Summary: | killall(1) limited to 16 character process names by procfs(5) | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | m.seaman <m.seaman> | ||||
| Component: | bin | Assignee: | freebsd-bugs (Nobody) <bugs> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | ||||||
| Priority: | Normal | ||||||
| Version: | Unspecified | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
On Wed, 15 Dec 1999 15:48:18 GMT, m.seaman@inpharmatica.co.uk wrote: > killall(1) reads procfs /proc/${pid}/status entries to find > the process names the user wants to kill. Can we get the process names anywhere else? Ciao, Sheldon. Sheldon Hearn wrote:
>
> On Wed, 15 Dec 1999 15:48:18 GMT, m.seaman@inpharmatica.co.uk wrote:
>
> > killall(1) reads procfs /proc/${pid}/status entries to find
> > the process names the user wants to kill.
>
> Can we get the process names anywhere else?
Hmmm... The only other prospect in /proc is the 'cmdline' entry, but that has
the same 16 character limitation as the status entry.
st-pancras:/tmp:% ./12345678901234567 &
[1] 79007
st-pancras:/tmp:% cd /proc/79007
st-pancras:/proc/79007:% cat cmdline
1234567890123456st-pancras:/proc/79007:%
Failing that, we could parse the output of /bin/ps -ax --- easily doable from
perl, but dependent on processes not mangling argv[0] in unforeseen ways (ps
-axc has the same 16 character limitation as above).
Otherwise, we'd be looking at reading kvm the way ps(1) does, which is
not much fun from perl: it would probably be necessary to implement a
FreeBSD::KVM module using the perl '.xs' code thingy to generate an interface
to the kvm functions. Plus we would have to use suidperl to run the script
setgid to kmem, which doesn't strike me as particularly desirable.
Hmmm... here's a patch to killall(1) to use ps(1) output as well as reading
/proc: ps(1) output is used if the given program-name-to-kill is longer than
16 characters, or a match could not otherwise be made, to distinguish between
similarly named processes around 16 characters long. eg:
st-pancras:~:% /tmp/1234567890123456 &
[1] 79288
st-pancras:~:% /tmp/12345678901234567 &
[2] 79289
st-pancras:~:% ./killall.pl -v 12345678901234567
kill -TERM 79289
[2] - Terminated /tmp/12345678901234567
st-pancras:~:% ./killall.pl -v 1234567890123456
kill -TERM 79288
[1] + Terminated /tmp/1234567890123456
diff -u killall.pl.orig killall.pl
--- killall.pl.orig Tue Aug 31 10:08:27 1999
+++ killall.pl Fri Dec 17 15:19:39 1999
@@ -30,11 +30,13 @@
$ENV{'PATH'} = '/bin:/usr/bin'; # security
+$pscmd = '/bin/ps -ax'; # list all processes
$procfs = '/proc';
$signal = 'SIGTERM'; # default signal for kill
$debug = 0;
$match = 0; # 0 match exactly program name
$show = 0; # do nothings
+%procs = (); # Lookup processes by PID
# see /sys/miscfs/procfs/procfs_status.c
$PROC_NAME = 0;
@@ -68,6 +70,23 @@
undef %pidu;
undef %thiskill;
+open(PS, "$pscmd|") || die "$pscmd $!\n";
+while (<PS>) {
+ my ($pid, $proc);
+ chomp;
+
+ # Processes can alter their argv[0], which will be reflected in
+ # ps(1) output, so this is by no means reliable. Typically login
+ # shells will have `-' pre-pended. System processes like swapper
+ # are usually in (brackets) and then there's sendmail and nfsd that
+ # use argv[0] for status messages.
+
+ if (($pid, $proc) = m/^\s*(\d+)\s+\S+\s+\S+\s+\S+\s+(\S+)/) {
+ ($procs{$pid} = $proc) =~ s@.*/@@; # Strip any leading path
+ }
+}
+close(PS);
+
foreach (sort{$a <=> $b} grep(/^[0-9]/, readdir(PROCFS))) {
$status = "$procfs/$_/status";
$pid = $_;
@@ -85,8 +104,12 @@
($programMatch = $program) =~ s/(\W)/\\$1/g if $match;
# match program name
- if ($proc[$PROC_NAME] eq $program ||
- ($match && $proc[$PROC_NAME] =~ /$programMatch/i)) {
+ if ( (length $program <= 16 &&
+ ($proc[$PROC_NAME] eq $program ||
+ ($match && $proc[$PROC_NAME] =~ /$programMatch/i))) ||
+ (defined $procs{$pid} &&
+ ($procs{$pid} eq $program ||
+ ($match && $procs{$pid} =~ /$programMatch/i)))) {
# id test
if ($proc[$PROC_EUID] eq $id || # effective uid
--
Certe, Toto, sentio nos in Kansate non iam adesse.
Dr. Matthew Seaman, Inpharmatica Ltd, 60 Charlotte St, London, W1P 2AX
Tel: +44 171 631 4644 x229 Fax: +44 171 631 4844
Since killall(1) has recently transmogrified into a C program, I guess this PR might be closable. However, the same bug still seems to be present: st-pancras:/tmp:# uname -a FreeBSD st-pancras.inpharmatica.co.uk 4.1.1-STABLE FreeBSD 4.1.1-STABLE #0: Tue Sep 26 12:32:33 BST 2000 root@st-pancras.inpharmatica.co.uk:/export/i386/obj/export/src/sys/ST-PANCRAS i386 st-pancras:/tmp:# file /usr/bin/killall /usr/bin/killall: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), dynamically linked, stripped st-pancras:/tmp:# ./123456789012345 & [1] 249 st-pancras:/tmp:# ./1234567890123456 & [2] 250 st-pancras:/tmp:# ./12345678901234567 & [3] 251 st-pancras:/tmp:# head /proc/{249,250,251}/status ==> /proc/249/status <== 123456789012345 249 227 249 227 5,0 ctty 969973928,166376 0,0 0,6293 nanslp 0 0 0,0,0,2,3,4,5,20,31,994,998 - ==> /proc/250/status <== 1234567890123456 250 227 250 227 5,0 ctty 969973930,750074 0,0 0,6484 nanslp 0 0 0,0,0,2,3,4,5,20,31,994,998 - ==> /proc/251/status <== 1234567890123456 251 227 251 227 5,0 ctty 969973934,657696 0,0 0,6582 nanslp 0 0 0,0,0,2,3,4,5,20,31,994,998 - st-pancras:/tmp:# killall 12345678901234567 No matching processes were found st-pancras:/tmp:# killall 1234567890123456 [3] - Terminated ./12345678901234567 [2] - Terminated ./1234567890123456 Cheers, Matthew -- Certe, Toto, sentio nos in Kansate non iam adesse. Dr. Matthew Seaman, Inpharmatica Ltd, 60 Charlotte St, London, W1T 2NU Tel: +44 20 7631 4644 x229 Fax: +44 20 7631 4844 State Changed From-To: open->closed killall doesn't use procfs anymore. |
killall(1) reads procfs /proc/${pid}/status entries to find the process names the user wants to kill. However, only the first 16 (MAXCOMLEN from /usr/include/sys/param.h) characters of the process name are available. Trying naively to killall(1) a process with a longer name is guarranteed to fail: instead the supplied name should be truncated to the first 16 characters. I'm not convinced that modifying procfs() to fix this somewhat obscure case is really going to be worthwhile. This should certainly be documented though. How-To-Repeat: b0:/tmp:% cat foo.c #include <unistd.h> int main (int argc, char *argv[]) { sleep(600); } b0:/tmp:% cc -o 1234567890123 foo.c b0:/tmp:% cp 1234567890123{,4} b0:/tmp:% cp 1234567890123{,45} b0:/tmp:% cp 1234567890123{,456} b0:/tmp:% cp 1234567890123{,4567} b0:/tmp:% ./12345678901234 & [4] 63828 b0:/tmp:% ./12345678901235 & [5] 63829 b0:/tmp:% ./123456789012345 & [6] 63830 b0:/tmp:% ./1234567890123456 & [7] 63831 b0:/tmp:% ./12345678901234567 & [8] 63832 b0:/tmp:% head /proc/{63826,63828,63830,63831,63832}/status ==> /proc/63826/status <== 1234567890123 63826 63513 63826 63513 5,2 ctty 945270683,3518 0,1030 0,6184 nanslp 1000 1000 1000,1000,1000,0,999,1018,994,993,997 ==> /proc/63828/status <== 12345678901234 63828 63513 63828 63513 5,2 ctty 945270704,936540 0,909 0,6369 nanslp 1000 1000 1000,1000,1000,0,999,1018,994,993,997 ==> /proc/63830/status <== 123456789012345 63830 63513 63830 63513 5,2 ctty 945270715,716412 0,3262 0,4349 nanslp 1000 1000 1000,1000,1000,0,999,1018,994,993,997 ==> /proc/63831/status <== 1234567890123456 63831 63513 63831 63513 5,2 ctty 945270719,857664 0,1879 0,5639 nanslp 1000 1000 1000,1000,1000,0,999,1018,994,993,997 ==> /proc/63832/status <== 1234567890123456 63832 63513 63832 63513 5,2 ctty 945270723,443053 0,2114 0,5287 nanslp 1000 1000 1000,1000,1000,0,999,1018,994,993,997 b0:/tmp:% killall 12345678901234567 No processes matching ``12345678901234567''