This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
[Bug tapsets/17920] File descriptor to pathname function
- From: "dsmith at redhat dot com" <sourceware-bugzilla at sourceware dot org>
- To: systemtap at sourceware dot org
- Date: Mon, 28 Sep 2015 20:33:10 +0000
- Subject: [Bug tapsets/17920] File descriptor to pathname function
- Auto-submitted: auto-generated
- References: <bug-17920-6586 at http dot sourceware dot org/bugzilla/>
https://sourceware.org/bugzilla/show_bug.cgi?id=17920
David Smith <dsmith at redhat dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |dsmith at redhat dot com
--- Comment #1 from David Smith <dsmith at redhat dot com> ---
I looked into this today. I'm not sure it is possible to do, at least cleanly.
For reference's sake, here's what I came up with. Note that this only works on
semi-recent kernels (I developed this on rawhide -
4.3.0-0.rc2.git1.1.fc24.x86_64) and isn't correct with respect to locking data
structures. See comments for details.
====
function task_fd_lookup:long(task:long, fd:long)
%{
struct task_struct *t = (struct task_struct *)(long)STAP_ARG_task;
unsigned int fd = (unsigned int)(unsigned long)STAP_ARG_fd;
struct files_struct *files = NULL;
struct file *file = NULL;
int put_task_struct_needed = 0;
/* Before using the task_struct pointer, make sure it is valid
* to read. */
(void)kderef_buffer(NULL, t, sizeof(struct task_struct));
get_task_struct(t);
put_task_struct_needed = 1;
// This is *wrong*. We should be calling get_files_struct()
// here, but it isn't exported. This means that we can't lock
// the files_struct. So, let's hope keeping the task_struct
// usage count increased is enough.
files = t->files;
if (files) {
/* Before using the files_struct pointer, make sure it is
* valid to read. */
(void)kderef_buffer(NULL, files, sizeof(struct files_struct));
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
spin_unlock(&files->file_lock);
}
if (file) {
// Sigh. This is really wrong also. We're returning a
// pointer which isn't locked or has had its usage
// count increased. There is nothing keeping this
// pointer valid until we use it later.
STAP_RETURN(file);
}
else {
STAP_ERROR ("cannot find file in task");
}
CATCH_DEREF_FAULT();
if (put_task_struct_needed)
put_task_struct(t);
%}
probe begin
{
file = task_fd_lookup(task_current(), 0)
println(fullpath_struct_path(&@cast(file, "file")->f_path))
exit()
}
====
Note that this code doesn't handle pipes, sockets, etc., but that is the least
of the worries about the above code.
Perhaps a better way of going here would be put a probe on vfs.open, vfs.write,
and vfs.read and if you aren't in your target process skip the probe. Something
like this:
====
probe vfs.read, vfs.write
{
if (pid() != target()) next
printf("%s: %s\n", name, fullpath_struct_path(&file->f_path))
}
probe vfs.open
{
if (pid() != target()) next
printf("%s: %s\n", name, pathname)
}
====
====
# stap ./file_monitor.stp -c "/bin/ls /dev/null"
/dev/null
vfs.open: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.read: /usr/bin/ls
vfs.open: /usr/lib64/ld-2.22.90.so
vfs.read: /usr/lib64/ld-2.22.90.so
vfs.read: /usr/lib64/ld-2.22.90.so
vfs.open: /etc/ld.so.cache
vfs.open: /usr/lib64/libselinux.so.1
vfs.read: /usr/lib64/libselinux.so.1
vfs.open: /usr/lib64/libcap.so.2.24
vfs.read: /usr/lib64/libcap.so.2.24
vfs.open: /usr/lib64/libc-2.22.90.so
vfs.read: /usr/lib64/libc-2.22.90.so
vfs.open: /usr/lib64/libpcre.so.1.2.5
vfs.read: /usr/lib64/libpcre.so.1.2.5
vfs.open: /usr/lib64/libdl-2.22.90.so
vfs.read: /usr/lib64/libdl-2.22.90.so
vfs.open: /usr/lib64/libattr.so.1.1.0
vfs.read: /usr/lib64/libattr.so.1.1.0
vfs.open: /usr/lib64/libpthread-2.22.90.so
vfs.read: /usr/lib64/libpthread-2.22.90.so
vfs.open: /usr/lib/locale/locale-archive
vfs.write: /dev/pts/2
====
--
You are receiving this mail because:
You are the assignee for the bug.