samba_3_0 still segfaults upon trying to refresh view of prin ters: gdb bt

Esh, Andrew Andrew_Esh at adaptec.com
Thu Apr 10 15:49:09 GMT 2003


I just noticed a potential problem in tdb/tdbutil.c, tdb_pack. The primary
intent of tdb_pack is to pack and store values into a given buffer. The use
it is also being put to is to use a null buffer and zero size in order to
simply "measure" the storage which would be needed if a buffer were actually
supplied. The problem is, some of the code in tdb_pack could still do the
storage to the given buffer, even when it is only measuring. It seems to me
that if someone were to pass the right arguments to tdb_pack, they could
cause a segfault.

The specific problem is that the bufsize is assumed to be a positive
integer. If it starts at zero, as in a measurement call, it gets decremented
by the measurement of the first storage item. The second storage item starts
with bufsize less than zero. The code will continue to work until the
bufsize is decremented below MAXINT, at which point the storage code will
become active, and the null pointer will have values written to it.

This probably does not explain the bug begin described by Alex Deiter, since
the call that appears to have caused that problem only passes one storage
item.

Here's a suggestion: Don't store when bufsize is zero, and don't alter
bufsize if it's already zero.

(This code isn't tested.)

Index: tdbutil.c
===================================================================
RCS file: /cvsroot/samba/source/tdb/tdbutil.c,v
retrieving revision 1.50
diff -u -c -r1.50 tdbutil.c
cvs server: conflicting specifications of output style
*** tdbutil.c	14 Mar 2003 17:12:40 -0000	1.50
--- tdbutil.c	10 Apr 2003 15:47:57 -0000
***************
*** 406,452 ****
  		case 'b': /* unsigned 8-bit integer */
  			len = 1;
  			bt = (uint8)va_arg(ap, int);
! 			if (bufsize >= len)
  				SSVAL(buf, 0, bt);
  			break;
  		case 'w': /* unsigned 16-bit integer */
  			len = 2;
  			w = (uint16)va_arg(ap, int);
! 			if (bufsize >= len)
  				SSVAL(buf, 0, w);
  			break;
  		case 'd': /* signed 32-bit integer (standard int in most
systems) */
  			len = 4;
  			d = va_arg(ap, uint32);
! 			if (bufsize >= len)
  				SIVAL(buf, 0, d);
  			break;
  		case 'p': /* pointer */
  			len = 4;
  			p = va_arg(ap, void *);
  			d = p?1:0;
! 			if (bufsize >= len)
  				SIVAL(buf, 0, d);
  			break;
  		case 'P': /* null-terminated string */
  			s = va_arg(ap,char *);
  			w = strlen(s);
  			len = w + 1;
! 			if (bufsize >= len)
  				memcpy(buf, s, len);
  			break;
  		case 'f': /* null-terminated string */
  			s = va_arg(ap,char *);
  			w = strlen(s);
  			len = w + 1;
! 			if (bufsize >= len)
  				memcpy(buf, s, len);
  			break;
  		case 'B': /* fixed-length string */
  			i = va_arg(ap, int);
  			s = va_arg(ap, char *);
  			len = 4+i;
! 			if (bufsize >= len) {
  				SIVAL(buf, 0, i);
  				memcpy(buf+4, s, i);
  			}
--- 406,452 ----
  		case 'b': /* unsigned 8-bit integer */
  			len = 1;
  			bt = (uint8)va_arg(ap, int);
! 			if (bufsize && bufsize >= len)
  				SSVAL(buf, 0, bt);
  			break;
  		case 'w': /* unsigned 16-bit integer */
  			len = 2;
  			w = (uint16)va_arg(ap, int);
! 			if (bufsize && bufsize >= len)
  				SSVAL(buf, 0, w);
  			break;
  		case 'd': /* signed 32-bit integer (standard int in most
systems) */
  			len = 4;
  			d = va_arg(ap, uint32);
! 			if (bufsize && bufsize >= len)
  				SIVAL(buf, 0, d);
  			break;
  		case 'p': /* pointer */
  			len = 4;
  			p = va_arg(ap, void *);
  			d = p?1:0;
! 			if (bufsize && bufsize >= len)
  				SIVAL(buf, 0, d);
  			break;
  		case 'P': /* null-terminated string */
  			s = va_arg(ap,char *);
  			w = strlen(s);
  			len = w + 1;
! 			if (bufsize && bufsize >= len)
  				memcpy(buf, s, len);
  			break;
  		case 'f': /* null-terminated string */
  			s = va_arg(ap,char *);
  			w = strlen(s);
  			len = w + 1;
! 			if (bufsize && bufsize >= len)
  				memcpy(buf, s, len);
  			break;
  		case 'B': /* fixed-length string */
  			i = va_arg(ap, int);
  			s = va_arg(ap, char *);
  			len = 4+i;
! 			if (bufsize && bufsize >= len) {
  				SIVAL(buf, 0, i);
  				memcpy(buf+4, s, i);
  			}
***************
*** 459,465 ****
  		}
  
  		buf += len;
! 		bufsize -= len;
  	}
  
  	va_end(ap);
--- 459,468 ----
  		}
  
  		buf += len;
! 		if (bufsize)
! 		  bufsize -= len;
! 		if (bufsize < 0)
! 		  bufsize = 0;
  	}
  
  	va_end(ap);
-----Original Message-----
From: Esh, Andrew 
Sent: Thursday, April 10, 2003 10:09 AM
To: 'Alex Deiter'; samba-technical at lists.samba.org
Subject: RE: samba_3_0 still segfaults upon trying to refresh view of
printers: gdb bt


Make sure you have version 1.50 of tdb/tdbutil.c. Make clean and recompile.

