1 // SPDX-License-Identifier: LGPL-2.1 2 /* 3 * trace/beauty/fcntl.c 4 * 5 * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 6 */ 7 8 #include "trace/beauty/beauty.h" 9 #include <linux/kernel.h> 10 #include <uapi/linux/fcntl.h> 11 12 static size_t fcntl__scnprintf_getfd(unsigned long val, char *bf, size_t size) 13 { 14 return scnprintf(bf, size, "%s", val ? "CLOEXEC" : "0"); 15 } 16 17 static size_t syscall_arg__scnprintf_fcntl_getfd(char *bf, size_t size, struct syscall_arg *arg) 18 { 19 return fcntl__scnprintf_getfd(arg->val, bf, size); 20 } 21 22 static size_t fcntl__scnprintf_getlease(unsigned long val, char *bf, size_t size) 23 { 24 static const char *fcntl_setlease[] = { "RDLCK", "WRLCK", "UNLCK", }; 25 static DEFINE_STRARRAY(fcntl_setlease); 26 27 return strarray__scnprintf(&strarray__fcntl_setlease, bf, size, "%x", val); 28 } 29 30 static size_t syscall_arg__scnprintf_fcntl_getlease(char *bf, size_t size, struct syscall_arg *arg) 31 { 32 return fcntl__scnprintf_getlease(arg->val, bf, size); 33 } 34 35 size_t syscall_arg__scnprintf_fcntl_cmd(char *bf, size_t size, struct syscall_arg *arg) 36 { 37 if (arg->val == F_GETFL) { 38 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_open_flags); 39 goto mask_arg; 40 } 41 if (arg->val == F_GETFD) { 42 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getfd); 43 goto mask_arg; 44 } 45 if (arg->val == F_DUPFD_CLOEXEC || arg->val == F_DUPFD) { 46 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fd); 47 goto out; 48 } 49 if (arg->val == F_GETOWN) { 50 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_pid); 51 goto mask_arg; 52 } 53 if (arg->val == F_GETLEASE) { 54 syscall_arg__set_ret_scnprintf(arg, syscall_arg__scnprintf_fcntl_getlease); 55 goto mask_arg; 56 } 57 /* 58 * Some commands ignore the third fcntl argument, "arg", so mask it 59 */ 60 if (arg->val == F_GET_SEALS || 61 arg->val == F_GETSIG) { 62 mask_arg: 63 arg->mask |= (1 << 2); 64 } 65 out: 66 return syscall_arg__scnprintf_strarrays(bf, size, arg); 67 } 68 69 size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_arg *arg) 70 { 71 int cmd = syscall_arg__val(arg, 1); 72 73 if (cmd == F_DUPFD) 74 return syscall_arg__scnprintf_fd(bf, size, arg); 75 76 if (cmd == F_SETFD) 77 return fcntl__scnprintf_getfd(arg->val, bf, size); 78 79 if (cmd == F_SETFL) 80 return open__scnprintf_flags(arg->val, bf, size); 81 82 if (cmd == F_SETOWN) 83 return syscall_arg__scnprintf_pid(bf, size, arg); 84 85 if (cmd == F_SETLEASE) 86 return fcntl__scnprintf_getlease(arg->val, bf, size); 87 /* 88 * We still don't grab the contents of pointers on entry or exit, 89 * so just print them as hex numbers 90 */ 91 if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK || 92 cmd == F_OFD_SETLK || cmd == F_OFD_SETLKW || cmd == F_OFD_GETLK || 93 cmd == F_GETOWN_EX || cmd == F_SETOWN_EX || 94 cmd == F_GET_RW_HINT || cmd == F_SET_RW_HINT || 95 cmd == F_GET_FILE_RW_HINT || cmd == F_SET_FILE_RW_HINT) 96 return syscall_arg__scnprintf_hex(bf, size, arg); 97 98 return syscall_arg__scnprintf_long(bf, size, arg); 99 } 100