fche changed the topic of #systemtap to: http://sourceware.org/systemtap; email systemtap@sourceware.org if answers here not timely, conversations may be logged
orivej has quit [Ping timeout: 252 seconds]
hpt has joined #systemtap
orivej has joined #systemtap
_whitelogger has joined #systemtap
nkambo has joined #systemtap
gila has joined #systemtap
sanoj has joined #systemtap
MaartenK has joined #systemtap
<MaartenK> hi all
<MaartenK> is it possible to use systemtap to modify the output of getdents for a single user and a single process?
hpt has quit [Quit: Lost terminal]
gila has quit [Quit: My Mac Pro has gone to sleep. ZZZzzz…]
sanoj has quit [Ping timeout: 246 seconds]
gila has joined #systemtap
orivej has quit [Ping timeout: 268 seconds]
<MaartenK> hmm, getting closer
<MaartenK> I have this simple handler now:
<MaartenK> probe syscall.getdents {
<MaartenK> if (execname() == "ls") {
<MaartenK> }
<MaartenK> printf("%s\n", d_name(dirp_uaddr));
<MaartenK> }
<MaartenK> and I would like to get the directory name
<MaartenK> but I am getting a "ERROR: kernel string copy fault
<MaartenK> "
<MaartenK> can anyone point me in the right direction?
<MaartenK> i would like to get the path of the directlry (like "/something" on which the getdents call is performed
<MaartenK> within the source code I see that dirp_uaddr is defined as $dirent, so I expect that the d_name call should return what I need
<MaartenK> but it does not...
gila has quit [Quit: My Mac Pro has gone to sleep. ZZZzzz…]
nkambo has quit [Ping timeout: 240 seconds]
orivej has joined #systemtap
<fche> d_name is for use on kernel-memory-resident dirent structures; these are syscalls passing user-space copies
<fche> ^Maa
<fche> ^MaartenK
<fche> Pretty-printing $dirp$$ might work just to see what's inside
<fche> you may be able to modify contents with set_user_* (& $dirp->field) kindof thing
<fche> or trap readdir(3) in glibc with user-space probes; then there's only one address space to worry about
orivej has quit [Ping timeout: 248 seconds]
<MaartenK> fche: cool, thanks :)
<MaartenK> I got the path by running fullpath_struct_file(task_current(), task_fd_lookup(task_current(), fd) now
<MaartenK> but it feels a little bit dirty :)
<fche> that's a good way too
<fche> a feeling of dirtiness is natural when one's performing live vivisection on running software
<MaartenK> fair point
<MaartenK> just one more question regarding the set_user_* command, I am trying to update the d_ino long in the dirent struct like this: set_user_long(&(direnttofix["pointer"]->d_ino), 4);
<MaartenK> where direnttofix["pointer"] ccntains the pointer to the struct
<MaartenK> which results in the following error:
<MaartenK> semantic error: unknown type in dereference: operator '&' at fixlicenses.stp:12:17
<MaartenK> source: set_user_long(&(direnttofix["pointer"]->d_ino), 4);
<MaartenK> am I missing something there?
<fche> you'd have to @cast() that pointer to a struct*
<fche> ie @cast(direnttofix[tid() or whatever], "dirent") -> d_ino
<MaartenK> ok, so the end result should be this: set_user_long((@cast(direnttofix["pointer"], "linux_dirent")->d_ino), 4); ?
<MaartenK> hmm, that actually runs, but gives me an ERROR: user long copy fault at 0x0000000000060001
<MaartenK> when the call is made
<fche> that tells me the direnttofix[...] value was not right?
<fche> what is the value of that direnttofix["pointer"] expression?
<MaartenK> running it now, at this moment the value is 11500176
<fche> where did the value come from? that too looks kind of low for a normal heap or stack address
<MaartenK> i created it with the following line direnttofix["pointer"] = pointer_arg(2);
<MaartenK> where the second argument is the linux_dirent struct of the getdents call (see https://linux.die.net/man/2/getdents64)
<fche> that looks ok, but you may need asmlinkage()
<fche> and at the site where you -read- direnttofix["pointer"], you may need to check that a value has been set
<fche> since reading a variable such as an array slot that wasn't set results in a zero in systemtap
<fche> btw why direnttofix["pointer"] vs. a plain scalar direnttofix?
<fche> or indexed by tid(), in case of multiple threads doing this concurrently?
<MaartenK> that makes more sense, fixing that
<MaartenK> i see that the value returned by pointer_arg(2) is actually identical to dirp_uaddr, avariable made available by syscall.getdents
<fche> yup
<fche> that's on purpose - we try to make the parameters accessible with a more human name
<MaartenK> that is indeed much easier to read
<MaartenK> I guess I can skip the asmlinkage part in that case, as I am no longer using pointer_arg
<fche> yup
<MaartenK> hmm, this is weird
<MaartenK> my ls -i is showing / to have an inode value of 2, however, this line: printf("%i\n", @cast(direnttofix[tid()], "linux_dirent")->d_ino); gives me a value of 393217
<MaartenK> I would have expected those to be the same
<fche> could try printf($cast(direnttofix[tid()],"linux_dirent")$) to pretty-print the lot just to see
<MaartenK> parse error: expected literal string
<MaartenK> saw: identifier '$cast' at fixlicenses.stp:13:10
<MaartenK> source: printf($cast(direnttofix[tid()],"linux_dirent")$)
<fche> sorry $ @cast(...)
<fche> and a $ at the end
<fche> or ... geez I should try things before I say ... try @cast(foo) $
<MaartenK> don't worry, I appreciate your help and time
<MaartenK> hmm, that is not working either
<MaartenK> parse error: expected literal string
<MaartenK> saw: operator '@cast' at fixlicenses.stp:13:10
<MaartenK> source: printf(@cast(direnttofix[tid()],"linux_dirent")$)
<MaartenK> not sure if it matters, but I am running version systemtap-3.1-4.el7_4.x86_64
<fche> printf("%s", @cast(....)$ )
<fche> heh, operating on holiday vapours
<fche> it's as though there's a lot less oxygen around here
<MaartenK> I am getting {.d_ino=393217, .d_off=480086981411533459, .d_reclen=24, .d_name=[...]} as output now
<fche> that doesn't look entirely wrong, but not entirely right either :)
<fche> if you add another $ after the first $, you'll probably get d_name printed too
<MaartenK> {.d_ino=393217, .d_off=480086981411533459, .d_reclen=24, .d_name="home"}
<MaartenK> *blink*
<fche> progress of a sort!
<MaartenK> \o/
<MaartenK> even thoug I am more confused now, as the output for d_name should not be "home" and the inode on which home resides is also 2
<fche> try /bin/stat / /home
<fche> compare
<MaartenK> they are both indicating inode 2 as location (which makes sense as / and /home are both lvm partitions)
<MaartenK> File: ‘/’
<MaartenK> Size: 4096 Blocks: 8 IO Block: 4096 directory
<MaartenK> Device: fd00h/64768d Inode: 2 Links: 21
<MaartenK> and
<MaartenK> File: ‘/home’
<MaartenK> Size: 4096 Blocks: 8 IO Block: 4096 directory
<MaartenK> Device: fd04h/64772d Inode: 2 Links: 14
<MaartenK> I am going home, it is 17:20 and even though I am not that much away from sea level the amount of oxygen in my brain seems to be way to low
<fche> haha ditto
<MaartenK> fche: thank you once more for your time and input
<fche> good evening!
<fche> my pleasure
orivej has joined #systemtap
orivej has quit [Ping timeout: 255 seconds]
orivej has joined #systemtap
tonyj has quit [Remote host closed the connection]
fche has quit [Quit: Leaving]