Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SIGSEGV: segmentation violation #22

Open
jackie575 opened this issue Dec 13, 2023 · 2 comments
Open

SIGSEGV: segmentation violation #22

jackie575 opened this issue Dec 13, 2023 · 2 comments

Comments

@jackie575
Copy link

jackie575 commented Dec 13, 2023

HI ,I encounter a problem when many concurrent goroutine execute Script.ExportsCall;Here is The Env And Error Info

OS:  Mac Os  14.1.2 (23B92)
CPU ARCH:  2.6 GHz  Intel Core i7 Amd64

Go Version: go1.21.5
Frida-go-sdk version:  v0.6.10

Android Device Version : Android 12 
Android frida-server version :  16.1.4 Arm64


Updated:  switch the latest Frida-Server 16.1.8 , the problem reproduced

===========

Error Stack:
SIGSEGV: segmentation violation
PC=0x1010b21c2 m=15 sigcode=1
signal arrived during cgo execution

goroutine 2986 [syscall]:
runtime.cgocall(0x100a46800, 0xc00129ae58)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/cgocall.go:157 +0x4b fp=0xc00129ae30 sp=0xc00129adf8 pc=0x10000aaab
github.com/frida/frida-go/frida._Cfunc_g_object_unref(0x7fb31d817380)
        _cgo_gotypes.go:3402 +0x3f fp=0xc00129ae58 sp=0xc00129ae30 pc=0x1002e71df
github.com/frida/frida-go/frida.unrefGObj.func1(0x7fb31d817380)
        /Users/jackie/go/pkg/mod/github.com/frida/[email protected]/frida/cleanups.go:30 +0x3b fp=0xc00129ae90 sp=0xc00129ae58 pc=0x1002eb31b
github.com/frida/frida-go/frida.unrefGObj(0x7fb31d817380)
        /Users/jackie/go/pkg/mod/github.com/frida/[email protected]/frida/cleanups.go:30 +0x18 fp=0xc00129aea8 sp=0xc00129ae90 pc=0x1002eb2b8
github.com/frida/frida-go/frida.clean(0x7fb31d817380, {0x1012f6734, 0xb})
        /Users/jackie/go/pkg/mod/github.com/frida/[email protected]/frida/cleanups.go:37 +0x5e fp=0xc00129aee0 sp=0xc00129aea8 pc=0x1002eb39e
github.com/frida/frida-go/frida.(*Session).Clean(0xc000015900)
        /Users/jackie/go/pkg/mod/github.com/frida/[email protected]/frida/session.go:198 +0x33 fp=0xc00129af10 sp=0xc00129aee0 pc=0x100302d33
frida-go-rpc/MyFridaApp/fridaApiHooker.close({0xc000015800, 0xc0000158a8, 0xc000015900, 0xc0001f02a0})
        /GoProjects/frida-go-rpc/MyApp/ApiHooker.go:35 +0x3c fp=0xc00129af38 sp=0xc00129af10 pc=0x1007bd41c
frida-go-rpc/MyFridaApp/.GetClient.func1.1.1()
        /GoProjects/frida-go-rpc/MyFridaApp/FridaClient.go:158 +0x9e fp=0xc00129afe0 sp=0xc00129af38 pc=0x1007bf91e
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00129afe8 sp=0xc00129afe0 pc=0x1000785e1
created by frida-go-rpc/MyFridaApp/.GetClient.func1.1 in goroutine 5
        /GoProjects/frida-go-rpc/MyFridaApp/FridaClient.go:148 +0x145

goroutine 1 [sleep]:
runtime.gopark(0x10135a680, 0xc0002300f0, 0x13, 0x13, 0x1)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:398 +0xfc fp=0xc001491b60 sp=0xc001491b30 pc=0x10004673c
time.Sleep(0x174876e800)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/time.go:195 +0x110 fp=0xc001491ba0 sp=0xc001491b60 pc=0x100075550
main.main()
        /GoProjects/frida-go-rpc/main.go:213 +0x12a fp=0xc001491f68 sp=0xc001491ba0 pc=0x100a4474a
runtime.main()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:267 +0x267 fp=0xc001491fe0 sp=0xc001491f68 pc=0x1000462c7
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc001491fe8 sp=0xc001491fe0 pc=0x1000785e1

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc0015a5fe8 sp=0xc0015a5fe0 pc=0x1000785e1

