blob: ef09f7302b2657886a78337c20c27093a8a16b12 [file] [log] [blame]
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "args.h"
#include "symbol_offsets.h"
#include "openssl.h"
#include "node_tls.h"
static __inline void process_openssl_data(struct pt_regs* ctx, __u64 id, __u32 data_direction, struct sock_data_args_t* args, __u32 func_name) {
int bytes_count = PT_REGS_RC(ctx);
if (data_direction == SOCK_DATA_DIRECTION_INGRESS) {
// not reading finish, needs to keep reading
// NOTE: if the connection is server side role, and receive a unfinished message,
// the message type and protocol may could not be recognized.
// because some SSL framework only read one byte on each SSL_read method call,
// unless we save the buffer data, then process the SSL data.
size_t excepted_size = args->excepted_size;
if (bytes_count > 0 && bytes_count >= excepted_size) {
args->ssl_buffer_force_unfinished = 1;
}
}
process_write_data(ctx, id, args, bytes_count, data_direction, false, func_name, true);
}
static int get_fd_symaddr(__u32 tgid, bool read, void* ssl) {
struct openssl_symaddr* addr = get_openssl_symaddr(tgid);
if (addr == NULL) {
return -1;
}
__u32 bio_offset = read ? addr->bio_read_offset : addr->bio_write_offset;
__u32 fd_offset = addr->fd_offset;
void *bio = NULL;
bpf_probe_read(&bio, sizeof(bio), ssl + bio_offset);
__u32 fd;
bpf_probe_read(&fd, sizeof(fd), bio + fd_offset);
return fd;
}
static int get_fd(uint32_t tgid, bool read, void* ssl) {
int fd = 0;
fd = get_fd_symaddr(tgid, read, ssl);
if (fd > 2) {
return fd;
}
fd = get_node_tls_fd(tgid, ssl);
if (fd > 0) {
return fd;
}
return 0;
}
SEC("uprobe/ssl_write")
int openssl_write(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
__u32 tgid = id >> 32;
void* ssl = (void*)PT_REGS_PARM1(ctx);
__u32 fd = get_fd(tgid, false, ssl);
char* buf = (char*)PT_REGS_PARM2(ctx);
struct sock_data_args_t data_args = {};
data_args.fd = fd;
data_args.buf = buf;
data_args.start_nacs = bpf_ktime_get_ns();
bpf_map_update_elem(&openssl_sock_data_args, &id, &data_args, 0);
set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_SSL_WRITE);
return 0;
}
SEC("uretprobe/ssl_write")
int openssl_write_ret(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
if (args && args->fd > 0) {
args->data_id = ssl_get_data_id(2, id, args->fd);
process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_EGRESS, args, SOCKET_OPTS_TYPE_SSL_WRITE);
}
bpf_map_delete_elem(&openssl_sock_data_args, &id);
return 0;
}
SEC("uprobe/ssl_read")
int openssl_read(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
__u32 tgid = id >> 32;
void* ssl = (void*)PT_REGS_PARM1(ctx);
__u32 fd = get_fd(tgid, true, ssl);
char* buf = (char*)PT_REGS_PARM2(ctx);
size_t excepted_size = PT_REGS_PARM3(ctx);
struct sock_data_args_t data_args = {};
data_args.fd = fd;
data_args.buf = buf;
data_args.excepted_size = excepted_size;
data_args.start_nacs = bpf_ktime_get_ns();
bpf_map_update_elem(&openssl_sock_data_args, &id, &data_args, 0);
set_conn_as_ssl(ctx, tgid, fd, SOCKET_OPTS_TYPE_SSL_WRITE);
return 0;
}
SEC("uretprobe/ssl_read")
int openssl_read_ret(struct pt_regs* ctx) {
__u64 id = bpf_get_current_pid_tgid();
struct sock_data_args_t *args = bpf_map_lookup_elem(&openssl_sock_data_args, &id);
if (args && args->fd > 0) {
args->data_id = ssl_get_data_id(4, id, args->fd);
process_openssl_data(ctx, id, SOCK_DATA_DIRECTION_INGRESS, args, SOCKET_OPTS_TYPE_SSL_READ);
}
bpf_map_delete_elem(&openssl_sock_data_args, &id);
return 0;
}