|
|
@@ -16,7 +16,6 @@ import (
|
|
|
"github.com/coroot/coroot-node-agent/utils"
|
|
|
klog "github.com/sirupsen/logrus"
|
|
|
"golang.org/x/arch/x86/x86asm"
|
|
|
- "io"
|
|
|
"os"
|
|
|
"path/filepath"
|
|
|
"strings"
|
|
|
@@ -46,43 +45,6 @@ type InnerSymbolInfo struct {
|
|
|
NET_Send InstInfo
|
|
|
}
|
|
|
|
|
|
-type LibNetInfo struct {
|
|
|
- LibName string
|
|
|
- LibPath string
|
|
|
- FuncSymbol InstInfo
|
|
|
- InnerSymbol InnerSymbolInfo
|
|
|
- ProcLoadPath string
|
|
|
- FileDeleted bool
|
|
|
- MapFile string
|
|
|
-}
|
|
|
-
|
|
|
-type UprobeData struct {
|
|
|
- Offset int
|
|
|
- Func string
|
|
|
- ELFPath string
|
|
|
-}
|
|
|
-
|
|
|
-type JvmInjector struct {
|
|
|
- Pid int
|
|
|
- ReleaseLibNetInfo LibNetInfo
|
|
|
- DebugLibNetInfo LibNetInfo
|
|
|
- RecodeInfo LibNetInfo
|
|
|
- // 原方法首个指令不为jmp | ReleaseLibNetInfo 读取无异常
|
|
|
- PreCheck struct {
|
|
|
- NeedInjectionCheck bool // 原指令校验 true表示可以继续执行注入
|
|
|
- LoadingCheck bool // true 表示加载成功
|
|
|
- IoFdCheck bool // fd地址校验
|
|
|
- NetSendFuncCheck bool // netsend校验
|
|
|
- EbpfCanInjection bool // 满足则注入ebpf
|
|
|
- }
|
|
|
- AfterCheck struct {
|
|
|
- IoFdCheck bool
|
|
|
- NetSendFuncCheck bool
|
|
|
- }
|
|
|
- Uprobe UprobeData
|
|
|
- Rootfs string
|
|
|
-}
|
|
|
-
|
|
|
func (j *JvmInjector) findReleaseAddressInfoFromMem() error {
|
|
|
funcAbsAddress := j.ReleaseLibNetInfo.FuncSymbol.SymAddr
|
|
|
releaseFuncSym := InnerSymbolInfo{}
|
|
|
@@ -463,7 +425,7 @@ func findLibraryBasesList(pid int, libraryName string, libPath string) ([]uint64
|
|
|
return bases, nil
|
|
|
}
|
|
|
|
|
|
-func (j *JvmInjector) findLibBaseFromProcMaps(libName string) (uint64, string, string, bool, error) {
|
|
|
+func (j *JvmInjector) findLibBaseFromProcMaps(pid int, libName string) (uint64, string, string, bool, error) {
|
|
|
mapsFile := fmt.Sprintf("/proc/%d/maps", j.Pid)
|
|
|
file, err := os.Open(mapsFile)
|
|
|
if err != nil {
|
|
|
@@ -558,7 +520,7 @@ func (j *JvmInjector) getFunctionOffset(libPath, functionName string) (elf.Symbo
|
|
|
|
|
|
func (j *JvmInjector) InitProg() error {
|
|
|
// 获取release库的基地址
|
|
|
- baseAddress, releaseSoFilePathInProc, mapFilesPath, deleted, err := j.findLibBaseFromProcMaps(j.ReleaseLibNetInfo.LibName)
|
|
|
+ baseAddress, releaseSoFilePathInProc, mapFilesPath, deleted, err := FindLibBaseFromProcMaps(j.Pid, j.ReleaseLibNetInfo.LibName)
|
|
|
//j.ReleaseLibNetInfo.LibPath = releaseSoFilePathInProc
|
|
|
j.ReleaseLibNetInfo.FileDeleted = deleted
|
|
|
j.ReleaseLibNetInfo.MapFile = mapFilesPath
|
|
|
@@ -581,13 +543,13 @@ func (j *JvmInjector) InitProg() error {
|
|
|
|
|
|
// find cwlibnet.so in proc maps
|
|
|
var readDebugSoPathInMaps string
|
|
|
- _, readDebugSoPathInMaps, j.DebugLibNetInfo.MapFile, j.DebugLibNetInfo.FileDeleted, _ = j.findLibBaseFromProcMaps(j.DebugLibNetInfo.LibName)
|
|
|
+ _, readDebugSoPathInMaps, j.DebugLibNetInfo.MapFile, j.DebugLibNetInfo.FileDeleted, _ = FindLibBaseFromProcMaps(j.Pid, j.DebugLibNetInfo.LibName)
|
|
|
j.DebugLibNetInfo.LibPath = debugSoFilePhysicalPath
|
|
|
j.DebugLibNetInfo.ProcLoadPath = filepath.Join(jvmLibBaseDir, j.DebugLibNetInfo.LibName)
|
|
|
// condition create
|
|
|
pathFromProg := utils.GetDefaultLibsPath("jvm", j.DebugLibNetInfo.LibName)
|
|
|
if noFileErr != nil && readDebugSoPathInMaps == "" && !j.DebugLibNetInfo.FileDeleted {
|
|
|
- err = copyFileAndMatchPermissions(pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
|
|
|
+ err = CopyFileAndMatchPermissions(pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
|
|
|
klog.Infof("[src:%s],[target:%s],[perm:%s]", pathFromProg, debugSoFilePhysicalPath, pJvmlibnetPhysicalPath)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
@@ -600,7 +562,7 @@ func (j *JvmInjector) InitProg() error {
|
|
|
klog.Infof("[inject] Base address of [%s]:[%x]", j.ReleaseLibNetInfo.LibName, baseAddress)
|
|
|
|
|
|
// 获取函数的偏移量
|
|
|
- functionSym, err := j.getFunctionOffset(pJvmlibnetPhysicalPath, functionName)
|
|
|
+ functionSym, err := GetFunctionOffset(pJvmlibnetPhysicalPath, functionName)
|
|
|
|
|
|
// 计算函数的实际内存地址
|
|
|
j.ReleaseLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
|
|
|
@@ -631,7 +593,7 @@ func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
|
|
|
//libName := j.DebugLibNetInfo.LibPath
|
|
|
|
|
|
// 获取release库的基地址
|
|
|
- baseAddress, libPath, err := j.findLibBaseByPathFromProcMaps(j.DebugLibNetInfo.ProcLoadPath)
|
|
|
+ baseAddress, libPath, err := FindLibBaseByPathFromProcMaps(j.Pid, j.DebugLibNetInfo.ProcLoadPath)
|
|
|
klog.Infof("[inject] debug base address of [%s] : %x", libPath, baseAddress)
|
|
|
functionName := j.DebugLibNetInfo.FuncSymbol.SymName
|
|
|
//j.DebugLibNetInfo.LibPath = libPath
|
|
|
@@ -641,7 +603,7 @@ func (j *JvmInjector) findDebugFuncContextFromLibPath() error {
|
|
|
}
|
|
|
|
|
|
// 获取函数的偏移量
|
|
|
- functionSym, err := j.getFunctionOffset(j.DebugLibNetInfo.LibPath, functionName)
|
|
|
+ functionSym, err := GetFunctionOffset(j.DebugLibNetInfo.LibPath, functionName)
|
|
|
// 计算函数的实际内存地址
|
|
|
j.DebugLibNetInfo.FuncSymbol.SymAddr = baseAddress + functionSym.Value
|
|
|
j.DebugLibNetInfo.FuncSymbol.SymSize = functionSym.Size
|
|
|
@@ -846,7 +808,7 @@ func JvmInject(jvmInjector *JvmInjector) error {
|
|
|
return err
|
|
|
}
|
|
|
printCodeData(jvmInjector.ReleaseLibNetInfo)
|
|
|
- _type, _, err := jvmInjector.findLibBaseByPathFromProcMaps(jvmInjector.DebugLibNetInfo.ProcLoadPath)
|
|
|
+ _type, _, err := FindLibBaseByPathFromProcMaps(pid, jvmInjector.DebugLibNetInfo.ProcLoadPath)
|
|
|
if err != nil {
|
|
|
// load so
|
|
|
if _type == 1 {
|
|
|
@@ -861,6 +823,7 @@ func JvmInject(jvmInjector *JvmInjector) error {
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
+ klog.Infoln("[inject] so already loaded.")
|
|
|
jvmInjector.PreCheck.LoadingCheck = true
|
|
|
}
|
|
|
|
|
|
@@ -876,7 +839,13 @@ func JvmInject(jvmInjector *JvmInjector) error {
|
|
|
}
|
|
|
|
|
|
if !jvmInjector.validateAllPreCheck() {
|
|
|
- klog.Infof("[inject] validate all pre check")
|
|
|
+ klog.Errorf("[inject] validateAllPreCheck failed: "+
|
|
|
+ "NeedInjectionCheck=%v, LoadingCheck=%v, IoFdCheck=%v, NetSendFuncCheck=%v",
|
|
|
+ jvmInjector.PreCheck.NeedInjectionCheck,
|
|
|
+ jvmInjector.PreCheck.LoadingCheck,
|
|
|
+ jvmInjector.PreCheck.IoFdCheck,
|
|
|
+ jvmInjector.PreCheck.NetSendFuncCheck,
|
|
|
+ )
|
|
|
return err
|
|
|
}
|
|
|
// 修改
|
|
|
@@ -959,42 +928,3 @@ func JvmInject(jvmInjector *JvmInjector) error {
|
|
|
}
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
-func copyFileAndMatchPermissions(srcFile, destFile, permFile string) error {
|
|
|
- // 获取权限文件的信息
|
|
|
- permInfo, err := os.Stat(permFile)
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to stat permission file: %w", err)
|
|
|
- }
|
|
|
-
|
|
|
- // 打开源文件
|
|
|
- src, err := os.Open(srcFile)
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to open source file: %w", err)
|
|
|
- }
|
|
|
- defer src.Close()
|
|
|
-
|
|
|
- // 创建目标文件
|
|
|
- dst, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE, permInfo.Mode())
|
|
|
- if err != nil {
|
|
|
- return fmt.Errorf("failed to create destination file: %w", err)
|
|
|
- }
|
|
|
- defer dst.Close()
|
|
|
- // 复制文件内容
|
|
|
- if _, err := io.Copy(dst, src); err != nil {
|
|
|
- return fmt.Errorf("failed to copy file content: %w", err)
|
|
|
- }
|
|
|
-
|
|
|
- // 获取用户和组信息并设置
|
|
|
- if stat, ok := permInfo.Sys().(*syscall.Stat_t); ok {
|
|
|
- fmt.Println(stat.Uid)
|
|
|
- fmt.Println(stat.Gid)
|
|
|
- if err := dst.Chown(int(stat.Uid), int(stat.Gid)); err != nil {
|
|
|
- return fmt.Errorf("failed to set file ownership: %w", err)
|
|
|
- }
|
|
|
- } else {
|
|
|
- return fmt.Errorf("failed to retrieve ownership information")
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|