goroutine 2 [force gc (idle)]:
runtime.gopark(0x10135a640, 0x103fb1d60, 0x11, 0x14, 0x1)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:398 +0xfc fp=0xc00006af80 sp=0xc00006af50 pc=0x10004673c
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:404 +0x25 fp=0xc00006afb0 sp=0xc00006af80 pc=0x1000467c5
runtime.forcegchelper()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:322 +0xb5 fp=0xc00006afe0 sp=0xc00006afb0 pc=0x100046555
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00006afe8 sp=0xc00006afe0 pc=0x1000785e1
created by runtime.init.6 in goroutine 1
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:310 +0x1a

goroutine 18 [GC sweep wait]:
runtime.gopark(0x10135a640, 0x103fb2ba0, 0xc, 0x14, 0x1)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:398 +0xfc fp=0xc000066750 sp=0xc000066720 pc=0x10004673c
runtime.goparkunlock(0x1?, 0x0?, 0x0?, 0x0?)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:404 +0x25 fp=0xc000066780 sp=0xc000066750 pc=0x1000467c5
runtime.bgsweep(0x0?)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgcsweep.go:321 +0xe5 fp=0xc0000667c8 sp=0xc000066780 pc=0x10002f525
runtime.gcenable.func1()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgc.go:200 +0x25 fp=0xc0000667e0 sp=0xc0000667c8 pc=0x1000237a5
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc0000667e8 sp=0xc0000667e0 pc=0x1000785e1
created by runtime.gcenable in goroutine 1
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgc.go:200 +0x66

goroutine 19 [GC scavenge wait]:
runtime.gopark(0x10135a640, 0x103fb33e0, 0xd, 0x14, 0x2)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:398 +0xfc fp=0xc000066f40 sp=0xc000066f10 pc=0x10004673c
runtime.goparkunlock(0x1013a5288?, 0x0?, 0x0?, 0x0?)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:404 +0x25 fp=0xc000066f70 sp=0xc000066f40 pc=0x1000467c5
runtime.(*scavengerState).park(0x103fb33e0)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgcscavenge.go:425 +0x45 fp=0xc000066f98 sp=0xc000066f70 pc=0x10002c7e5
runtime.bgscavenge(0x0?)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgcscavenge.go:658 +0x65 fp=0xc000066fc8 sp=0xc000066f98 pc=0x10002cd85
runtime.gcenable.func2()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgc.go:201 +0x25 fp=0xc000066fe0 sp=0xc000066fc8 pc=0x100023745
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc000066fe8 sp=0xc000066fe0 pc=0x1000785e1
created by runtime.gcenable in goroutine 1
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mgc.go:201 +0xa5

goroutine 3 [finalizer wait]:
runtime.gopark(0x10135a370, 0x103feeda8, 0x10, 0x14, 0x1)
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/proc.go:398 +0xfc fp=0xc00006a628 sp=0xc00006a5f8 pc=0x10004673c
runtime.runfinq()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mfinal.go:193 +0xfa fp=0xc00006a7e0 sp=0xc00006a628 pc=0x10002285a
runtime.goexit()
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/asm_amd64.s:1650 +0x1 fp=0xc00006a7e8 sp=0xc00006a7e0 pc=0x1000785e1
created by runtime.createfing in goroutine 1
        /usr/local/Cellar/go/1.21.5/libexec/src/runtime/mfinal.goExiting.

Any Other Info ,when the app call Script.ExportsCall Timeout, i think it is just broken Session,so i close the resource , reopen another DeviceManager 、Device、Session and so on; Here is the code

hooker.script.Clean()
hooker.session.Clean()
hooker.device.Clean()
hooker.deviceManager.Clean()

Can anyone help me to solve it?
Many Thanks!

@NSEcho
Copy link
Member

NSEcho commented Dec 13, 2023

Hey, can you paste the code that caused the error

@jackie575
Copy link
Author

jackie575 commented Dec 13, 2023

Hey, can you paste the code that caused the error

Thanks For Your Reply!

Here is the code :

type FridaClient struct {
	
	apiHooker *fridaApiHooker
	// 
	refreshChan *chan uint32
	// Client Version,
	version * atomic.Uint32
	// Frida Resource is ok?
	OK bool
}

type fridaApiHooker struct {
	
	deviceManager *frida.DeviceManager
	
	device *frida.Device
	
	session *frida.Session
	
	script *frida.Script
}


