-
Notifications
You must be signed in to change notification settings - Fork 362
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
restructure i386 syscalls code in syscall lists
syscall lists are used so that we can have a common place to define: syscall ids for the tracepoint hook filtering, and syscall function symbols for the enforcer. The previous implementation of i386 syscalls in these lists was using the fact that (most) of the i386 syscalls are implemented using functions prefixed by __ia32_sys. This, however, is not true for ARM where most system calls have the same implementation for aarch32 and aarch64 and their prefix is __arm64. This means that for arm, we cannot determine the ABI of a system call from its function. Morover, x86_64 has two 32-bit abis: i386 and x32, and we might, eventually, want to add supoprt the latter. This patch reworks the code of the syscall lists. In syscall lists, users can now use the abi/ prefix (e.g., i386/) to specify system calls under a specific ABI. The commits adds a new SyscallVal type which represents values in a system call list. For this type, we imlement the two required methods: - ID(): get the id of the system call to pass in BPF - Symbol(): get the symbol that corresponds to the implementation of the syscall Signed-off-by: Kornilios Kourtis <[email protected]>
- Loading branch information
Showing
10 changed files
with
271 additions
and
123 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Authors of Tetragon | ||
|
||
package tracing | ||
|
||
import ( | ||
"fmt" | ||
"runtime" | ||
"strings" | ||
|
||
"github.com/cilium/tetragon/pkg/arch" | ||
"github.com/cilium/tetragon/pkg/syscallinfo" | ||
) | ||
|
||
// The code in this file deals with values found in syscall lists (type: "syscalls") | ||
// We need the following type of information for the values: | ||
// - ID(): a system call id | ||
// - Symbol(): the kernel function symbol that implements the syscall | ||
|
||
type SyscallVal string | ||
|
||
// return syscall id for value | ||
func (value SyscallVal) ID() (int, error) { | ||
abi, sc, err := parseSyscallValue(value) | ||
if err != nil { | ||
return -1, err | ||
} | ||
|
||
sc = strings.TrimPrefix(sc, "sys_") | ||
id, err := syscallinfo.SyscallID(sc, abi) | ||
if err != nil { | ||
return -1, fmt.Errorf("failed list '%s' cannot translate syscall '%s': %w", value, sc, err) | ||
} | ||
if abi == "i386" { | ||
id |= Is32Bit | ||
} | ||
return id, nil | ||
} | ||
|
||
func (v SyscallVal) Symbol() (string, error) { | ||
abi, sc, err := parseSyscallValue(v) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
var prefix string | ||
switch abi { | ||
case "x64": | ||
prefix = "__x64_" | ||
case "arm64": | ||
prefix = "__arm64_" | ||
case "i386": | ||
prefix = "__ia32_" | ||
default: | ||
return "", fmt.Errorf("unexpected error, unknown ABI: '%s'", abi) | ||
} | ||
|
||
return prefix + sc, nil | ||
} | ||
|
||
func validateABI(xarg, abi string) error { | ||
switch xarg { | ||
case "": | ||
// no arch | ||
if abi != "x64" && abi != "i386" && abi != "arm64" { | ||
return fmt.Errorf("invalid ABI: %s", abi) | ||
} | ||
case "amd64": | ||
if abi != "x64" && abi != "i386" { | ||
return fmt.Errorf("invalid ABI (%s) for arch (%s)", abi, xarg) | ||
} | ||
case "i386": | ||
if abi != "i386" { | ||
return fmt.Errorf("invalid ABI (%s) for arch (%s)", abi, xarg) | ||
} | ||
case "arm64": | ||
if abi != "arm64" { | ||
return fmt.Errorf("invalid ABI (%s) for arch (%s)", abi, xarg) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func defaultABI() (string, error) { | ||
switch a := runtime.GOARCH; a { | ||
case "amd64": | ||
return "x64", nil | ||
case "arm64": | ||
return "arm64", nil | ||
default: | ||
return "", fmt.Errorf("unsupported arch: %s", a) | ||
} | ||
|
||
} | ||
|
||
func parseSyscallValue(value SyscallVal) (abi string, name string, err error) { | ||
val := string(value) | ||
arr := strings.Split(string(val), "/") | ||
switch len(arr) { | ||
case 1: | ||
// Original version of this code tried to determine the abi by looking at the | ||
// prefix, so we maintain this behavior although it will not work for ARM32. | ||
var xarch string | ||
xarch, name = arch.CutSyscallPrefix(val) | ||
switch xarch { | ||
case "": | ||
abi, err = defaultABI() | ||
case "amd64": | ||
abi = "x64" | ||
case "i386": | ||
abi = "i386" | ||
case "arm64": | ||
abi = "arm64" | ||
} | ||
return | ||
|
||
case 2: | ||
xabi := arr[0] | ||
xarch, xname := arch.CutSyscallPrefix(arr[1]) | ||
if err = validateABI(xarch, xabi); err != nil { | ||
return | ||
} | ||
abi = xabi | ||
name = xname | ||
|
||
default: | ||
err = fmt.Errorf("invalid syscall value: '%s'", value) | ||
} | ||
return | ||
} |
Oops, something went wrong.