Bug#855869: dsniff: segfaults on portmapper messages

James Cowgill jcowgill at debian.org
Wed Feb 22 16:40:06 UTC 2017


Package: dsniff
Version: 2.4b1+debian-23
Severity: important

Hi,

dsniff segfaults when receiving any RPC portmapper messages.

To generate such messages, I used:
rpcinfo -l <hostname of server with NFS running> 100021 4

But I expect any rpcinfo -l command will cause this to happen.

> Program received signal SIGSEGV, Segmentation fault.
> __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:294
> 294     ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
> (gdb) bt full
> #0  __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:294
> No locals.
> #1  0x00007ffff655ce24 in _IO_new_file_xsputn (f=0x7fffffffe0f0, data=0x555555797bd4, n=140737326206416) at fileops.c:1327
>         s = 0x555555797bd4 ""
>         to_do = 140737326206416
>         n = 140737326206416
>         data = 0x555555797bd4
>         f = 0x7fffffffe0f0
>         s = 0x555555797bd4 ""
>         to_do = 140737326206416
> #2  0x000055555555983e in rpc_decode (buf=buf at entry=0x555555797bd0 "6]T\275", len=88, len at entry=92, msg=msg at entry=0x7fffffffe1c0) at ./rpc.c:129
>         xdrs = {x_op = (unknown: 4136102144), x_ops = 0x7ffff687f440 <_IO_file_jumps>, x_public = 0x7ffff68835a3 <_IO_2_1_stderr_+131> "\n",
>           x_private = 0x7ffff655bb32 <new_do_write+98> "H\205\300H\211\305\017\267\273\200", x_base = 0x2525252525252525 <error: Cannot access memory at address 0x2525252525252525>, x_handy = 1}
>         fraghdr = <optimized out>
>         p = 0x555555797bd4 ""
>         tmp = <optimized out>
>         stat = 0
>         tmplen = <optimized out>
> #3  0x000055555555ec71 in decode_portmap (buf=0x555555797bd0 "6]T\275", len=92, obuf=<optimized out>, olen=<optimized out>) at ./decode_portmap.c:35
>         xdrs = {x_op = (unknown: 4294959712), x_ops = 0x7fffffffe1a0, x_public = 0x6f00000063 <error: Cannot access memory at address 0x6f00000063>,
>           x_private = 0x6f <error: Cannot access memory at address 0x6f>, x_base = 0x5555555617df "portmap", x_handy = 1}
>         msg = {rm_xid = 0, rm_direction = CALL, ru = {RM_cmb = {cb_rpcvers = 0, cb_prog = 0, cb_vers = 0, cb_proc = 0, cb_cred = {oa_flavor = 0, oa_base = 0x0, oa_length = 0}, cb_verf = {oa_flavor = 0,
>                 oa_base = 0x0, oa_length = 0}}, RM_rmb = {rp_stat = MSG_ACCEPTED, ru = {RP_ar = {ar_verf = {oa_flavor = 0, oa_base = 0x0, oa_length = 0}, ar_stat = SUCCESS, ru = {AR_versions = {low = 0,
>                       high = 0}, AR_results = {where = 0x0, proc = 0x0}}}, RP_dr = {rj_stat = RPC_MISMATCH, ru = {RJ_versions = {low = 0, high = 0}, RJ_why = AUTH_OK}}}}}}
>         pm = <optimized out>
>         pmap = {pm_prog = 93824994606032, pm_vers = 140737326678332, pm_prot = 64, pm_port = 206158430232}
>         xm = <optimized out>
>         hdrlen = <optimized out>
> #4  0x000055555555a524 in trigger_tcp_half (addr=addr at entry=0x7ffff7fa0010, hs=hs at entry=0x7ffff7fa0088, t=0x55555577f470 <tcp_triggers+656>) at ./trigger.c:377
>         buf = 0x555555797bd0 "6]T\275"
>         len = 92
> #5  0x000055555555afaa in trigger_tcp (ts=0x7ffff7fa0010, conn_save=<optimized out>) at ./trigger.c:430
>         tr = <optimized out>
> #6  0x00007ffff77a7f68 in process_tcp () from /usr/lib/libnids.so.1.21
> No symbol table info available.
> #7  0x00007ffff77a5f35 in ?? () from /usr/lib/libnids.so.1.21
> No symbol table info available.
> #8  0x00007ffff77a60ae in ?? () from /usr/lib/libnids.so.1.21
> No symbol table info available.
> #9  0x00007ffff77a621b in nids_pcap_handler () from /usr/lib/libnids.so.1.21
> No symbol table info available.
> #10 0x00007ffff7565646 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
> No symbol table info available.
> #11 0x00007ffff75662d7 in ?? () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
> No symbol table info available.
> #12 0x00007ffff756e26d in pcap_loop () from /usr/lib/x86_64-linux-gnu/libpcap.so.0.8
> No symbol table info available.
> #13 0x00007ffff77a58f6 in nids_run () from /usr/lib/libnids.so.1.21
> No symbol table info available.
> #14 0x0000555555556dc3 in main (argc=<optimized out>, argv=<optimized out>) at ./dsniff.c:269
>         services = 0x555555561958 "/usr/share/dsniff/dsniff.services"
>         savefile = 0x0
>         triggers = 0x0
>         c = <optimized out>

A few things I notice looking at rpc_decode...

> int
> rpc_decode(u_char *buf, int len, struct rpc_msg *msg)
> {
[...]
> 	/* Decode RPC message. */
> 	memset(msg, 0, sizeof(*msg));
> 	
> 	if (ntohl(((struct rpc_msg *)buf)->rm_direction) == CALL) {

This:
- Almost certainly breaks the strict aliasing rule and is thus undefined
behavior.
- Will fail on 64-bit systems since struct rpc_msg::xid is 64-bits, but
the RPC xid field in buf is only 32-bits.
- I expect the check for REPLY below fails on big-endian systems.

> 		xdrmem_create(&xdrs, buf, len, XDR_DECODE);
> 		
> 		if (!xdr_callmsg(&xdrs, msg)) {
> 			xdr_destroy(&xdrs);
> 			return (0);
> 		}
> 	}
> 	else if (ntohl(((struct rpc_msg *)buf)->rm_direction) == REPLY) {
> 		msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
> 		xdrmem_create(&xdrs, buf, len, XDR_DECODE);
> 		
> 		if (!xdr_replymsg(&xdrs, msg)) {
> 			xdr_destroy(&xdrs);
> 			return (0);
> 		}
> 	}
> 	stat = xdr_getpos(&xdrs);
> 	xdr_destroy(&xdrs);

Both these calls try to read / free garbage memory if both if statements
above fail.

Thanks,
James

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.alioth.debian.org/pipermail/pkg-security-team/attachments/20170222/dea0fe92/attachment.sig>


More information about the Pkg-security-team mailing list