The reason is: The tdb_pack function was modified on March 14th to do
estimates of the storage size which would be required for a given set of
arguments. The printing.c code in your stack dump is using tdb_pack in this
way at the line indicated. When I look at version 1.50 of tdbutil.c, the
line shown in your stack dump does not contain executable code. The printing
code is trying to use tdb_pack to measure the packed storage size of a
single local integer, which the correct tdb_pack code should easily be able
to do. This leads me to think that old tdbutil code was linked in, instead
of 3.0 HEAD code.

-----Original Message-----
From: Alex Deiter [mailto:tiamat at komi.mts.ru]
Sent: Thursday, April 10, 2003 1:38 AM
To: samba-technical at lists.samba.org
Subject: Re: samba_3_0 still segfaults upon trying to refresh view of
printers: gdb bt


Hello!

i build samba_3_0 (today cvs) and see segfaults upon trying to refresh view
of printer:

#0  0x284dc613 in kill () from /usr/lib/libc.so.5
(gdb) bt
#0  0x284dc613 in kill () from /usr/lib/libc.so.5
#1  0x2853fcac in abort () from /usr/lib/libc.so.5
#2  0x08175a92 in smb_panic () at lib/util.c:1431
#3  0x081663ec in fault_report (sig=11) at lib/fault.c:41
#4  0x08166436 in sig_fault (sig=11) at lib/fault.c:61
#5  <signal handler called>
#6  tdb_pack (buf=0x8318200 "", bufsize=-1077940832, fmt=0x0)
    at tdb/tdbutil.c:403
#7  0x08187e79 in store_queue_struct (pdb=0x0, pts=0xbfbfeda0)
    at printing/printing.c:858
#8  0x08188495 in print_queue_update (snum=9) at printing/printing.c:1071
#9  0x08189795 in print_queue_length (snum=9, pstatus=0xbfbff170)
    at printing/printing.c:1773
#10 0x08102b0f in construct_printer_info_2 (print_hnd=0x830c800,
    printer=0x828c100, snum=9) at rpc_server/srv_spoolss_nt.c:4141
#11 0x08103d53 in getprinter_level_2 (print_hnd=0x830c800, snum=9,
    buffer=0x8248ec0, offered=0, needed=0xbfbff334)
    at rpc_server/srv_spoolss_nt.c:4744
#12 0x08104110 in _spoolss_getprinter (p=0x830d000, q_u=0xbfbff340,
    r_u=0xbfbff330) at rpc_server/srv_spoolss_nt.c:4929
#13 0x080f9341 in api_spoolss_getprinter (p=0x830d000)
    at rpc_server/srv_spoolss.c:403
#14 0x081156cd in api_rpcTNP (p=0x830d000, rpc_name=0x82490d0 "spoolss",
---Type <return> to continue, or q <return> to quit---
    api_rpc_cmds=0x82c1800, n_cmds=51) at rpc_server/srv_pipe.c:1732
#15 0x0811535c in api_pipe_request (p=0x830d000) at
rpc_server/srv_pipe.c:1651
#16 0x0810f6c4 in process_request_pdu (p=0x830d000, rpc_in_p=0x0)
    at rpc_server/srv_pipe_hnd.c:669
#17 0x0810f89f in process_complete_pdu (p=0x830d000)
    at rpc_server/srv_pipe_hnd.c:741
#18 0x0810fb1a in process_incoming_data (p=0x830d000, data=0x8248dd0 " ",
n=40)
    at rpc_server/srv_pipe_hnd.c:837
#19 0x0810fcdd in write_to_internal_pipe (np_conn=0x830d000,
    data=0x8248dd0 " ", n=56) at rpc_server/srv_pipe_hnd.c:876
#20 0x0810fc5c in write_to_pipe (p=0x82c5a00, data=0x8248dc0 "\005", n=56)
    at rpc_server/srv_pipe_hnd.c:859
#21 0x08079d0b in api_fd_reply (conn=0x82c5600, vuid=100, outbuf=0x82ea000
"",
    setup=0x82c5a00, data=0x8248dc0 "\005", params=0x0, suwcnt=2, tdscnt=56,
    tpscnt=0, mdrcnt=1024, mprcnt=0) at smbd/ipc.c:298
#22 0x08079ee8 in named_pipe (conn=0x82c5600, vuid=100, outbuf=0x82ea000 "",
    name=0xbfbff756 "", setup=0x8249bf0, data=0x8248dc0 "\005", params=0x0,
    suwcnt=2, tdscnt=56, tpscnt=0, msrcnt=0, mdrcnt=1024, mprcnt=0)
    at smbd/ipc.c:342
#23 0x0807a837 in reply_trans (conn=0x82c5600, inbuf=0x82c9000 "",
    outbuf=0x82ea000 "", size=144, bufsize=131072) at smbd/ipc.c:532
#24 0x080aa957 in switch_message (type=37, inbuf=0x82c9000 "",
    outbuf=0x82ea000 "", size=144, bufsize=131072) at smbd/process.c:758
---Type <return> to continue, or q <return> to quit---
#25 0x080aa9e5 in construct_reply (inbuf=0x82c9000 "", outbuf=0x82ea000 "",
    size=144, bufsize=131072) at smbd/process.c:788
#26 0x080aacf2 in process_smb (inbuf=0x82c9000 "", outbuf=0x82ea000 "")
    at smbd/process.c:889
#27 0x080ab71f in smbd_process () at smbd/process.c:1306
#28 0x080707b9 in main (argc=2, argv=0xbfbffb20) at smbd/server.c:900
#29 0x0806eea5 in _start ()
(gdb)

Thanks!


More information about the samba-technical mailing list