18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: LGPL-2.1
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * trace/beauty/prctl.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "trace/beauty/beauty.h"
98c2ecf20Sopenharmony_ci#include <linux/kernel.h>
108c2ecf20Sopenharmony_ci#include <uapi/linux/prctl.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include "trace/beauty/generated/prctl_option_array.c"
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ciDEFINE_STRARRAY(prctl_options, "PR_");
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistatic size_t prctl__scnprintf_option(int option, char *bf, size_t size, bool show_prefix)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", show_prefix, option);
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistatic size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size, bool show_prefix)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	static DEFINE_STRARRAY(prctl_set_mm_options, "PR_SET_MM_");
248c2ecf20Sopenharmony_ci	return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", show_prefix, option);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	int option = syscall_arg__val(arg, 0);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	if (option == PR_SET_MM)
328c2ecf20Sopenharmony_ci		return prctl__scnprintf_set_mm(arg->val, bf, size, arg->show_string_prefix);
338c2ecf20Sopenharmony_ci	/*
348c2ecf20Sopenharmony_ci	 * We still don't grab the contents of pointers on entry or exit,
358c2ecf20Sopenharmony_ci	 * so just print them as hex numbers
368c2ecf20Sopenharmony_ci	 */
378c2ecf20Sopenharmony_ci	if (option == PR_SET_NAME)
388c2ecf20Sopenharmony_ci		return syscall_arg__scnprintf_hex(bf, size, arg);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	return syscall_arg__scnprintf_long(bf, size, arg);
418c2ecf20Sopenharmony_ci}
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	int option = syscall_arg__val(arg, 0);
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	if (option == PR_SET_MM)
488c2ecf20Sopenharmony_ci		return syscall_arg__scnprintf_hex(bf, size, arg);
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	return syscall_arg__scnprintf_long(bf, size, arg);
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cisize_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg)
548c2ecf20Sopenharmony_ci{
558c2ecf20Sopenharmony_ci	unsigned long option = arg->val;
568c2ecf20Sopenharmony_ci	enum {
578c2ecf20Sopenharmony_ci                SPO_ARG2 = (1 << 1),
588c2ecf20Sopenharmony_ci                SPO_ARG3 = (1 << 2),
598c2ecf20Sopenharmony_ci                SPO_ARG4 = (1 << 3),
608c2ecf20Sopenharmony_ci                SPO_ARG5 = (1 << 4),
618c2ecf20Sopenharmony_ci                SPO_ARG6 = (1 << 5),
628c2ecf20Sopenharmony_ci        };
638c2ecf20Sopenharmony_ci	const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6;
648c2ecf20Sopenharmony_ci	const u8 all = SPO_ARG2 | all_but2;
658c2ecf20Sopenharmony_ci	const u8 masks[] = {
668c2ecf20Sopenharmony_ci		[PR_GET_DUMPABLE]	 = all,
678c2ecf20Sopenharmony_ci		[PR_SET_DUMPABLE]	 = all_but2,
688c2ecf20Sopenharmony_ci		[PR_SET_NAME]		 = all_but2,
698c2ecf20Sopenharmony_ci		[PR_GET_CHILD_SUBREAPER] = all_but2,
708c2ecf20Sopenharmony_ci		[PR_SET_CHILD_SUBREAPER] = all_but2,
718c2ecf20Sopenharmony_ci		[PR_GET_SECUREBITS]	 = all,
728c2ecf20Sopenharmony_ci		[PR_SET_SECUREBITS]	 = all_but2,
738c2ecf20Sopenharmony_ci		[PR_SET_MM]		 = SPO_ARG4 | SPO_ARG5 | SPO_ARG6,
748c2ecf20Sopenharmony_ci		[PR_GET_PDEATHSIG]	 = all,
758c2ecf20Sopenharmony_ci		[PR_SET_PDEATHSIG]	 = all_but2,
768c2ecf20Sopenharmony_ci	};
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (option < ARRAY_SIZE(masks))
798c2ecf20Sopenharmony_ci		arg->mask |= masks[option];
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	return prctl__scnprintf_option(option, bf, size, arg->show_string_prefix);
828c2ecf20Sopenharmony_ci}
83