83 lines
2.5 KiB
Markdown
83 lines
2.5 KiB
Markdown
# hss_match_process / hss_match_port_token
|
|
|
|
**Source:** `hss-proc.h:12` and `hss-proc.h:19`
|
|
|
|
Heuristically determines whether a process's command line suggests it
|
|
owns a given port.
|
|
|
|
## hss_match_port_token
|
|
|
|
```c
|
|
static int hss_match_port_token(const char *args, const char *needle);
|
|
```
|
|
|
|
Checks whether `needle` (the port number as a string) appears in
|
|
`args` as a **whole token**, not as a substring of a larger number.
|
|
|
|
```c
|
|
size_t n = strlen(needle);
|
|
for (const char *p = args; (p = strstr(p, needle)); p++)
|
|
if ((p == args || p[-1] < '0' || p[-1] > '9') &&
|
|
(p[n] < '0' || p[n] > '9')) return 1;
|
|
return 0;
|
|
```
|
|
|
|
The boundary check: the character before and after the match must both
|
|
be non-digit (or the match is at the start/end of the string). This
|
|
prevents `8000` from matching inside `18000` or `80001`.
|
|
|
|
## hss_match_process
|
|
|
|
```c
|
|
static int hss_match_process(int port, const char *args, const char *needle);
|
|
```
|
|
|
|
Two-tier matching strategy:
|
|
|
|
### Tier 1: Known services
|
|
|
|
Hard-coded associations between well-known services and their ports:
|
|
|
|
| Service | Port(s) |
|
|
|---------|---------|
|
|
| `sshd` | 22 |
|
|
| `httpd`, `apache`, `nginx`, `lighttpd` | 80, 443 |
|
|
| `ftp` | 21 |
|
|
| `postgres` | 5432 |
|
|
| `redis` | 6379 |
|
|
| `mysql`, `mariadb` | 3306 |
|
|
|
|
If the command line contains the service name **and** the port matches,
|
|
it's a direct hit. No token-boundary check needed — `sshd` on port 22
|
|
is unambiguous.
|
|
|
|
### Tier 2: Interpreters
|
|
|
|
```c
|
|
return (strstr(args, "python") || strstr(args, "node") ||
|
|
strstr(args, "java") || strstr(args, "ruby")) &&
|
|
hss_match_port_token(args, needle);
|
|
```
|
|
|
|
For interpreted languages, the port number typically appears in the
|
|
command line (e.g., `python3 -m http.server 8000`, `node app.js 3000`).
|
|
The match requires **both**:
|
|
|
|
1. An interpreter name in the command line.
|
|
2. The port number as a whole token (via `hss_match_port_token`).
|
|
|
|
This avoids false positives — a `java` process whose command line
|
|
happens to contain `8000` as part of a heap size (`-Xmx8000m`) won't
|
|
match, because `8000` is adjacent to other digits.
|
|
|
|
## Limitations
|
|
|
|
- Only matches processes whose command line is visible via
|
|
`proc_getprocargs` (all processes, but the args may be truncated or
|
|
unavailable for kernel-internal tasks).
|
|
- Cannot detect a process that listens on a port without mentioning it
|
|
on the command line (e.g., a config-file-only port binding).
|
|
- The known-service table is static; new services require a code change.
|
|
|
|
This is the "heuristic" tradeoff: fast and dependency-free, but not
|
|
exhaustive.
|