While ktrace'ing firefox, I managed to produce a ktrace.out file that
makes pledge(2) abort kdump:
$ kdump >/dev/null
Killed
$ dmesg | tail -1
kdump(24965): syscall 5
The problem is that the "rpath" request is dropped in kdump's second
pledge call. However, kdump's sockoptlevelname() formatter calls
getprotobynumber() which in turn tries to open /etc/protocols, and the
latter isn't among the exceptions for SYS_open in kern_pledge.c.
gdb and ktrace output are a bit further down.
I see two fixes for this (apart from dropping the call to
getprotobynumber):
1. drop the second pledge call from kdump, i.e., let it have "rpath"
throughout:
Index: usr.bin/kdump/kdump.c
===================================================================
RCS file: /var/cvs/src/usr.bin/kdump/kdump.c,v
retrieving revision 1.113
diff -u -p -r1.113 kdump.c
--- usr.bin/kdump/kdump.c 9 Oct 2015 01:37:08 -0000 1.113
+++ usr.bin/kdump/kdump.c 10 Oct 2015 07:25:33 -0000
@@ -250,9 +250,6 @@ main(int argc, char *argv[])
if (!freopen(tracefile, "r", stdin))
err(1, "%s", tracefile);
- if (pledge("stdio getpw", NULL) == -1)
- err(1, "pledge");
-
if (fread_tail(&ktr_header, sizeof(struct ktr_header), 1) == 0 ||
ktr_header.ktr_type != htobe32(KTR_START))
errx(1, "%s: not a dump", tracefile);
2. add an exception to pledge to allow reading from /etc/protocols. The
most simple-minded way would be this (if anything in this direction
is acceptable, it would probably be preferable to have a request to
allow access to the databases in netdb.h):
Index: sys/kern/kern_pledge.c
===================================================================
RCS file: /var/cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.4
diff -u -p -r1.4 kern_pledge.c
--- sys/kern/kern_pledge.c 9 Oct 2015 05:30:03 -0000 1.4
+++ sys/kern/kern_pledge.c 10 Oct 2015 06:07:42 -0000
@@ -567,6 +567,11 @@ pledge_namei(struct proc *p, char *origp
strcmp(path, "/etc/localtime") == 0)
return (0);
+ /* For {get,set}proto*() */
+ if ((p->p_pledgenote == TMN_RPATH) &&
+ strcmp(path, "/etc/protocols") == 0)
+ return (0);
+
/* /usr/share/nls/../libc.cat has to succeed for strerror(3). */
if ((p->p_pledgenote == TMN_RPATH) &&
strncmp(path, "/usr/share/nls/",
Following semarie@'s instructions from a few days ago, I added "abort"
requests to the two pledge calls in kdump.c and recompiled with
debugging symbols. Here's the backtrace:
$ ktrace -f kdump.trace /usr/obj/usr.bin/kdump/kdump >/dev/null
Abort trap (core dumped)
$ gdb -q /usr/obj/usr.bin/kdump/kdump kdump.core
Core was generated by `kdump'.
Program terminated with signal 6, Aborted.
Loaded symbols for /usr/obj/usr.bin/kdump/kdump
Reading symbols from /usr/lib/libc.so.83.0...done.
Loaded symbols for /usr/lib/libc.so.83.0
Reading symbols from /usr/libexec/ld.so...done.
Loaded symbols for /usr/libexec/ld.so
#0 0x00001fc0ecf76bea in open () at <stdin>:2
2 <stdin>: No such file or directory.
in <stdin>
(gdb) bt
#0 0x00001fc0ecf76bea in open () at <stdin>:2
#1 0x00001fc0ecfd36d2 in *_libc_fopen (file=0x1fc0ed0eed10 "/etc/protocols",
mode=Variable "mode" is not available.
) at /usr/src/lib/libc/stdio/fopen.c:54
#2 0x00001fc0ecf89e45 in *_libc_setprotoent_r (f=0, pd=0x1fc0ed416fa0) at
/usr/src/lib/libc/net/getprotoent.c:45
#3 0x00001fc0ecf807ee in *_libc_getprotobynumber_r (num=6, pe=0x1fc0ed40d7d0,
pd=0x1fc0ed416fa0)
at /usr/src/lib/libc/net/getproto.c:39
#4 0x00001fc0ecf80847 in getprotobynumber (num=Variable "num" is not available.
) at /usr/src/lib/libc/net/getproto.c:57
#5 0x00001fbe1930adf5 in sockoptlevelname (optname=1) at
/usr/src/usr.bin/kdump/kdump.c:1714
#6 0x00001fbe19308dd3 in ktrsyscall (ktr=0x1fc0cb23c000, ktrlen=48) at
/usr/src/usr.bin/kdump/kdump.c:973
#7 0x00001fbe193082f9 in main (argc=1, argv=0x7f7ffffe4908) at
/usr/src/usr.bin/kdump/kdump.c:288
Current language: auto; currently asm
(gdb)
and here's the tail of the output of
$ kdump -f kdump.trace
(...)
24076 kdump GIO fd 1 wrote 4096 bytes
"0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa628,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa508,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa4c8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa458,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa458,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa458,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa458,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa4c8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa4c8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa4c8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa378,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL
socket(AF_LOCAL,0x8001<SOCK_STREAM|SOCK_CLOEXEC>,0)
7792 firefox RET socket 4
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa378,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL connect(4,0x7f7fffffa4a0,106)
7792 firefox STRU struct sockaddr { AF_LOCAL, "/tmp/.X11-unix/X0" }
7792 firefox NAMI "/tmp/.X11-unix/X0"
7792 firefox RET connect -1 errno 2 No such file or directory
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL close(4)
7792 firefox RET close 0
7792 firefox CALL kbind(0x7f7fffffa3b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa338,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa138,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa0b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa0b8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa0f8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa0f8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa0f8,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL kbind(0x7f7fffffa138,0x18,0xcb4f1e3561aaf036)
7792 firefox RET kbind 0
7792 firefox CALL getpid()
7792 firefox RET getpid 7792/0x1e70
7792 firefox CALL clock_gettime(CLOCK_MONOTONIC,0x7f7fffff91b0)
7792 firefox STRU struct timespec { 4264<"Jan 1 02:11:04
1970">.475489185 }
7792 firefox RET clock_gettime 0
7792 firefox CALL stat(0x192050ea29e0,0x7f7fffff9130)
7792 firefox NAMI "/etc/resolv.conf"
7792 firefox STRU struct stat { dev=1054, ino=5065749,
mode=-rw-r--r-- , nlink=1, uid=0<"root">, gid=1000<"theo">, rd\
ev=20291402, atime=1444404456<"Oct 9 17:27:36 2015">.487754626,
mtime=1444404431<"Oct 9 17:27:11 2015">.737170355, ctim\
e=1444404431<"Oct 9 17:27:11 2015">.737170355, size=88, blocks=8,
blksize=32768, flags=0x0, gen=0x0 }
7792 firefox RET stat 0
7792 firefox CALL open(0x192050ea29e0,0x10000<O_RDONLY|O_CLOEXEC>)
7792 firefox NAMI "/etc/resolv.conf"
7792 firefox RET open 4
7792 firefox CALL fstat(4,0x7f7fffff8fd0)
7792 firefox STRU struct stat { dev=1054, ino=5065749,
mode=-rw-r--r-- , nlink=1, uid=0<"root">, gid=1000<"theo">, rd\
ev=20291402, atime=1444404456<"Oct 9 17:27:36 2015">.48775"
24076 kdump RET write 16384/0x4000
24076 kdump CALL kbind(0x7f7ffffe46e8,0x18,0x5e9e45632db196b5)
24076 kdump RET kbind 0
24076 kdump CALL open(0x1fc0ed0eed10,0x10000<O_RDONLY|O_CLOEXEC>)
24076 kdump NAMI "/etc/protocols"
24076 kdump PSIG SIGABRT SIG_DFL
24076 kdump NAMI "kdump.core"