/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright © 2025 Microsoft Corporation
* Copyright © 2026 Cloudflare, Inc.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM landlock
#if !defined(_TRACE_LANDLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_LANDLOCK_H
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/landlock.h>
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
#include <linux/tracepoint.h>
#include <linux/trace_seq.h>
#include <net/af_unix.h>
enum landlock_request_type;
struct dentry;
struct landlock_blockers;
struct landlock_domain;
struct landlock_hierarchy;
struct landlock_rule;
struct landlock_ruleset;
struct path;
struct sock;
struct task_struct;
static_assert(sizeof(access_mask_t) <= sizeof(u64));
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_CHANGE_TOPOLOGY);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_FS_ACCESS);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_NET_ACCESS);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_NAMESPACE);
TRACE_DEFINE_ENUM(LANDLOCK_REQUEST_CAPABILITY);
#ifdef CREATE_TRACE_POINTS
/* About 6 KiB, leaving about 2 KiB for sibling helpers and fixed fields. */
#define TRACE_UNTRUSTED_STR_OUTPUT_SIZE \
(TRACE_SEQ_BUFFER_SIZE - TRACE_SEQ_BUFFER_SIZE / 4)
/*
* A raw UTF-8 ellipsis (…) marks truncation and cannot collide with escaped
* input: ESCAPE_NAP renders every non-ASCII input byte in octal.
*/
#define TRACE_TRUNCATION_MARKER "\xe2\x80\xa6"
/*
* Escapes @len bytes of an untrusted string into the trace sequence @p so it
* cannot inject field separators or control characters into the ftrace text
* output, and can be unambiguously recovered. Called from the TP_printk() of
* the tracepoints that expose paths and process names. @len is passed by the
* caller (rather than derived with strlen()) so a name that is not
* NUL-terminated or carries embedded NUL bytes (an abstract socket name) is
* escaped in full instead of being truncated at the first NUL.
*
* Strings that exceed the output limit retain the largest complete escaped
* prefix followed by the truncation marker.
*
* Return: a pointer into @p's buffer, or NULL if @src is NULL or the fixed
* output reservation is unavailable.
*/
static inline const char *
__trace_print_untrusted_str(struct trace_seq *p, const char *src, size_t len)
{
const unsigned int escape_flags = ESCAPE_SPACE | ESCAPE_SPECIAL |
ESCAPE_NAP | ESCAPE_APPEND |
ESCAPE_OCTAL;
const size_t marker_len = sizeof(TRACE_TRUNCATION_MARKER) - 1;
size_t buf_size, prefix_len, prefix_size;
int escaped_size;
char *buf;
const char *ret;
buf_size = seq_buf_get_buf(&p->seq, &buf);
if (!src || buf_size < TRACE_UNTRUSTED_STR_OUTPUT_SIZE)
return NULL;
ret = trace_seq_buffer_ptr(p);
escaped_size = string_escape_mem(src, len, buf,
TRACE_UNTRUSTED_STR_OUTPUT_SIZE,
escape_flags, " ='\"\\");
if (likely(escaped_size < TRACE_UNTRUSTED_STR_OUTPUT_SIZE)) {
seq_buf_commit(&p->seq, escaped_size);
trace_seq_putc(p, 0);
return ret;
}
prefix_len = 0;
prefix_size = 0;
while (prefix_len < len) {
const char *const src_char = src + prefix_len;
int char_size