Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

capability.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright (c) 2000 Wichert Akkerman <wakkerma@debian.org>
  3. * Copyright (c) 2011 Denys Vlasenko <dvlasenk@redhat.com>
  4. * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
  5. * Copyright (c) 2014-2018 The strace developers.
  6. * All rights reserved.
  7. *
  8. * SPDX-License-Identifier: LGPL-2.1-or-later
  9. */
  10. #include "defs.h"
  11. /* these constants are the same as in <linux/capability.h> */
  12. enum {
  13. #include "caps0.h"
  14. };
  15. #include "xlat/cap_mask0.h"
  16. /* these constants are CAP_TO_INDEX'ed constants from <linux/capability.h> */
  17. enum {
  18. #include "caps1.h"
  19. };
  20. #include "xlat/cap_mask1.h"
  21. /* these constants are the same as in <linux/capability.h> */
  22. enum {
  23. _LINUX_CAPABILITY_VERSION_1 = 0x19980330,
  24. _LINUX_CAPABILITY_VERSION_2 = 0x20071026,
  25. _LINUX_CAPABILITY_VERSION_3 = 0x20080522
  26. };
  27. #include "xlat/cap_version.h"
  28. struct user_cap_header_struct {
  29. uint32_t version;
  30. int pid;
  31. };
  32. struct user_cap_data_struct {
  33. uint32_t effective;
  34. uint32_t permitted;
  35. uint32_t inheritable;
  36. };
  37. static const struct user_cap_header_struct *
  38. get_cap_header(struct tcb *const tcp, const kernel_ulong_t addr)
  39. {
  40. static struct user_cap_header_struct header;
  41. if (!addr || !verbose(tcp))
  42. return NULL;
  43. if (umove(tcp, addr, &header) < 0)
  44. return NULL;
  45. return &header;
  46. }
  47. static void
  48. print_cap_header(struct tcb *const tcp, const kernel_ulong_t addr,
  49. const struct user_cap_header_struct *const h)
  50. {
  51. if (!addr || !h) {
  52. printaddr(addr);
  53. return;
  54. }
  55. tprints("{version=");
  56. printxval(cap_version, h->version,
  57. "_LINUX_CAPABILITY_VERSION_???");
  58. tprintf(", pid=%d}", h->pid);
  59. }
  60. static void
  61. print_cap_bits(const uint32_t lo, const uint32_t hi)
  62. {
  63. if (lo || !hi)
  64. printflags(cap_mask0, lo, "CAP_???");
  65. if (hi) {
  66. if (lo)
  67. tprints("|");
  68. printflags(cap_mask1, hi, "CAP_???");
  69. }
  70. }
  71. static void
  72. print_cap_data(struct tcb *const tcp, const kernel_ulong_t addr,
  73. const struct user_cap_header_struct *const h)
  74. {
  75. struct user_cap_data_struct data[2];
  76. unsigned int len;
  77. if (!addr || !h) {
  78. printaddr(addr);
  79. return;
  80. }
  81. if (_LINUX_CAPABILITY_VERSION_2 == h->version ||
  82. _LINUX_CAPABILITY_VERSION_3 == h->version)
  83. len = 2;
  84. else
  85. len = 1;
  86. if (umoven_or_printaddr(tcp, addr, len * sizeof(data[0]), data))
  87. return;
  88. tprints("{effective=");
  89. print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0);
  90. tprints(", permitted=");
  91. print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0);
  92. tprints(", inheritable=");
  93. print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0);
  94. tprints("}");
  95. }
  96. SYS_FUNC(capget)
  97. {
  98. const struct user_cap_header_struct *h;
  99. if (entering(tcp)) {
  100. h = get_cap_header(tcp, tcp->u_arg[0]);
  101. print_cap_header(tcp, tcp->u_arg[0], h);
  102. tprints(", ");
  103. } else {
  104. h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]);
  105. print_cap_data(tcp, tcp->u_arg[1], h);
  106. }
  107. return 0;
  108. }
  109. SYS_FUNC(capset)
  110. {
  111. const struct user_cap_header_struct *const h =
  112. get_cap_header(tcp, tcp->u_arg[0]);
  113. print_cap_header(tcp, tcp->u_arg[0], h);
  114. tprints(", ");
  115. print_cap_data(tcp, tcp->u_arg[1], h);
  116. return RVAL_DECODED;
  117. }