summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2009-09-16 22:32:28 -0400
committerFrank Ch. Eigler <fche@elastic.org>2009-09-16 22:37:24 -0400
commit6ecd877049008c5abe9c6720ea8fc64732f47eb5 (patch)
tree407a536c1271b8e5757899e461c481e599266d67
parent6846cfc8a5cdb24fccb19037b27a180d2300ee09 (diff)
downloadsystemtap-steved-6ecd877049008c5abe9c6720ea8fc64732f47eb5.tar.gz
systemtap-steved-6ecd877049008c5abe9c6720ea8fc64732f47eb5.tar.xz
systemtap-steved-6ecd877049008c5abe9c6720ea8fc64732f47eb5.zip
PR10650: markup some unprivileged-safe tapset functions
Add /* unprivileged */ to a variety of tapset embedded-c functions, together with uid-assertion-checking code as needed. This is only an initial set, and may need to grow or shrink after further testing. Prototyped-By: Dave Brolley <brolley@redhat.com> * runtime/runtime.h (is_myproc, assert_is_myproc): New macros. * runtime/addr-map.c (lookup_bad_addr): Reject if !is_myproc in unprivileged mode. * runtime/print.c (_stp_print_kernel_info): Add unprivileged mode info. * tapset/DEVGUIDE: Document /* pure */ and /* unprivileged */. * tapset/*.stp: Add /* unprivileged */ here and there, in questionable cases along with an assert_is_myproc().
-rw-r--r--runtime/addr-map.c4
-rw-r--r--runtime/print.c12
-rw-r--r--runtime/runtime.h28
-rw-r--r--tapset/DEVGUIDE17
-rw-r--r--tapset/context.stp46
-rw-r--r--tapset/conversions.stp50
-rw-r--r--tapset/string.stp20
-rw-r--r--tapset/timestamp_gtod.stp2
-rw-r--r--tapset/ucontext-symbols.stp6
-rw-r--r--tapset/ucontext-unwind.stp6
-rw-r--r--tapset/utrace.stp27
11 files changed, 155 insertions, 63 deletions
diff --git a/runtime/addr-map.c b/runtime/addr-map.c
index a9aa8d88..35de7a64 100644
--- a/runtime/addr-map.c
+++ b/runtime/addr-map.c
@@ -115,6 +115,10 @@ lookup_bad_addr(unsigned long addr, size_t size)
return 1;
#ifndef STP_PRIVILEGED
+ /* Unprivileged users must not access memory while the context
+ does not refer to their own process. */
+ if (! is_myproc ())
+ return 1;
/* Unprivileged users must not access kernel space memory. */
if (addr + size > TASK_SIZE)
return 1;
diff --git a/runtime/print.c b/runtime/print.c
index 945f7a72..335403fb 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -225,7 +225,11 @@ static void _stp_print_kernel_info(char *vstr, int ctx, int num_probes)
#ifdef DEBUG_MEM
"+alloc"
#endif
- ", probes: %d\n",
+ ", probes: %d"
+#ifndef STP_PRIVILEGED
+ ", unpriv-uid: %d"
+#endif
+ "\n",
THIS_MODULE->name,
vstr,
#ifndef STAPCONF_GRSECURITY
@@ -242,7 +246,11 @@ static void _stp_print_kernel_info(char *vstr, int ctx, int num_probes)
#ifdef DEBUG_MEM
_stp_allocated_memory - _stp_allocated_net_memory,
#endif
- num_probes);
+ num_probes
+#ifndef STP_PRIVILEGED
+ , _stp_uid
+#endif
+ );
}
/** @} */
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 064ded7b..7087d435 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -54,6 +54,32 @@ static void _stp_warn (const char *fmt, ...) __attribute__ ((format (printf, 1,
static void _stp_exit(void);
+
+
+/* unprivileged user support */
+
+#ifdef STAPCONF_TASK_UID
+#define STP_CURRENT_EUID (current->euid)
+#else
+#define STP_CURRENT_EUID (task_euid(current))
+#endif
+
+#define is_myproc() (STP_CURRENT_EUID == _stp_uid)
+
+#ifndef STP_PRIVILEGED
+#define assert_is_myproc() do { \
+ if (! is_myproc()) { \
+ snprintf (CONTEXT->error_buffer, MAXSTRINGLEN, "semi-privileged tapset function called without is_myproc checking for pid %d (euid %d)", \
+ current->tgid, STP_CURRENT_EUID); \
+ CONTEXT->last_error = CONTEXT->error_buffer; \
+ goto out; \
+ } } while (0)
+#else
+#define assert_is_myproc() do {} while (0)
+#endif
+
+
+
#include "debug.h"
/* atomic globals */
@@ -106,6 +132,8 @@ static struct
#endif
#include "addr-map.c"
+
+
/* Support functions for int64_t module parameters. */
static int param_set_int64_t(const char *val, struct kernel_param *kp)
{
diff --git a/tapset/DEVGUIDE b/tapset/DEVGUIDE
index 693521a8..5d7c8658 100644
--- a/tapset/DEVGUIDE
+++ b/tapset/DEVGUIDE
@@ -244,6 +244,23 @@ potentially be invalid. If you're not sure, err on the side of caution.
The cost of using kread() is small compared to the cost of your tapset
inadvertently crashing a system!
+Add the string
+ /* pure */
+into the body of the embedded-C function if it has no side-effects
+such as changing external state, so that systemtap could elide
+(optimize away) a call to the function if its results are unused.
+
+Add the string
+ /* unprivileged */
+into the body of the embedded-C function, only if it is safe for use
+by unprivileged users. In general, this requires the function to be
+absolutely robust with respect to its inputs, and expose/modify no
+information except that belonging to the user's own processes.
+(The assert_is_myproc() macro may help enforce this.) Roughly
+speaking, it should only perform operations that the same user
+could already do from ordinary userspace interfaces.
+
+
Review & Submission
-------------------
All new tapsets and major changes should be reviewed "early and often"
diff --git a/tapset/context.stp b/tapset/context.stp
index 21af79b4..226e3ee5 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -34,28 +34,28 @@ function print_regs () %{
/**
* sfunction execname - Returns the execname of a target process (or group of processes).
*/
-function execname:string () %{ /* pure */
+function execname:string () %{ /* pure */ /* unprivileged */
strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN);
%}
/**
* sfunction pid - Returns the ID of a target process.
*/
-function pid:long () %{ /* pure */
+function pid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = current->tgid;
%}
/**
* sfunction tid - Returns the thread ID of a target process.
*/
-function tid:long () %{ /* pure */
+function tid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = current->pid;
%}
/**
* sfunction ppid - Returns the process ID of a target process's parent process.
*/
-function ppid:long () %{ /* pure */
+function ppid:long () %{ /* pure */ /* unprivileged */
#if defined(STAPCONF_REAL_PARENT)
THIS->__retvalue = current->real_parent->tgid;
#else
@@ -66,7 +66,7 @@ function ppid:long () %{ /* pure */
/**
* sfunction pgrp - Returns the process group ID of the current process.
*/
-function pgrp:long () %{ /* pure */
+function pgrp:long () %{ /* pure */ /* unprivileged */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
struct signal_struct *ss = kread( &(current->signal) );
THIS->__retvalue = kread ( &(ss->pgrp) );
@@ -82,7 +82,7 @@ function pgrp:long () %{ /* pure */
* The session ID of a process is the process group ID of the session
* leader. Session ID is stored in the signal_struct since Kernel 2.6.0.
*/
-function sid:long () %{ /* pure */
+function sid:long () %{ /* pure */ /* unprivileged */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
struct signal_struct *ss = kread( &(current->signal) );
THIS->__retvalue = kread ( &(ss->session) );
@@ -95,7 +95,7 @@ function sid:long () %{ /* pure */
/**
* sfunction pexecname - Returns the execname of a target process's parent process.
*/
-function pexecname:string () %{ /* pure */
+function pexecname:string () %{ /* pure */ /* unprivileged */
#if defined(STAPCONF_REAL_PARENT)
strlcpy (THIS->__retvalue, current->real_parent->comm, MAXSTRINGLEN);
#else
@@ -106,7 +106,7 @@ function pexecname:string () %{ /* pure */
/**
* sfunction gid - Returns the group ID of a target process.
*/
-function gid:long () %{ /* pure */
+function gid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->gid;
#else
@@ -117,7 +117,7 @@ function gid:long () %{ /* pure */
/**
* sfunction egid - Returns the effective gid of a target process.
*/
-function egid:long () %{ /* pure */
+function egid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->egid;
#else
@@ -128,7 +128,7 @@ function egid:long () %{ /* pure */
/**
* sfunction uid - Returns the user ID of a target process.
*/
-function uid:long () %{ /* pure */
+function uid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->uid;
#else
@@ -139,7 +139,7 @@ function uid:long () %{ /* pure */
/**
* sfunction euid - Return the effective uid of a target process.
*/
-function euid:long () %{ /* pure */
+function euid:long () %{ /* pure */ /* unprivileged */
#ifdef STAPCONF_TASK_UID
THIS->__retvalue = current->euid;
#else
@@ -147,19 +147,18 @@ function euid:long () %{ /* pure */
#endif
%}
+
/**
* sfunction is_myproc - Determines if the current probe point has occurred in the user's own process.
*
* Return 1 if the current probe point has occurred in the user's own process.
*/
function is_myproc:long () %{ /* pure */ /* unprivileged */
-#ifdef STAPCONF_TASK_UID
- THIS->__retvalue = (current->euid == _stp_uid);
-#else
- THIS->__retvalue = (task_euid(current) == _stp_uid);
-#endif
+ THIS->__retvalue = is_myproc();
%}
+
+
// cpuid() is not documented
function cpuid:long () %{ /* pure */
THIS->__retvalue = smp_processor_id();
@@ -168,7 +167,7 @@ function cpuid:long () %{ /* pure */
/**
* sfunction cpu - Returns the current cpu number.
*/
-function cpu:long () %{ /* pure */
+function cpu:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = smp_processor_id();
%}
@@ -178,7 +177,7 @@ function cpu:long () %{ /* pure */
* Context:
* The current probe point.
*/
-function pp:string () %{ /* pure */
+function pp:string () %{ /* pure */ /* unprivileged */
strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN);
%}
@@ -190,7 +189,7 @@ function pp:string () %{ /* pure */
* For example, <command>registers_valid()</command> returns 0
* when called from a begin or end probe.
*/
-function registers_valid:long () %{ /* pure */
+function registers_valid:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = (CONTEXT->regs != NULL);
%}
@@ -199,7 +198,7 @@ function registers_valid:long () %{ /* pure */
*
* Return 1 if the probe point occurred in user-mode.
*/
-function user_mode:long () %{ /* pure */ /* currently a user-mode address? */
+function user_mode:long () %{ /* pure */ /* unprivileged */
if (CONTEXT->regs) {
#if defined(__i386__) || defined(__x86_64__)
THIS->__retvalue = (uint64_t) user_mode_vm (CONTEXT->regs);
@@ -227,7 +226,7 @@ function is_return:long () %{ /* pure */
/**
* sfunction target - Return the process ID of the target process.
*/
-function target:long () %{ /* pure */
+function target:long () %{ /* pure */ /* unprivileged */
THIS->__retvalue = _stp_target;
%}
@@ -238,7 +237,7 @@ function target:long () %{ /* pure */
/// <remark>FIXME: need description.</remark>
/// </para>
///</formalpara>
-function module_name:string () %{ /* pure */
+function module_name:string () %{ /* pure */ /* unprivileged */
strlcpy(THIS->__retvalue, THIS_MODULE->name, MAXSTRINGLEN);
%}
@@ -290,8 +289,9 @@ function stack_unused:long () %{ /* pure */
* with usymname() or symdata(). Often the task will be in the VDSO
* where it entered the kernel. FIXME - need VDSO tracking support #10080.
*/
-function uaddr:long () %{ /* pure */
+function uaddr:long () %{ /* pure */ /* unprivileged */
int64_t addr = 0;
+ assert_is_myproc();
if (current->mm)
{
struct pt_regs *uregs;
diff --git a/tapset/conversions.stp b/tapset/conversions.stp
index fdf00bd3..a218025b 100644
--- a/tapset/conversions.stp
+++ b/tapset/conversions.stp
@@ -1,5 +1,5 @@
// conversions tapset
-// Copyright (C) 2005-2008 Red Hat Inc.
+// Copyright (C) 2005-2009 Red Hat Inc.
// Copyright (C) 2007 Intel Corporation.
//
// This file is part of systemtap, and is free software. You can
@@ -79,15 +79,18 @@ deref_fault: /* branched to from kread() */
function user_string:string (addr:long) { return user_string2 (addr, "<unknown>") }
-function user_string2:string (addr:long, err_msg:string) %{ /* pure */
+function user_string2:string (addr:long, err_msg:string) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (_stp_strncpy_from_user (THIS->__retvalue,
(const char __user*) (uintptr_t) THIS->addr,
MAXSTRINGLEN) < 0)
strlcpy (THIS->__retvalue, THIS->err_msg, MAXSTRINGLEN);
%}
-function user_string_warn:string (addr:long) %{ /* pure */
- long rc = _stp_strncpy_from_user (THIS->__retvalue,
+function user_string_warn:string (addr:long) %{ /* pure */ /* unprivileged */
+ long rc;
+ assert_is_myproc();
+ rc = _stp_strncpy_from_user (THIS->__retvalue,
(const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN);
if (rc < 0) {
// NB: using error_buffer to get local space for the warning, but we're
@@ -100,7 +103,8 @@ function user_string_warn:string (addr:long) %{ /* pure */
}
%}
-function user_string_quoted:string (addr:long) %{ /* pure */
+function user_string_quoted:string (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (THIS->addr == 0)
strlcpy (THIS->__retvalue, "NULL", MAXSTRINGLEN);
else
@@ -113,8 +117,9 @@ function user_string_n:string (addr:long, n:long) {
return user_string_n2(addr, n, "<unknown>")
}
-function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */
+function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ /* unprivileged */
long len = THIS->n + 1;
+ assert_is_myproc();
len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len;
if (_stp_strncpy_from_user(THIS->__retvalue,
(char __user *) (uintptr_t) THIS->addr,
@@ -124,10 +129,11 @@ function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */
THIS->__retvalue[len - 1] = '\0';
%}
-function user_string_n_warn:string (addr:long, n:long) %{ /* pure */
+function user_string_n_warn:string (addr:long, n:long) %{ /* pure */ /* unprivileged */
long len = THIS->n + 1;
long rc;
+ assert_is_myproc();
len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len;
rc = _stp_strncpy_from_user(THIS->__retvalue,
(char __user *) (uintptr_t) THIS->addr, len);
@@ -143,8 +149,10 @@ function user_string_n_warn:string (addr:long, n:long) %{ /* pure */
THIS->__retvalue[len - 1] = '\0';
%}
-function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */
- long len = THIS->n + 1;
+function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ /* unprivileged */
+ long len;
+ assert_is_myproc();
+ len = THIS->n + 1;
if (THIS->addr == 0)
strlcpy(THIS->__retvalue, "NULL", MAXSTRINGLEN);
else
@@ -155,7 +163,8 @@ function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */
// When userspace data is not accessible, the following functions return 0
-function user_short:long (addr:long) %{ /* pure */
+function user_short:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) {
@@ -164,7 +173,8 @@ fault:
}
%}
-function user_short_warn:long (addr:long) %{ /* pure */
+function user_short_warn:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) {
@@ -176,7 +186,8 @@ fault:
}
%}
-function user_int:long (addr:long) %{ /* pure */
+function user_int:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) {
@@ -185,7 +196,8 @@ fault:
}
%}
-function user_int_warn:long (addr:long) %{ /* pure */
+function user_int_warn:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) {
@@ -197,7 +209,8 @@ fault:
}
%}
-function user_long:long (addr:long) %{ /* pure */
+function user_long:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) {
@@ -206,7 +219,8 @@ fault:
}
%}
-function user_long_warn:long (addr:long) %{ /* pure */
+function user_long_warn:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) {
@@ -218,7 +232,8 @@ fault:
}
%}
-function user_char:long (addr:long) %{ /* pure */
+function user_char:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) {
@@ -227,7 +242,8 @@ fault:
}
%}
-function user_char_warn:long (addr:long) %{ /* pure */
+function user_char_warn:long (addr:long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char)))
goto fault;
if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) {
diff --git a/tapset/string.stp b/tapset/string.stp
index 4b0a2a0d..92750b6b 100644
--- a/tapset/string.stp
+++ b/tapset/string.stp
@@ -8,7 +8,7 @@
* @param s string
* @return Returns the length of the string.
*/
-function strlen:long(s:string) %{ /* pure */
+function strlen:long(s:string) %{ /* pure */ /* unprivileged */
THIS->__retvalue = strlen(THIS->s);
%}
@@ -19,7 +19,7 @@ function strlen:long(s:string) %{ /* pure */
* @param length Length of string to return.
* @return Returns the substring.
*/
-function substr:string(str:string,start:long, length:long) %{ /* pure */
+function substr:string(str:string,start:long, length:long) %{ /* pure */ /* unprivileged */
int length = THIS->length >= MAXSTRINGLEN ? MAXSTRINGLEN : THIS->length + 1;
if (THIS->start >= 0 && length > 0 && THIS->start < strlen(THIS->str))
strlcpy(THIS->__retvalue, THIS->str + THIS->start, length);
@@ -31,7 +31,7 @@ function substr:string(str:string,start:long, length:long) %{ /* pure */
* @param pos the given position. 0 = start of the string
* @return Returns the char in given position of string.
*/
-function stringat:long(str:string, pos:long) %{ /* pure */
+function stringat:long(str:string, pos:long) %{ /* pure */ /* unprivileged */
if (THIS->pos >= 0 && THIS->pos < strlen(THIS->str))
THIS->__retvalue = THIS->str[THIS->pos];
else
@@ -44,7 +44,7 @@ function stringat:long(str:string, pos:long) %{ /* pure */
* @param s2 string
* @return Returns 1 if s2 is in s1. Otherwise 0.
*/
-function isinstr:long(s1:string,s2:string) %{ /* pure */
+function isinstr:long(s1:string,s2:string) %{ /* pure */ /* unprivileged */
if (strstr(THIS->s1,THIS->s2) != NULL)
THIS->__retvalue = 1;
else
@@ -58,13 +58,13 @@ function isinstr:long(s1:string,s2:string) %{ /* pure */
* replaced by the corresponding escape sequence in the returned
* string.
*/
-function text_str:string(input:string)
-%{ /* pure */
+function text_str:string(input:string)
+%{ /* pure */ /* unprivileged */
_stp_text_str(THIS->__retvalue, THIS->input, 0, 0, 0);
%}
function text_strn:string(input:string, len:long, quoted:long)
-%{ /* pure */
+%{ /* pure */ /* unprivileged */
_stp_text_str(THIS->__retvalue, THIS->input, THIS->len, THIS->quoted, 0);
%}
@@ -77,7 +77,7 @@ function text_strn:string(input:string, len:long, quoted:long)
* delim Token delimiter. Set of characters that delimit the tokens.
*/
function tokenize:string(input:string, delim:string)
-%{ /* pure */
+%{ /* unprivileged */
static char str[MAXSTRINGLEN];
static char *str_start;
static char *str_end;
@@ -106,7 +106,7 @@ function tokenize:string(input:string, delim:string)
* @return Returns the parent string with substrings replaced. Else returns parent string.
*/
function str_replace:string (prnt_str:string, srch_str:string, rplc_str:string)
-%{
+%{ /* pure */ /* unprivileged */
char *ptr = THIS->prnt_str;
char *ptr_base = THIS->prnt_str;
int strlen_srch_str = strlen(THIS->srch_str);
@@ -135,7 +135,7 @@ function str_replace:string (prnt_str:string, srch_str:string, rplc_str:string)
* base The base to use
*/
function strtol:long(str:string, base:long)
-%{ /* pure */
+%{ /* pure */ /* unprivileged */
THIS->__retvalue = simple_strtol(THIS->str, NULL, THIS->base);
%}
diff --git a/tapset/timestamp_gtod.stp b/tapset/timestamp_gtod.stp
index b916a3b1..acf525f0 100644
--- a/tapset/timestamp_gtod.stp
+++ b/tapset/timestamp_gtod.stp
@@ -17,7 +17,7 @@
*
* Return the number of nanoseconds since the UNIX epoch.
*/
-function gettimeofday_ns:long () %{ /* pure */
+function gettimeofday_ns:long () %{ /* pure */ /* unprivileged */
/* NOTE: we can't use do_gettimeofday because we could be called from a
* context where xtime_lock is already held. See bug #2525. */
THIS->__retvalue = _stp_gettimeofday_ns();
diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp
index 7fed71d2..e884a36b 100644
--- a/tapset/ucontext-symbols.stp
+++ b/tapset/ucontext-symbols.stp
@@ -46,7 +46,8 @@ function usymname:string (addr: long) %{ /* pure */
* will be omitted and if the symbol name is unknown it will return the
* hex string for the given address.
*/
-function usymdata:string (addr: long) %{ /* pure */
+function usymdata:string (addr: long) %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
current, 1);
%}
@@ -63,9 +64,10 @@ function usymdata:string (addr: long) %{ /* pure */
* name of the function containing the address, and an estimate of
* its position within that function. Return nothing.
*/
-function print_ustack(stk:string) %{
+function print_ustack(stk:string) %{ /* pure */ /* unprivileged */
char *ptr = THIS->stk;
char *tok = strsep(&ptr, " ");
+ assert_is_myproc();
while (tok && *tok) {
_stp_print_char(' ');
_stp_usymbol_print (simple_strtol(tok, NULL, 16), current);
diff --git a/tapset/ucontext-unwind.stp b/tapset/ucontext-unwind.stp
index df275d4b..e1a8ade3 100644
--- a/tapset/ucontext-unwind.stp
+++ b/tapset/ucontext-unwind.stp
@@ -24,7 +24,8 @@
* Equivalent to <command>print_ustack(ubacktrace())</command>,
* except that deeper stack nesting may be supported. Return nothing.
*/
-function print_ubacktrace () %{
+function print_ubacktrace () %{ /* unprivileged */
+ assert_is_myproc();
if (CONTEXT->regs) {
_stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE,
current);
@@ -41,7 +42,8 @@ function print_ubacktrace () %{
* string length. Returns empty string when current probe point cannot
* determine user backtrace.
*/
-function ubacktrace:string () %{ /* pure */
+function ubacktrace:string () %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
if (CONTEXT->regs)
_stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN,
CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE,
diff --git a/tapset/utrace.stp b/tapset/utrace.stp
index 0d26ed5f..4f841b30 100644
--- a/tapset/utrace.stp
+++ b/tapset/utrace.stp
@@ -4,23 +4,38 @@
#include "syscall.h"
%}
-function _utrace_syscall_nr:long () %{ /* pure */
- THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs);
+function _utrace_syscall_nr:long () %{ /* pure */ /* unprivileged */
+ assert_is_myproc();
+ if (! CONTEXT->regs) {
+ CONTEXT->last_error = "invalid call without context registers";
+ } else {
+ THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs);
+ }
%}
-function _utrace_syscall_arg:long (n:long) %{ /* pure */
+function _utrace_syscall_arg:long (n:long) %{ /* pure */ /* unprivileged */
unsigned long arg = 0;
- syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg);
+ assert_is_myproc();
+ if (! CONTEXT->regs) {
+ CONTEXT->last_error = "invalid call without context registers";
+ } else {
+ syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg);
+ }
THIS->__retvalue = arg;
%}
-function _utrace_syscall_return:long () %{ /* pure */
+function _utrace_syscall_return:long () %{ /* pure */ /* unprivileged */
/*
* Here's the reason for the "unsigned long" cast. Since all
* values inside systemtap are 64-bit numbers, return values were
* getting sign extended. This caused return values to not match
* up with the same values passes as arguments.
*/
- THIS->__retvalue = (unsigned long)syscall_get_return_value(current,
+ assert_is_myproc();
+ if (! CONTEXT->regs) {
+ CONTEXT->last_error = "invalid call without context registers";
+ } else {
+ THIS->__retvalue = (unsigned long)syscall_get_return_value(current,
CONTEXT->regs);
+ }
%}