// Close close the resource held by the frida client singleton
func (hooker fridaApiHooker) close()  {

	hooker.script.Clean()
	
	hooker.session.Clean()
	
	hooker.device.Clean()
	
	hooker.deviceManager.Clean()
	
}

// newApiHooker make new frida Resource
func newApiHooker() *fridaApiHooker {
	
	jsScript := readJsScript()
	
	deviceManager := frida.NewDeviceManager()
	

	devices, err := deviceManager.EnumerateDevices()
	if err != nil {
	
		panic("Device Error!")
	}
	
	for _, d := range devices {
		log.Printf("[*] Found device with id:%v", d.ID())
	}
	
	device, err := deviceManager.USBDevice()
	if err != nil {
	
		log.Printf("Could not get usb device: %v", err)
	
		os.Exit(1)
	}


	log.Printf("[*] Attaching to `App`")
	

	session, err := device.Attach(processName, nil)
	if err != nil {
		
		log.Printf("New Session Fail!err:%v", err)
		os.Exit(1)
	}
	
	fridaScript, err := session.CreateScript(jsScript)
	if err != nil {
		
		log.Printf("New Frida Script Fail! err:%v", err)
		os.Exit(1)
	}


	if err := fridaScript.Load(); err != nil {
	
		log.Printf("Load Frida Script Fail!err:%v", err)
		os.Exit(1)
	}

	return &fridaApiHooker{
		deviceManager: deviceManager,
		device:        device,
		session:       session,
		script:   fridaScript,
	}
}


func (client * FridaClient) CallFrida(param *CallFridaParam) (*rpc.CallResult, error) {
	// for loop 3 times
	for i := 0; i < 3; i++ {
		// every iteration , call the func , if err is TimeOutError,close
		// the resource,  reopen it 
		result, err := client.doFridaCallInner(param)

		if err != nil {
			
			if errors.Is(err, timeoutError) {
				// Timeout Error,get Client Version
				ver := client.version.Load()
				*client.refreshChan <- ver

				// wait for the client version greater than current,and 'ok'
				// statuc switch to 'true'

				for !(client.version.Load() > ver && client.OK) {
					// wait for reloader to reload resource
					time.Sleep(1 * time.Second)
				}

				continue
			} else {
				// other error than TimeOut
				return nil, err
			}
		} else {
			// call frida success ,just return it
			return result, nil
		}
	}

	// for loop end ,can't get result ,return err
	return nil, timeoutError

}


func (client *FridaClient) doFridaCallInner(param *FridaCallParam) (*rpc.FridaResult, error) {
	// make chan to recv result
	ch := make(chan FridaResult, 1)

	go func() {
		
		defer close(ch)

		
		resultMap := client.apiHooker.script.ExportsCall("JSFuncName",
			// 
			params
		)
	
		ch <- FridaResult{resultMap, nil}
		
	}()
	// 4. 当前协程等待结果
	select {
	case <-time.After(RpcTimeout * time.Second):
		{
			// 
			return nil, timeoutError
		}
	case result := <-ch:
		{
			return &result,nil
		}
	}
}




// GetFridaClient make FridaClient Singleton
func GetFridaClient() *FridaClient {
	
	clientInitLock.Do(func() {
		log.Printf("init  Frida client! ")
	
	
		apiHooker := newApiHooker()
		
		ch := make(chan uint32, 1)
		
		ver := atomic.Uint32{}
		// incr to version 1 
		ver.Add(1)
		clientSingleton = &FridaClient{
			apiHooker: apiHooker,
			//  version init to 1
			version: &ver,
			// size 1 channel 
			refreshChan: &ch,
			// 
			OK: true,
		}
		// 7. launch a new coroutine , do for refresh Resource
		go func() {
			for {
				// wait for channel recv 
				v := <-*clientSingleton.refreshChan
				
				if v == clientSingleton.version.Load() {
					//  version equals ,do the resource refresh actions
					casSuccess := clientSingleton.version.CompareAndSwap(v, v+1)
					if casSuccess {
						go func() {
							log.Printf("resource clean up")
							// when cas success ,refresh resource 
							clientSingleton.OK = false

							defer func() { clientSingleton.OK = true }()
							
							_ = clientSingleton.apiHooker.close()

							// make new hooker ,update the prop of singleton
							clientSingleton.apiHooker = newApiHooker()
						}()
					}
				} else {
					// Version different,Just return
					log.Printf("", v, clientSingleton.version)
				}
			}
		}()
	})
	
	return clientSingleton
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants