When I run the following Shell code in a normal macOS Desktop app I get a list of my login’s running processes:
Var tempShell As New Shell
Var Result As String
tempShell.ExecuteMode = Shell.ExecuteModes.Asynchronous
tempShell.Execute("lsof -u `whoami` ")
Do
tempShell.Poll
Loop Until Not tempShell.IsRunning
ListBox1.RemoveAllRows
If tempShell.Result <> "" Then
Var tempArray() As String = tempShell.Result.ToArray(EndOfLine)
For tempInt As Integer = 0 To tempArray.LastIndex
Listbox1.AddRow(tempArray(tempInt))
Next tempInt
End If
But when I sandbox it using AppWrapper I get the following tempShell.Result:
lsof: can’t get PID byte count: Operation not permitted
How can I run a sandboxed LSOF Shell command? Is there a way to not return the PID or PID byte count, as I don’t need them?
If your app is sandboxed, you shouldn’t be able to use lsof (except perhaps for your own process, but I’m not even sure), as that’s what the sandbox is here for.
Have you tried the entitlements in AppWrapper? I seem to recall there is one for using the shell…
I only want to access the open files of the current user (not every user) — that is why I am using -u whoami in the command.
I am not sure how the ‘id’ command would help me since I need to return my open files, not get info on my id.
I have not seen any Shell entitlements in AppWrapper — where are they? Or is there a plist entry for Shell access? Or is there a way to get LSOF to not return the PID values?
Sorry - I thought you were trying to pull the ID from the output.
As Thom mentions, Sandboxing prohibits lsof.
There’s no entitlements for shell since you’d need entitlements for the command line app that you’re executing IN the shell. Battled that one for years with the BRU command line tool. Ended up having to play sudoers games and the backup tools can’t be sandboxed (that would limit their usefulness in that case).
As far as i know it doesn’t. You just need to make sure you set the context, as shell works as a blank terminal without a profile and without settings.
I have found a solution that works using NSUserUnixTaskMBS. It will run any Script shell (MBS have a similar class for running AppleScripts too). It runs these outside of the App Sandbox, meaning you can break the normal rules.
Note that: your Shell Script must have the extension .sh, must be set with executable bit on via chmod +x, must have the #!/bin/bash shebang prefix and linefeeds for EndOfLine.
You have to manually place your Script file (myScript.sh) into the special read-only (to your app) Application Scripts (user drag or Open Folder). Set the output to a text file (normally not on Desktop!) — I had to send the output to a text file as I was unable to return the text Results in the executeFinished Event. Then Execute the Script (the cog icon will spin in the menu bar). I have created a ClassNSUserUnixTaskMBS that sets a Boolean isFinished to True when Event executeFinished runs (you could put your extra action code here instead).
Here is the code:
If Not NSUserScriptTaskMBS.Available Then
Return
End If
'Var f As FolderItem = NSUserUnixTaskMBS.ScriptFolder 'this should work, but always returns Nil
Var f As FolderItem = SpecialFolder.UserLibrary.Child("Application Scripts").Child(NSBundleMBS.mainBundle.bundleIdentifier).Child("myScript.sh") 'it needs executable bit on ie chmod +x /pathtofile/
If f = Nil Or Not f.Exists Then
Return
End If
Var tempNSErrorMBS As NSErrorMBS
Var tempNSUserUnixTaskMBS As ClassNSUserUnixTaskMBS
Try
tempNSUserUnixTaskMBS = New ClassNSUserUnixTaskMBS(f, tempNSErrorMBS)
Catch Error
Var ErrorMessage As String = Error.Message
Return
End Try
f = SpecialFolder.Desktop.Child("myResults.txt") 'the output file must exist
f.Remove
If f <> Nil And Not f.Exists Then
Var tempTextOutputStream As TextOutputStream = TextOutputStream.Create(f)
If tempTextOutputStream <> Nil Then
tempTextOutputStream.Close
End If
End If
Var tempNSFileHandleMBS As NSFileHandleMBS = NSFileHandleMBS.fileHandleForWritingToFile(f, tempNSErrorMBS)
If tempNSErrorMBS <> Nil Then
Var ErrorMessage As String = tempNSErrorMBS.Description
Return
End If
tempNSUserUnixTaskMBS.standardOutput = tempNSFileHandleMBS
tempNSUserUnixTaskMBS.execute
Do
DelayMBS 3.0
Thread.YieldToNext
Loop Until tempNSUserUnixTaskMBS.isFinished
In the context of this thread, I only meant that being allowed to run an LSOF Shell command was breaking the normal sandbox rules, but is in no way malware. Users can view my two line Shell Script as it is in plain text.
You are right, as this would add a new list of sandbox problems! I used the Desktop only for my testing and this example, but I use different code in my app. This was to allow others to test the code as easily as possible, and why I added “(normally not on Desktop!)”.