Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Jan 2007 14:10:40 +0100
From:      Martin Kammerhofer <dada@pluto.tugraz.at>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   ports/108085: port devel/py-freebsd: reference counting bug
Message-ID:  <200701181310.l0IDAegR028055@pluto.tugraz.at>
Resent-Message-ID: <200701181320.l0IDKF2U025589@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         108085
>Category:       ports
>Synopsis:       port devel/py-freebsd: reference counting bug
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 18 13:20:15 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Martin Kammerhofer
>Release:        FreeBSD 6.2-PRERELEASE i386
>Organization:
>Environment:
System: FreeBSD Martin.liebt.Susi 6.2-PRERELEASE FreeBSD 6.2-PRERELEASE #2: Tue Dec 5 13:15:11 CET 2006 toor@Martin.liebt.Susi:/usr/src/sys/i386/compile/P2B-S i386
>Description:
Bug #1:
  The Python wrapper freebsd.setprogname passes a temporary C pointer
  to setprogname(3). Libc's setprogname stashes this pointer rather than
  a copy of the referenced string. Therefore when libc uses this pointer
  later on -- e.g. for error reporting or setproctitle(3) -- it points to
  arbitrary data inside the Python interpreter.
  This bug can be trivially fixed by proper reference counting.

Bug #2:
  The Python wrapper freebsd.setproctitle passes its raw string argument
  to setproctitle(3). This is a security risk whenever the string
  contains user-supplied data and well documented in the setproctitle(3)
  man page.

>How-To-Repeat:
# Bug #1:
martin@Martin:~/patches$ python2.4
Python 2.4.4 (#2, Nov 28 2006, 22:41:53) 
[GCC 3.4.6 [FreeBSD] 20060305] on freebsd6
Type "help", "copyright", "credits" or "license" for more information.
>Fix:
--- TUTORIAL.orig	Sun May  8 08:55:00 2005
+++ TUTORIAL	Sat Nov 25 18:06:41 2006
@@ -165,7 +165,7 @@
 'rumble'
 >>> setproctitle('py-freebsd testing session')
 >>> os.system('ps auxw|grep freebsd')
-perky 71593  0.0  0.8  6288 4176  p8  S+    2:10AM   0:00.16 global: py-freebsd testing session (python)
+perky 71593  0.0  0.8  6288 4176  p8  S+    2:10AM   0:00.16 rumble: py-freebsd testing session (python)
 
 
 ====
--- src/process.c.orig	Sun May  8 08:55:00 2005
+++ src/process.c	Sat Nov 25 18:12:52 2006
@@ -51,10 +51,19 @@
 static PyObject *
 PyFB_setprogname(PyObject *self, PyObject *args)
 {
-	char *progname;
+	const char	*progname;
+	static PyObject	*namestr = NULL;
 
 	if (!PyArg_ParseTuple(args, "s:setprogname", &progname))
 		return NULL;
+	/*
+	 * Setprogname(3) does not copy the string, it only stores the
+	 * string pointer. Make sure that the string object does not
+	 * get garbage collected and its memory reused!
+	 */
+	Py_XDECREF(namestr);	/* maybe free old progname */
+	PyArg_ParseTuple(args, "O", &namestr);
+	Py_INCREF(namestr);	/* keep new progname object */
 
 	setprogname(progname);
 	Py_RETURN_NONE;
@@ -64,16 +73,24 @@
 static char PyFB_setproctitle__doc__[] =
 "setproctitle(title):\n"
 "The setproctitle() library routine sets the process title that\n"
-"appears on the ps(1) command.";
+"appears on the ps(1) command. The progname and a colon are\n"
+"prepended automatically. This behaviour is suppressed when the\n"
+"title starts with a dash (-) character. Calling with a None\n"
+"argument restores a default process title.";
 
 static PyObject *
 PyFB_setproctitle(PyObject *self, PyObject *args)
 {
-	char *newtitle;
+	const char *newtitle;
 
-	if (!PyArg_ParseTuple(args, "s:setproctitle", &newtitle))
+	if (!PyArg_ParseTuple(args, "z:setproctitle", &newtitle))
 		return NULL;
 
-	setproctitle(newtitle);
+	if (newtitle == NULL)
+		setproctitle(NULL);
+	else if (*newtitle == '-')
+		setproctitle("-%s", newtitle+1);
+	else
+		setproctitle("%s", newtitle);
 	Py_RETURN_NONE;
 }
>Release-Note:
>Audit-Trail:
>Unformatted:
 >>> import freebsd, os, gc
 >>> progname = "Monty"
 >>> freebsd.setprogname(progname)
 >>> freebsd.getprogname()
 'Monty'
 >>> progname = "Nasty"
 >>> gc.collect()
 0
 >>> freebsd.getprogname()
 '<stdin>'
 >>> 
 
 # Bug #2:
 martin@Martin:~$ python2.4
 Python 2.4.4 (#2, Nov 28 2006, 22:41:53) 
 [GCC 3.4.6 [FreeBSD] 20060305] on freebsd6
 Type "help", "copyright", "credits" or "license" for more information.
 >>> import freebsd, os
 >>> freebsd.setproctitle("%d%d%d%d%d%d%d")
 >>> os.system("ps %d" % os.getpid())
   PID  TT  STAT      TIME COMMAND
  2171  p3  S+     0:00,23 python2.4: 838570953-1077971584134712879136162644136155948-10779715281351665100
 >>> freebsd.setproctitle("%s" * 99)
 Segmentation fault: 11 (core dumped)
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701181310.l0IDAegR028055>