cirron 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +31 -1
- data/cirron.gemspec +2 -1
- data/lib/cirron.rb +1 -0
- data/lib/injector.rb +64 -0
- metadata +25 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28bb8894ef6331fcd6bae4aa768a71ce98fbf29b3870c83ec215c81dea120dd2
|
4
|
+
data.tar.gz: 54c4983a926fc03bfda415ef785b5ce0046c3a410ad92526c0ed9b8c98be4de8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a46bd52674c2dd8886521d6c90d93defbbcca383aaf5a685330e75e784060ee4dbeaa5c08f5b8e459950e9b1ba7f53c64e28565a174cb0601dae6ce3c6ba7d4
|
7
|
+
data.tar.gz: b058dab6e5657950507ad766dea5b6edfaa74107656a08cfcd38bc1e48a867f83966cbdc462484e982c42f827b941bf27f15cf290f2396be9036b1302911a7b8
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ It can also trace syscalls using +strace+, Linux only!
|
|
24
24
|
Hello
|
25
25
|
=> Counter(time_enabled_ns: 110260, instruction_count: 15406, branch_misses: 525, page_faults: 0)
|
26
26
|
|
27
|
-
=== Syscalls
|
27
|
+
=== Tracing Syscalls
|
28
28
|
|
29
29
|
$ sudo irb
|
30
30
|
irb> require 'cirron'
|
@@ -38,6 +38,36 @@ It can also trace syscalls using +strace+, Linux only!
|
|
38
38
|
irb> File.write("/tmp/trace", Cirron::to_tef(trace))
|
39
39
|
=> 267
|
40
40
|
|
41
|
+
=== Tampering with Syscalls
|
42
|
+
|
43
|
+
Available tampering actions are:
|
44
|
+
error: Inject a fault with the specified errno.
|
45
|
+
retval: Inject a success with the specified return value.
|
46
|
+
signal: Deliver the specified signal on syscall entry.
|
47
|
+
delay_enter: Delay syscall entry by the specified time.
|
48
|
+
delay_exit: Delay syscall exit by the specified time.
|
49
|
+
poke_enter: Modify memory at argN on syscall entry.
|
50
|
+
poke_exit: Modify memory at argN on syscall exit.
|
51
|
+
syscall: Inject a different syscall instead.
|
52
|
+
|
53
|
+
The when argument can be used to specify when to perform the tampering.
|
54
|
+
|
55
|
+
See the Tampering section of the [strace manual page](https://man7.org/linux/man-pages/man1/strace.1.html) for more detailed explanaition of the arguments.
|
56
|
+
|
57
|
+
```
|
58
|
+
$ sudo irb
|
59
|
+
irb> require 'cirron'
|
60
|
+
|
61
|
+
irb> injector = Cirron.injector
|
62
|
+
irb> injector.inject("openat", "error", "ENOSPC")
|
63
|
+
irb> injector.inject("openat", "delay_enter", "1s", when_condition="2+2")
|
64
|
+
irb> injector.run do
|
65
|
+
irb> # Open now fails with "No space left on device" and every
|
66
|
+
irb> # other call to `openat` will be delayed by 1s.
|
67
|
+
irb> File.open("test.txt", "w")
|
68
|
+
irb> end
|
69
|
+
```
|
70
|
+
|
41
71
|
== Additional Information
|
42
72
|
|
43
73
|
For more detailed information, please visit the project's GitHub page: https://github.com/s7nfo/Cirron
|
data/cirron.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'pathname'
|
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = "cirron"
|
9
|
-
spec.version = "0.
|
9
|
+
spec.version = "0.4.0"
|
10
10
|
spec.authors = ["Matt Stuchlik"]
|
11
11
|
spec.email = ["matej.stuchlik@gmail.com"]
|
12
12
|
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
"lib/cirronlib.cpp",
|
26
26
|
"lib/collector.rb",
|
27
27
|
"lib/tracer.rb",
|
28
|
+
"lib/injector.rb",
|
28
29
|
"README.md",
|
29
30
|
"LICENSE",
|
30
31
|
"cirron.gemspec"
|
data/lib/cirron.rb
CHANGED
data/lib/injector.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'open3'
|
3
|
+
|
4
|
+
Rule = Struct.new(:syscall, :action, :value, :when)
|
5
|
+
|
6
|
+
module Cirron
|
7
|
+
class Injector
|
8
|
+
VALID_ACTIONS = [
|
9
|
+
'error', 'retval', 'signal', 'syscall', 'delay_enter', 'delay_exit',
|
10
|
+
'poke_enter', 'poke_exit', 'when'
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@rules = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def inject(syscall, action, value, when_condition = nil)
|
18
|
+
unless VALID_ACTIONS.include?(action)
|
19
|
+
raise ArgumentError, "Invalid action: #{action}. Valid actions are: #{VALID_ACTIONS.join(', ')}"
|
20
|
+
end
|
21
|
+
|
22
|
+
@rules << Rule.new(syscall, action, value, when_condition)
|
23
|
+
end
|
24
|
+
|
25
|
+
def run(timeout = 10)
|
26
|
+
trace_file = Tempfile.new('cirron_inject')
|
27
|
+
trace_file_path = trace_file.path
|
28
|
+
trace_file.close
|
29
|
+
trace_file.unlink
|
30
|
+
parent_pid = Process.pid
|
31
|
+
|
32
|
+
cmd = ["strace", "--quiet=attach,exit", "-f", "-o", trace_file_path, "-p", parent_pid.to_s]
|
33
|
+
|
34
|
+
@rules.each do |rule|
|
35
|
+
inject_arg = "inject=#{rule.syscall}:#{rule.action}=#{rule.value}"
|
36
|
+
inject_arg += ":when=#{rule.when}" if rule.when
|
37
|
+
cmd.concat(["-e", inject_arg])
|
38
|
+
end
|
39
|
+
|
40
|
+
strace_proc = spawn(*cmd, :out => "/dev/null", :err => "/dev/null")
|
41
|
+
|
42
|
+
begin
|
43
|
+
deadline = Time.now + timeout
|
44
|
+
until File.exist?(trace_file_path)
|
45
|
+
if Time.now > deadline
|
46
|
+
raise Timeout::Error, "Failed to start strace within #{timeout}s."
|
47
|
+
end
|
48
|
+
sleep 0.1
|
49
|
+
end
|
50
|
+
|
51
|
+
sleep 0.1
|
52
|
+
|
53
|
+
yield if block_given?
|
54
|
+
ensure
|
55
|
+
Process.kill('INT', strace_proc) rescue nil
|
56
|
+
Process.wait(strace_proc) rescue nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.injector
|
62
|
+
Injector.new
|
63
|
+
end
|
64
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cirron
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Stuchlik
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: "= Cirron\n\nCirron measures a piece of Ruby code and reports back several
|
14
14
|
performance counters: \nCPU instruction count, branch misses, page faults and time
|
@@ -18,14 +18,28 @@ description: "= Cirron\n\nCirron measures a piece of Ruby code and reports back
|
|
18
18
|
Usage\n\n=== Performance Counters\n $ sudo irb\n irb(main):001> require 'cirron'\n
|
19
19
|
\ => true\n irb(main):002* c = Cirron::collector do\n irb(main):003* puts \"Hello\"\n
|
20
20
|
\ irb(main):004> end\n Hello\n => Counter(time_enabled_ns: 110260, instruction_count:
|
21
|
-
15406, branch_misses: 525, page_faults: 0)\n\n=== Syscalls\n\n $ sudo irb\n
|
22
|
-
require 'cirron'\n => true\n irb> trace = Cirron::tracer do\n irb> #
|
23
|
-
here\n irb> puts \"Hello\"\n irb> end\n => [#<Syscall:0x00007c6c1a4b3608
|
24
|
-
[{iov_base=\\\"Hello\\\", iov_len=5}, {iov_base=\\\"\\\\n\\\", iov_len=1}],
|
25
|
-
@duration=\"0.000201\", @name=\"writev\", @pid=\"2261962\", @retval=\"6\",
|
26
|
-
\
|
27
|
-
Cirron::to_tef(trace))\n => 267\n\n
|
28
|
-
|
21
|
+
15406, branch_misses: 525, page_faults: 0)\n\n=== Tracing Syscalls\n\n $ sudo irb\n
|
22
|
+
\ irb> require 'cirron'\n => true\n irb> trace = Cirron::tracer do\n irb> #
|
23
|
+
Your code here\n irb> puts \"Hello\"\n irb> end\n => [#<Syscall:0x00007c6c1a4b3608
|
24
|
+
@args=\"1, [{iov_base=\\\"Hello\\\", iov_len=5}, {iov_base=\\\"\\\\n\\\", iov_len=1}],
|
25
|
+
2\", @duration=\"0.000201\", @name=\"writev\", @pid=\"2261962\", @retval=\"6\",
|
26
|
+
@timestamp=\"1720285300.334976\">]\n # Save the trace for ingesting to Perfetto\n
|
27
|
+
\ irb> File.write(\"/tmp/trace\", Cirron::to_tef(trace))\n => 267\n\n=== Tampering
|
28
|
+
with Syscalls\n\nAvailable tampering actions are:\nerror: Inject a fault with the
|
29
|
+
specified errno.\nretval: Inject a success with the specified return value.\nsignal:
|
30
|
+
Deliver the specified signal on syscall entry.\ndelay_enter: Delay syscall entry
|
31
|
+
by the specified time.\ndelay_exit: Delay syscall exit by the specified time.\npoke_enter:
|
32
|
+
Modify memory at argN on syscall entry.\npoke_exit: Modify memory at argN on syscall
|
33
|
+
exit.\nsyscall: Inject a different syscall instead.\n\nThe when argument can be
|
34
|
+
used to specify when to perform the tampering.\n\nSee the Tampering section of the
|
35
|
+
[strace manual page](https://man7.org/linux/man-pages/man1/strace.1.html) for more
|
36
|
+
detailed explanaition of the arguments.\n\n```\n$ sudo irb\nirb> require 'cirron'\n\nirb>
|
37
|
+
injector = Cirron.injector\nirb> injector.inject(\"openat\", \"error\", \"ENOSPC\")\nirb>
|
38
|
+
injector.inject(\"openat\", \"delay_enter\", \"1s\", when_condition=\"2+2\")\nirb>
|
39
|
+
injector.run do\nirb> # Open now fails with \"No space left on device\" and
|
40
|
+
every\nirb> # other call to `openat` will be delayed by 1s.\nirb> File.open(\"test.txt\",
|
41
|
+
\"w\")\nirb> end\n```\n\n== Additional Information\n\nFor more detailed information,
|
42
|
+
please visit the project's GitHub page: https://github.com/s7nfo/Cirron"
|
29
43
|
email:
|
30
44
|
- matej.stuchlik@gmail.com
|
31
45
|
executables: []
|
@@ -39,6 +53,7 @@ files:
|
|
39
53
|
- lib/cirron.rb
|
40
54
|
- lib/cirronlib.cpp
|
41
55
|
- lib/collector.rb
|
56
|
+
- lib/injector.rb
|
42
57
|
- lib/tracer.rb
|
43
58
|
homepage: https://github.com/s7nfo/Cirron
|
44
59
|
licenses:
|