tls.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. package ebpftracer
  2. import (
  3. "bufio"
  4. "bytes"
  5. "debug/buildinfo"
  6. "debug/elf"
  7. "errors"
  8. "fmt"
  9. "os"
  10. "regexp"
  11. "strconv"
  12. "strings"
  13. "github.com/cilium/ebpf/link"
  14. "github.com/coroot/coroot-node-agent/ebpftracer/tracer"
  15. "github.com/coroot/coroot-node-agent/proc"
  16. . "github.com/coroot/coroot-node-agent/utils/modelse"
  17. klog "github.com/sirupsen/logrus"
  18. "golang.org/x/arch/arm64/arm64asm"
  19. "golang.org/x/arch/x86/x86asm"
  20. "golang.org/x/mod/semver"
  21. )
  22. const (
  23. minSupportedGoVersion = "v1.15.0"
  24. goTlsWriteSymbol = "crypto/tls.(*Conn).Write"
  25. goTlsReadSymbol = "crypto/tls.(*Conn).Read"
  26. goExecute = "runtime.execute"
  27. goNewproc1 = "runtime.newproc1"
  28. goRunqget = "runtime.runqget"
  29. goServeHTTP = "net/http.serverHandler.ServeHTTP"
  30. goTransport = "net/http.(*Transport).roundTrip"
  31. goGrpcServerHandleStream = "google.golang.org/grpc.(*Server).handleStream"
  32. goGrpcHttp2OperateHeader = "google.golang.org/grpc/internal/transport.(*http2Server).operateHeaders"
  33. goGrpcServerWritestatus = "google.golang.org/grpc/internal/transport.(*http2Server).WriteStatus"
  34. goGrpcClientConnInvoke = "google.golang.org/grpc.(*ClientConn).Invoke"
  35. goGrpcClientLoopyHeaderHandler = "google.golang.org/grpc/internal/transport.(*loopyWriter).headerHandler"
  36. goGrpcHttp2ClientNewStream = "google.golang.org/grpc/internal/transport.(*http2Client).NewStream"
  37. )
  38. var (
  39. opensslVersionRe = regexp.MustCompile(`OpenSSL\s(\d\.\d+\.\d+)`)
  40. )
  41. func (t *Tracer) AttachOpenSslUprobes(pid uint32) ([]link.Link, error) {
  42. if t.DisableL7Tracing() {
  43. return nil, nil
  44. }
  45. libPath, version := getSslLibPathAndVersion(pid)
  46. if libPath == "" || version == "" {
  47. return nil, nil
  48. }
  49. log := func(msg string, err error) {
  50. if err != nil {
  51. for _, s := range []string{"no such file or directory", "no such process", "permission denied"} {
  52. if strings.HasSuffix(err.Error(), s) {
  53. return
  54. }
  55. }
  56. klog.Errorf("pid=%d libssl_version=%s: %s: %s", pid, version, msg, err)
  57. return
  58. }
  59. klog.Infof("pid=%d libssl_version=%s: %s", pid, version, msg)
  60. }
  61. exe, err := link.OpenExecutable(libPath)
  62. if err != nil {
  63. log("failed to open executable", err)
  64. return nil, err
  65. }
  66. var links []link.Link
  67. writeEnter := "openssl_SSL_write_enter"
  68. readEnter := "openssl_SSL_read_enter"
  69. readExEnter := "openssl_SSL_read_ex_enter"
  70. readExit := "openssl_SSL_read_exit"
  71. switch {
  72. case semver.Compare(version, "v3.0.0") >= 0:
  73. writeEnter = "openssl_SSL_write_enter_v3_0"
  74. readEnter = "openssl_SSL_read_enter_v3_0"
  75. readExEnter = "openssl_SSL_read_ex_enter_v3_0"
  76. case semver.Compare(version, "v1.1.1") >= 0:
  77. writeEnter = "openssl_SSL_write_enter_v1_1_1"
  78. readEnter = "openssl_SSL_read_enter_v1_1_1"
  79. readExEnter = "openssl_SSL_read_ex_enter_v1_1_1"
  80. }
  81. type prog struct {
  82. symbol string
  83. uprobe string
  84. uretprobe string
  85. }
  86. progs := []prog{
  87. {symbol: "SSL_write", uprobe: writeEnter},
  88. {symbol: "SSL_read", uprobe: readEnter},
  89. {symbol: "SSL_read", uretprobe: readExit},
  90. }
  91. if semver.Compare(version, "v1.1.1") >= 0 {
  92. progs = append(progs, []prog{
  93. {symbol: "SSL_write_ex", uprobe: writeEnter},
  94. {symbol: "SSL_read_ex", uprobe: readExEnter},
  95. {symbol: "SSL_read_ex", uretprobe: readExit},
  96. }...)
  97. }
  98. for _, p := range progs {
  99. if p.uprobe != "" {
  100. l, err := exe.Uprobe(p.symbol, t.uprobes[p.uprobe], nil)
  101. klog.Infoln("fucktls crypto/tls uprobes attached", p.symbol)
  102. if err != nil {
  103. //log("failed to attach uprobe", err)
  104. klog.Infoln("fucktls crypto/tls uprobes attached error", p.symbol)
  105. return nil, err
  106. }
  107. links = append(links, l)
  108. }
  109. if p.uretprobe != "" {
  110. klog.Infoln("fucktls crypto/tls uprobes attached ret", p.symbol)
  111. l, err := exe.Uretprobe(p.symbol, t.uprobes[p.uretprobe], nil)
  112. if err != nil {
  113. klog.Infoln("fucktls crypto/tls uprobes attached ret error", p.symbol)
  114. //log("failed to attach uretprobe", err)
  115. return nil, err
  116. }
  117. links = append(links, l)
  118. }
  119. }
  120. //log("libssl uprobes attached", nil)
  121. return links, nil
  122. }
  123. func (t *Tracer) AttachGoTlsUprobes(pid uint32, appInfo *AppInfo, codeType uint16) ([]link.Link, error) {
  124. if t.DisableL7Tracing() {
  125. return nil, nil
  126. }
  127. path := proc.Path(pid, "exe")
  128. instanceID := appInfo.InstanceIdHash.HashtVal
  129. appID := appInfo.AppIdHash.HashtVal
  130. var err error
  131. var name, version string
  132. log := func(msg string, err error) {
  133. if err != nil {
  134. for _, s := range []string{"not a Go executable", "no such file or directory", "no such process", "permission denied"} {
  135. if strings.HasSuffix(err.Error(), s) {
  136. return
  137. }
  138. }
  139. klog.Errorf("pid=%d golang_app=%s golang_version=%s: %s: %s", pid, name, version, msg, err)
  140. return
  141. }
  142. klog.Infof("pid=%d golang_app=%s golang_version=%s: %s", pid, name, version, msg)
  143. }
  144. bi, err := buildinfo.ReadFile(path)
  145. if err != nil {
  146. log("failed to read build info", err)
  147. return nil, err
  148. }
  149. // isGolangApp = true
  150. name, err = os.Readlink(path)
  151. if err != nil {
  152. log("failed to read name", err)
  153. return nil, err
  154. }
  155. version = strings.Replace(bi.GoVersion, "go", "v", 1)
  156. if semver.Compare(version, minSupportedGoVersion) < 0 {
  157. log(fmt.Sprintf("go_versions below %s are not supported", minSupportedGoVersion), nil)
  158. return nil, err
  159. }
  160. ef, err := elf.Open(path)
  161. if err != nil {
  162. log("failed to open as elf binary", err)
  163. return nil, err
  164. }
  165. defer ef.Close()
  166. symbols, err := ef.Symbols()
  167. if err != nil {
  168. if errors.Is(err, elf.ErrNoSymbols) {
  169. log("no symbol section", nil)
  170. return nil, err
  171. }
  172. log("failed to read symbols", err)
  173. return nil, err
  174. }
  175. textSection := ef.Section(".text")
  176. if textSection == nil {
  177. log("no text section", nil)
  178. return nil, err
  179. }
  180. textSectionData, err := textSection.Data()
  181. if err != nil {
  182. log("failed to read text section", err)
  183. return nil, err
  184. }
  185. textSectionLen := uint64(len(textSectionData) - 1)
  186. exe, err := link.OpenExecutable(path)
  187. if err != nil {
  188. log("failed to open executable", err)
  189. return nil, err
  190. }
  191. offset, ok := tracer.GetOffset(tracer.NewID("std", "runtime", "g", "goid"), path)
  192. bucketsOff, ok2 := tracer.GetOffset(tracer.NewID("std", "runtime", "hmap", "buckets"), path)
  193. if ok && ok2 {
  194. realVersion := strings.Replace(bi.GoVersion, "go", "", 1)
  195. parts := strings.Split(realVersion, ".")
  196. var major, minor, revision int
  197. if len(parts) >= 2 {
  198. major, err = strconv.Atoi(parts[0])
  199. if err != nil {
  200. log("Error converting major version:", err)
  201. return nil, err
  202. }
  203. minor, err = strconv.Atoi(parts[1])
  204. if err != nil {
  205. log("Error converting minor version:", err)
  206. return nil, err
  207. }
  208. if len(parts) >= 3 {
  209. revision, err = strconv.Atoi(parts[2])
  210. if err != nil {
  211. log("Error converting revision version:", err)
  212. }
  213. }
  214. goVersion := ((major & 0xFF) << 16) + ((minor & 0xFF) << 8) + min(revision, 255)
  215. info := EbpfProcInfo{}
  216. info.Version = uint32(goVersion)
  217. info.Offsets[OFFSET_IDX_GOID_RUNTIME_G] = uint16(offset)
  218. info.NetTCPConnItab = uint64(0)
  219. info.CryptoTLSConnItab = uint64(0)
  220. info.CredentialsSyscallConnItab = uint64(0)
  221. info.InstanceId = instanceID
  222. info.AppId = appID
  223. info.CodeType = codeType
  224. // go
  225. info.BucketsPtrPos = bucketsOff
  226. fields := map[*uint64]tracer.ID{
  227. &info.MethodPtrPos: tracer.NewID("std", "net/http", "Request", "Method"),
  228. &info.UrlPtrPos: tracer.NewID("std", "net/http", "Request", "URL"),
  229. &info.PathPtrPos: tracer.NewID("std", "net/url", "URL", "Path"),
  230. &info.StatusCodePos: tracer.NewID("std", "net/http", "response", "status"),
  231. &info.RequestHostPos: tracer.NewID("std", "net/http", "Request", "Host"),
  232. &info.ProtoPos: tracer.NewID("std", "net/http", "Request", "Proto"),
  233. &info.CtxPtrPos: tracer.NewID("std", "net/http", "Request", "ctx"),
  234. &info.HeadersPtrPos: tracer.NewID("std", "net/http", "Request", "Header"),
  235. }
  236. for field, id := range fields {
  237. off, ok := tracer.GetOffset(id, path)
  238. if !ok {
  239. klog.Warnf("failed to get offset for ID: %v", id)
  240. }
  241. *field = off
  242. }
  243. // 获取内存地址
  244. if appInfo.GoProcCache.StartAddr == 0 && appInfo.GoProcCache.EndAddr == 0 {
  245. allocDetails, allocErr := tracer.Allocate(int(pid))
  246. if allocErr != nil {
  247. return nil, allocErr
  248. }
  249. if allocDetails != nil {
  250. //info.StartAddr = allocDetails.StartAddr
  251. //info.EndAddr = allocDetails.EndAddr
  252. appInfo.GoProcCache.StartAddr = allocDetails.StartAddr
  253. appInfo.GoProcCache.EndAddr = allocDetails.EndAddr
  254. }
  255. }
  256. info.StartAddr = appInfo.GoProcCache.StartAddr
  257. info.EndAddr = appInfo.GoProcCache.EndAddr
  258. klog.Debugln("Major:", major)
  259. klog.Debugln("Minor:", minor)
  260. klog.Debugln("Revision:", revision)
  261. klog.Debugln("goVersion", goVersion)
  262. klog.WithField("pid", pid).Debugln("info.StartAddr", info.StartAddr)
  263. klog.WithField("pid", pid).Debugln("info.EndAddr", info.EndAddr)
  264. _, err = tracer.UpdateProcInfoToMap(t.collection, pid, info)
  265. if err != nil {
  266. klog.Error("failed to update program info", err)
  267. return nil, err
  268. }
  269. appInfo.EBPFProcInfo = &info
  270. }
  271. }
  272. var links []link.Link
  273. for _, s := range symbols {
  274. if elf.ST_TYPE(s.Info) != elf.STT_FUNC || s.Size == 0 {
  275. continue
  276. }
  277. switch s.Name {
  278. case goTlsWriteSymbol, goTlsReadSymbol:
  279. case goExecute, goNewproc1, goRunqget, goServeHTTP, goTransport, goGrpcHttp2OperateHeader,goGrpcServerHandleStream,goGrpcServerWritestatus,goGrpcClientConnInvoke,goGrpcClientLoopyHeaderHandler,goGrpcHttp2ClientNewStream:
  280. default:
  281. continue
  282. }
  283. address := s.Value
  284. for _, p := range ef.Progs {
  285. if p.Type != elf.PT_LOAD || (p.Flags&elf.PF_X) == 0 {
  286. continue
  287. }
  288. if p.Vaddr <= s.Value && s.Value < (p.Vaddr+p.Memsz) {
  289. address = s.Value - p.Vaddr + p.Off
  290. break
  291. }
  292. }
  293. //fmt.Println("s.Name-----:", s.Name)
  294. switch s.Name {
  295. case goExecute:
  296. l, err := exe.Uprobe(s.Name, t.uprobes["runtime_execute"], &link.UprobeOptions{Address: address})
  297. if err != nil {
  298. log("failed to attach write_enter uprobe", err)
  299. klog.Infoln("runtime.execute no")
  300. return nil, err
  301. } else {
  302. klog.Infoln("runtime.execute ok")
  303. }
  304. links = append(links, l)
  305. case goNewproc1:
  306. l, err := exe.Uprobe(s.Name, t.uprobes["enter_runtime_newproc1"], &link.UprobeOptions{Address: address})
  307. if err != nil {
  308. log("failed to attach newproc1 uprobe", err)
  309. return nil, err
  310. }
  311. links = append(links, l)
  312. sStart := s.Value - textSection.Addr
  313. sEnd := sStart + s.Size
  314. if sEnd > textSectionLen {
  315. continue
  316. }
  317. sBytes := textSectionData[sStart:sEnd]
  318. returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  319. if len(returnOffsets) == 0 {
  320. log("failed to attach enter_runtime_newproc1 uprobe", fmt.Errorf("no return offsets found"))
  321. return nil, err
  322. }
  323. for _, offset := range returnOffsets {
  324. l, err := exe.Uprobe(s.Name, t.uprobes["exit_runtime_newproc1"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  325. if err != nil {
  326. log("failed to attach exit_runtime_newproc1 uprobe", err)
  327. return nil, err
  328. }
  329. links = append(links, l)
  330. }
  331. case goRunqget:
  332. l, err := exe.Uprobe(s.Name, t.uprobes["enter_runtime_runqget"], &link.UprobeOptions{Address: address})
  333. if err != nil {
  334. log("failed to attach goRunqget uprobe", err)
  335. return nil, err
  336. }
  337. links = append(links, l)
  338. //sStart := s.Value - textSection.Addr
  339. //sEnd := sStart + s.Size
  340. //if sEnd > textSectionLen {
  341. // continue
  342. //}
  343. //sBytes := textSectionData[sStart:sEnd]
  344. //returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  345. //if len(returnOffsets) == 0 {
  346. // log("failed to attach enter_runtime_newproc1 uprobe", fmt.Errorf("no return offsets found"))
  347. // return nil
  348. //}
  349. //for _, offset := range returnOffsets {
  350. // l, err := exe.Uprobe(s.Name, t.uprobes["exit_runtime_newproc1"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  351. // if err != nil {
  352. // log("failed to attach exit_runtime_newproc1 uprobe", err)
  353. // return nil
  354. // }
  355. // links = append(links, l)
  356. //}
  357. case goGrpcClientConnInvoke:
  358. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_ClientConn_Invoke"], &link.UprobeOptions{Address: address})
  359. if err != nil {
  360. klog.WithError(err).Errorln("failed to attach uprobe_ClientConn_Invoke uprobe")
  361. continue
  362. }
  363. klog.Infoln("uprobe_ClientConn_Invoke ok")
  364. links = append(links, l)
  365. sStart := s.Value - textSection.Addr
  366. sEnd := sStart + s.Size
  367. klog.Infoln("uprobe_ClientConn_Invoke ok----111111")
  368. if sEnd > textSectionLen {
  369. continue
  370. }
  371. klog.Infoln("uprobe_ClientConn_Invoke ok----2222")
  372. sBytes := textSectionData[sStart:sEnd]
  373. returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  374. if len(returnOffsets) == 0 {
  375. err = fmt.Errorf("failed to attach uprobe_ClientConn_Invoke no return offsets found")
  376. klog.Errorln(err)
  377. return nil, err
  378. }
  379. for _, offset := range returnOffsets {
  380. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_ClientConn_Invoke_Returns"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  381. if err != nil {
  382. klog.WithError(err).Errorln(fmt.Errorf("failed to attach uprobe_ClientConn_Invoke_Returns uprobe"))
  383. return nil, err
  384. }
  385. klog.Infoln("uprobe_ClientConn_Invoke_Returns ok----")
  386. links = append(links, l)
  387. }
  388. case goGrpcClientLoopyHeaderHandler:
  389. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_LoopyWriter_HeaderHandler"], &link.UprobeOptions{Address: address})
  390. if err != nil {
  391. klog.WithError(err).Errorln("failed to attach uprobe_LoopyWriter_HeaderHandler uprobe")
  392. continue
  393. }
  394. klog.Infoln("uprobe_LoopyWriter_HeaderHandler ok")
  395. links = append(links, l)
  396. case goGrpcHttp2ClientNewStream:
  397. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_http2Client_NewStream"], &link.UprobeOptions{Address: address})
  398. if err != nil {
  399. klog.WithError(err).Errorln("failed to attach uprobe_http2Client_NewStream uprobe")
  400. continue
  401. }
  402. klog.Infoln("uprobe_http2Client_NewStream ok")
  403. links = append(links, l)
  404. case goGrpcHttp2OperateHeader:
  405. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_http2Server_operateHeader"], &link.UprobeOptions{Address: address})
  406. if err != nil {
  407. klog.WithError(err).Errorln("failed to attach uprobe_http2Server_operateHeader uprobe")
  408. continue
  409. }
  410. klog.Infoln("goGrpcHttp2OperateHeader ok")
  411. links = append(links, l)
  412. case goGrpcServerWritestatus:
  413. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_http2Server_WriteStatus"], &link.UprobeOptions{Address: address})
  414. if err != nil {
  415. klog.WithError(err).Errorln("failed to attach uprobe_http2Server_WriteStatus uprobe")
  416. continue
  417. }
  418. klog.Infoln("google.golang.org/grpc/internal/transport.(*http2Server).writeStatus ok")
  419. links = append(links, l)
  420. case goGrpcServerHandleStream:
  421. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_server_handleStream"], &link.UprobeOptions{Address: address})
  422. if err != nil {
  423. klog.WithError(err).Errorln("failed to attach uprobe_server_handleStream uprobe")
  424. continue
  425. }
  426. klog.Infoln("google.golang.org/grpc.(*Server).handleStream ok")
  427. links = append(links, l)
  428. sStart := s.Value - textSection.Addr
  429. sEnd := sStart + s.Size
  430. klog.Infoln("google.golang.org/grpc.(*Server).handleStream ok----111111")
  431. if sEnd > textSectionLen {
  432. continue
  433. }
  434. klog.Infoln("google.golang.org/grpc.(*Server).handleStream ok----2222")
  435. sBytes := textSectionData[sStart:sEnd]
  436. returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  437. if len(returnOffsets) == 0 {
  438. err = fmt.Errorf("failed to attach uprobe_server_handleStream2 no return offsets found")
  439. klog.Errorln(err)
  440. return nil, err
  441. }
  442. for _, offset := range returnOffsets {
  443. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_server_handleStream_Returns"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  444. if err != nil {
  445. klog.WithError(err).Errorln(fmt.Errorf("failed to attach exit_runtime_newproc1 uprobe"))
  446. return nil, err
  447. }
  448. klog.Infoln("google.golang.org/grpc.(*Server).handleStream ok----")
  449. links = append(links, l)
  450. }
  451. case goServeHTTP:
  452. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_HandlerFunc_ServeHTTP"], &link.UprobeOptions{Address: address})
  453. if err != nil {
  454. klog.WithError(err).Errorln("failed to attach uprobe_HandlerFunc_ServeHTTP uprobe")
  455. continue
  456. }
  457. klog.Infoln("net/http.serverHandler.ServeHTTP ok")
  458. links = append(links, l)
  459. sStart := s.Value - textSection.Addr
  460. sEnd := sStart + s.Size
  461. if sEnd > textSectionLen {
  462. continue
  463. }
  464. sBytes := textSectionData[sStart:sEnd]
  465. returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  466. if len(returnOffsets) == 0 {
  467. err = fmt.Errorf("failed to attach uprobe_HandlerFunc_ServeHTTP no return offsets found")
  468. klog.Errorln(err)
  469. return nil, err
  470. }
  471. for _, offset := range returnOffsets {
  472. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_HandlerFunc_ServeHTTP_Returns"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  473. if err != nil {
  474. klog.WithError(err).Errorln(fmt.Errorf("failed to attach exit_runtime_newproc1 uprobe"))
  475. return nil, err
  476. }
  477. links = append(links, l)
  478. }
  479. case goTransport:
  480. if t.DisableE2ETracing() {
  481. continue
  482. }
  483. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_Transport_roundTrip"], &link.UprobeOptions{Address: address})
  484. if err != nil {
  485. klog.WithError(err).Errorln(fmt.Errorf("failed to attach write_enter uprobe"))
  486. continue
  487. } else {
  488. }
  489. klog.Infoln("net/http.uprobe_Transport_roundTrip ok")
  490. links = append(links, l)
  491. sStart := s.Value - textSection.Addr
  492. sEnd := sStart + s.Size
  493. if sEnd > textSectionLen {
  494. continue
  495. }
  496. sBytes := textSectionData[sStart:sEnd]
  497. returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  498. if len(returnOffsets) == 0 {
  499. err = fmt.Errorf("failed to attach uprobe_Transport_roundTrip uprobe no return offsets found")
  500. klog.Errorln(err)
  501. return nil, err
  502. }
  503. for _, offset := range returnOffsets {
  504. l, err := exe.Uprobe(s.Name, t.uprobes["uprobe_Transport_roundTrip_Returns"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  505. if err != nil {
  506. klog.WithError(err).Errorln("failed to attach exit_runtime_newproc1 uprobe")
  507. return nil, err
  508. }
  509. links = append(links, l)
  510. }
  511. //case goTlsWriteSymbol:
  512. // klog.Infoln("fucktls goTlsWriteSymbol crypto/tls uprobes attached")
  513. // l, err := exe.Uprobe(s.Name, t.uprobes["go_crypto_tls_write_enter"], &link.UprobeOptions{Address: address})
  514. // if err != nil {
  515. // klog.WithError(err).Errorln("failed to attach write_enter uprobe")
  516. // return nil, err
  517. // }
  518. // links = append(links, l)
  519. //case goTlsReadSymbol:
  520. // klog.Infoln("fucktls goTlsReadSymbol crypto/tls uprobes attached")
  521. // l, err := exe.Uprobe(s.Name, t.uprobes["go_crypto_tls_read_enter"], &link.UprobeOptions{Address: address})
  522. // if err != nil {
  523. // klog.WithError(err).Errorln("failed to attach read_enter uprobe")
  524. // return nil, err
  525. // }
  526. // links = append(links, l)
  527. // sStart := s.Value - textSection.Addr
  528. // sEnd := sStart + s.Size
  529. // if sEnd > textSectionLen {
  530. // continue
  531. // }
  532. // sBytes := textSectionData[sStart:sEnd]
  533. // returnOffsets := getReturnOffsets(ef.Machine, sBytes)
  534. // if len(returnOffsets) == 0 {
  535. // err = fmt.Errorf("failed to attach read_exit uprobe no return offsets found")
  536. // klog.Errorln(err)
  537. // return nil, err
  538. // }
  539. // for _, offset := range returnOffsets {
  540. // l, err := exe.Uprobe(s.Name, t.uprobes["go_crypto_tls_read_exit"], &link.UprobeOptions{Address: address, Offset: uint64(offset)})
  541. // if err != nil {
  542. // klog.WithError(err).Errorln("failed to attach read_exit uprobe")
  543. // return nil, err
  544. // }
  545. // links = append(links, l)
  546. // }
  547. }
  548. }
  549. if len(links) == 0 {
  550. return nil, err
  551. }
  552. klog.Infoln("crypto/tls uprobes attached")
  553. return links, nil
  554. }
  555. func getSslLibPathAndVersion(pid uint32) (string, string) {
  556. f, err := os.Open(proc.Path(pid, "maps"))
  557. if err != nil {
  558. return "", ""
  559. }
  560. defer f.Close()
  561. scanner := bufio.NewScanner(f)
  562. scanner.Split(bufio.ScanLines)
  563. var libsslPath, libcryptoPath string
  564. for scanner.Scan() {
  565. parts := strings.Fields(scanner.Text())
  566. if len(parts) <= 5 {
  567. continue
  568. }
  569. libPath := parts[5]
  570. switch {
  571. case libsslPath == "" && strings.Contains(libPath, "libssl.so"):
  572. fullPath := proc.Path(pid, "root", libPath)
  573. if _, err = os.Stat(fullPath); err == nil {
  574. libsslPath = fullPath
  575. }
  576. case libcryptoPath == "" && strings.Contains(libPath, "libcrypto.so"):
  577. fullPath := proc.Path(pid, "root", libPath)
  578. if _, err = os.Stat(fullPath); err == nil {
  579. libcryptoPath = fullPath
  580. }
  581. default:
  582. continue
  583. }
  584. if libsslPath != "" && libcryptoPath != "" {
  585. break
  586. }
  587. }
  588. if libsslPath == "" || libcryptoPath == "" {
  589. return "", ""
  590. }
  591. ef, err := elf.Open(libcryptoPath)
  592. if err != nil {
  593. return "", ""
  594. }
  595. defer ef.Close()
  596. rodataSection := ef.Section(".rodata")
  597. if rodataSection == nil {
  598. return "", ""
  599. }
  600. rodataSectionData, err := rodataSection.Data()
  601. if err != nil {
  602. return "", ""
  603. }
  604. var version string
  605. for _, b := range bytes.Split(rodataSectionData, []byte("\x00")) {
  606. if len(b) == 0 {
  607. continue
  608. }
  609. s := string(b)
  610. if !strings.HasPrefix(s, "OpenSSL") {
  611. continue
  612. }
  613. if m := opensslVersionRe.FindStringSubmatch(s); len(m) > 1 {
  614. version = m[1]
  615. }
  616. }
  617. return libsslPath, "v" + version
  618. }
  619. func getReturnOffsets(machine elf.Machine, instructions []byte) []int {
  620. var res []int
  621. switch machine {
  622. case elf.EM_X86_64:
  623. for i := 0; i < len(instructions); {
  624. ins, err := x86asm.Decode(instructions[i:], 64)
  625. if err == nil && ins.Op == x86asm.RET {
  626. res = append(res, i)
  627. }
  628. i += ins.Len
  629. }
  630. case elf.EM_AARCH64:
  631. for i := 0; i < len(instructions); {
  632. ins, err := arm64asm.Decode(instructions[i:])
  633. if err == nil && ins.Op == arm64asm.RET {
  634. res = append(res, i)
  635. }
  636. i += 4
  637. }
  638. }
  639. return res
  640. }
  641. func min(a, b int) int {
  642. if a < b {
  643. return a
  644. }
  645. return b
  646. }