ports/108085: port devel/py-freebsd: reference counting bug
Martin Kammerhofer
dada at pluto.tugraz.at
Thu Jan 18 13:20:17 UTC 2007
>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 at 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 at 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 at 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)
More information about the freebsd-ports-bugs
mailing list