233 lines
5.9 KiB
C
233 lines
5.9 KiB
C
/*
|
|
* Copyright (c) 2005-2010 Slide, Inc
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
* * Neither the name of the author nor the names of other
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <Python.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/errno.h>
|
|
|
|
static char module_doc[] =
|
|
"This module provides access to the Linux prctl system call\n\
|
|
";
|
|
|
|
static char prctl_doc[] =
|
|
"prctl(option, [value]) -> result\n\n\
|
|
When just the option value is provided return the current setting. Set\n\
|
|
the option to a new value if the optional value parameter is supplied.\n\n\
|
|
Valid Options:\n\n\
|
|
PDEATHSIG: Receive signal (as defined by value) on parent exit\n\
|
|
DUMPABLE: current->mm->dumpable\n\
|
|
UNALIGN: Unaligned access control bits (if meaningful) \n\
|
|
KEEPCAPS: Whether or not to drop capabilities on setuid() away\n\
|
|
from uid 0\n\
|
|
FPEMU: Floating-point emulation control bits (if meaningful)\n\
|
|
FPEXC: Floating-point exception mode (if meaningful)\n\
|
|
TIMING: Whether we use statistical process timing or accurate\n\
|
|
timestamp\n\
|
|
NAME: Process name\n\
|
|
ENDIAN: Process endianess\n\
|
|
";
|
|
|
|
static PyObject *ErrorObject;
|
|
|
|
struct table_entry {
|
|
char *name;
|
|
char *desc;
|
|
int get;
|
|
int set;
|
|
};
|
|
|
|
#define PR_PDEATHSIG 0
|
|
#define PR_DUMPABLE 1
|
|
#define PR_UNALIGN 2
|
|
#define PR_KEEPCAPS 3
|
|
#define PR_FPEMU 4
|
|
#define PR_FPEXC 5
|
|
#define PR_TIMING 6
|
|
#define PR_NAME 7
|
|
|
|
#define MIN_ENTRY PR_PDEATHSIG
|
|
#define MAX_ENTRY PR_NAME
|
|
|
|
#ifdef PR_GET_ENDIAN
|
|
#define PR_ENDIAN 8
|
|
#undef MAX_ENTRY
|
|
#define MAX_ENTRY PR_ENDIAN
|
|
#endif
|
|
|
|
#define MAX_LEN 1024 /* well more then maximum kernel size (TASK_COMM_LEN) */
|
|
|
|
static struct table_entry _option_table[] = {
|
|
{"PDEATHSIG", NULL, PR_GET_PDEATHSIG, PR_SET_PDEATHSIG},
|
|
{"DUMPABLE", NULL, PR_GET_DUMPABLE, PR_SET_DUMPABLE},
|
|
{"UNALIGN", NULL, PR_GET_UNALIGN, PR_SET_UNALIGN},
|
|
{"KEEPCAPS", NULL, PR_GET_KEEPCAPS, PR_SET_KEEPCAPS},
|
|
{"FPEMU", NULL, PR_GET_FPEMU, PR_SET_FPEMU},
|
|
{"FPEXC", NULL, PR_GET_FPEXC, PR_SET_FPEXC},
|
|
{"TIMING", NULL, PR_GET_TIMING, PR_SET_TIMING},
|
|
{"NAME", NULL, PR_GET_NAME, PR_SET_NAME},
|
|
#ifdef PR_ENDIAN
|
|
{"ENDIAN", NULL, PR_GET_ENDIAN, PR_SET_ENDIAN},
|
|
#endif
|
|
{NULL, NULL, 0, 0}
|
|
};
|
|
|
|
static PyObject *_set_prctl(int option, PyObject *value)
|
|
{
|
|
unsigned long arg;
|
|
int result;
|
|
|
|
switch (option) {
|
|
case PR_NAME:
|
|
if (PyString_Check(value)) {
|
|
arg = (unsigned long)PyString_AS_STRING(value);
|
|
break;
|
|
}
|
|
|
|
if (PyUnicode_Check(value)) {
|
|
value = PyUnicode_AsUTF8String(value);
|
|
arg = (unsigned long)PyString_AS_STRING(value);
|
|
|
|
Py_DECREF(value);
|
|
break;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "option/value type error");
|
|
return NULL;
|
|
default:
|
|
if (PyInt_Check(value)) {
|
|
arg = PyInt_AS_LONG(value);
|
|
break;
|
|
}
|
|
|
|
if (PyLong_Check(value)) {
|
|
arg = PyLong_AsLongLong(value);
|
|
break;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "option/value type error");
|
|
return NULL;
|
|
}
|
|
|
|
|
|
result = prctl(_option_table[option].set, arg);
|
|
if (result < 0) {
|
|
PyErr_SetFromErrno(ErrorObject);
|
|
return NULL;
|
|
}
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
static PyObject *_get_prctl(int option)
|
|
{
|
|
PyObject *output;
|
|
char arg[MAX_LEN];
|
|
int result;
|
|
|
|
memset(arg, 0, MAX_LEN);
|
|
|
|
result = prctl(_option_table[option].get, arg);
|
|
if (result < 0) {
|
|
PyErr_SetFromErrno(ErrorObject);
|
|
return NULL;
|
|
}
|
|
|
|
switch (option) {
|
|
case PR_PDEATHSIG:
|
|
output = PyInt_FromLong(*(int *)arg);
|
|
break;
|
|
case PR_NAME:
|
|
output = PyString_FromString(arg);
|
|
break;
|
|
default:
|
|
output = PyInt_FromLong(result);
|
|
break;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
static PyObject *py_prctl(PyObject *self, PyObject *args)
|
|
{
|
|
PyObject *value = NULL;
|
|
int option;
|
|
|
|
if (!PyArg_ParseTuple(args, "i|O", &option, &value))
|
|
return NULL;
|
|
|
|
if (option < MIN_ENTRY || option > MAX_ENTRY) {
|
|
PyErr_SetString(PyExc_ValueError, "invalid option");
|
|
return NULL;
|
|
}
|
|
|
|
if (value)
|
|
return _set_prctl(option, value);
|
|
else
|
|
return _get_prctl(option);
|
|
}
|
|
|
|
|
|
static PyMethodDef _prctl_methods[] = {
|
|
{"prctl", py_prctl, METH_VARARGS, prctl_doc},
|
|
{NULL, NULL, 0, NULL}
|
|
};
|
|
|
|
PyMODINIT_FUNC initprctl(void)
|
|
{
|
|
PyObject *module;
|
|
PyObject *dict;
|
|
int i = 0;
|
|
|
|
module = Py_InitModule3("prctl", _prctl_methods, module_doc);
|
|
if (!module)
|
|
return;
|
|
|
|
dict = PyModule_GetDict(module);
|
|
if (!dict)
|
|
return;
|
|
|
|
ErrorObject = PyErr_NewException("prctl.PrctlError", NULL, NULL);
|
|
PyDict_SetItemString(dict, "PrctlError", ErrorObject);
|
|
|
|
while (_option_table[i].name) {
|
|
PyModule_AddIntConstant(module, _option_table[i].name, i);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Local Variables:
|
|
* c-file-style: "linux"
|
|
* indent-tabs-mode: t
|
|
* End:
|
|
*/
|