162306a36Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * trace/beauty/prctl.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "trace/beauty/beauty.h"
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <uapi/linux/prctl.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include "trace/beauty/generated/prctl_option_array.c"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciDEFINE_STRARRAY(prctl_options, "PR_");
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic size_t prctl__scnprintf_option(int option, char *bf, size_t size, bool show_prefix)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", show_prefix, option);
1962306a36Sopenharmony_ci}
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size, bool show_prefix)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	static DEFINE_STRARRAY(prctl_set_mm_options, "PR_SET_MM_");
2462306a36Sopenharmony_ci	return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", show_prefix, option);
2562306a36Sopenharmony_ci}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	int option = syscall_arg__val(arg, 0);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	if (option == PR_SET_MM)
3262306a36Sopenharmony_ci		return prctl__scnprintf_set_mm(arg->val, bf, size, arg->show_string_prefix);
3362306a36Sopenharmony_ci	/*
3462306a36Sopenharmony_ci	 * We still don't grab the contents of pointers on entry or exit,
3562306a36Sopenharmony_ci	 * so just print them as hex numbers
3662306a36Sopenharmony_ci	 */
3762306a36Sopenharmony_ci	if (option == PR_SET_NAME)
3862306a36Sopenharmony_ci		return syscall_arg__scnprintf_hex(bf, size, arg);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	return syscall_arg__scnprintf_long(bf, size, arg);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	int option = syscall_arg__val(arg, 0);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	if (option == PR_SET_MM)
4862306a36Sopenharmony_ci		return syscall_arg__scnprintf_hex(bf, size, arg);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	return syscall_arg__scnprintf_long(bf, size, arg);
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg)
5462306a36Sopenharmony_ci{
5562306a36Sopenharmony_ci	unsigned long option = arg->val;
5662306a36Sopenharmony_ci	enum {
5762306a36Sopenharmony_ci                SPO_ARG2 = (1 << 1),
5862306a36Sopenharmony_ci                SPO_ARG3 = (1 << 2),
5962306a36Sopenharmony_ci                SPO_ARG4 = (1 << 3),
6062306a36Sopenharmony_ci                SPO_ARG5 = (1 << 4),
6162306a36Sopenharmony_ci                SPO_ARG6 = (1 << 5),
6262306a36Sopenharmony_ci        };
6362306a36Sopenharmony_ci	const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6;
6462306a36Sopenharmony_ci	const u8 all = SPO_ARG2 | all_but2;
6562306a36Sopenharmony_ci	const u8 masks[] = {
6662306a36Sopenharmony_ci		[PR_GET_DUMPABLE]	 = all,
6762306a36Sopenharmony_ci		[PR_SET_DUMPABLE]	 = all_but2,
6862306a36Sopenharmony_ci		[PR_SET_NAME]		 = all_but2,
6962306a36Sopenharmony_ci		[PR_GET_CHILD_SUBREAPER] = all_but2,
7062306a36Sopenharmony_ci		[PR_SET_CHILD_SUBREAPER] = all_but2,
7162306a36Sopenharmony_ci		[PR_GET_SECUREBITS]	 = all,
7262306a36Sopenharmony_ci		[PR_SET_SECUREBITS]	 = all_but2,
7362306a36Sopenharmony_ci		[PR_SET_MM]		 = SPO_ARG4 | SPO_ARG5 | SPO_ARG6,
7462306a36Sopenharmony_ci		[PR_GET_PDEATHSIG]	 = all,
7562306a36Sopenharmony_ci		[PR_SET_PDEATHSIG]	 = all_but2,
7662306a36Sopenharmony_ci	};
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	if (option < ARRAY_SIZE(masks))
7962306a36Sopenharmony_ci		arg->mask |= masks[option];
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	return prctl__scnprintf_option(option, bf, size, arg->show_string_prefix);
8262306a36Sopenharmony_ci}
83