blob: 6b698acce653148706136a91a1c14209dfb1d9d8 [file] [log] [blame]
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +00001#include "defs.h"
2
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +00003/* these constants are the same as in <linux/capability.h> */
Dmitry V. Levinbf7fdfa2014-12-03 20:39:20 +00004enum {
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +00005#include "caps0.h"
Dmitry V. Levinbf7fdfa2014-12-03 20:39:20 +00006};
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +00007
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +00008#include "xlat/cap_mask0.h"
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +00009
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000010/* these constants are CAP_TO_INDEX'ed constants from <linux/capability.h> */
11enum {
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +000012#include "caps1.h"
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000013};
14
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +000015#include "xlat/cap_mask1.h"
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000016
17/* these constants are the same as in <linux/capability.h> */
Dmitry V. Levinbf7fdfa2014-12-03 20:39:20 +000018enum {
19 _LINUX_CAPABILITY_VERSION_1 = 0x19980330,
20 _LINUX_CAPABILITY_VERSION_2 = 0x20071026,
21 _LINUX_CAPABILITY_VERSION_3 = 0x20080522
22};
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000023
24#include "xlat/cap_version.h"
25
Dmitry V. Levinbf7fdfa2014-12-03 20:39:20 +000026typedef struct user_cap_header_struct {
27 uint32_t version;
28 int pid;
29} *cap_user_header_t;
30
31typedef struct user_cap_data_struct {
32 uint32_t effective;
33 uint32_t permitted;
34 uint32_t inheritable;
35} *cap_user_data_t;
36
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000037static cap_user_header_t
38get_cap_header(struct tcb *tcp, unsigned long addr)
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000039{
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000040 static struct user_cap_header_struct header;
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000041
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000042 if (!addr || !verbose(tcp))
43 return NULL;
44
45 if (umove(tcp, addr, &header) < 0)
46 return NULL;
47
48 return &header;
49}
50
51static void
52print_cap_header(struct tcb *tcp, unsigned long addr, cap_user_header_t h)
53{
Dmitry V. Levinc70da7c2015-07-20 17:50:56 +000054 if (!addr || !h) {
55 printaddr(addr);
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000056 return;
57 }
58
59 tprints("{");
60 printxval(cap_version, h->version,
61 "_LINUX_CAPABILITY_VERSION_???");
62 tprintf(", %d}", h->pid);
63}
64
65static void
66print_cap_bits(const uint32_t lo, const uint32_t hi)
67{
68 if (lo || !hi)
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +000069 printflags(cap_mask0, lo, "CAP_???");
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000070
71 if (hi) {
72 if (lo)
73 tprints("|");
Dmitry V. Levin2f0808b2015-02-18 23:59:50 +000074 printflags(cap_mask1, hi, "CAP_???");
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000075 }
76}
77
78static void
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000079print_cap_data(struct tcb *tcp, unsigned long addr, const cap_user_header_t h)
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000080{
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000081 struct user_cap_data_struct data[2];
82 unsigned int len;
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +000083
Dmitry V. Levinc70da7c2015-07-20 17:50:56 +000084 if (!addr || !h) {
85 printaddr(addr);
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000086 return;
87 }
88
89 if (_LINUX_CAPABILITY_VERSION_2 == h->version ||
90 _LINUX_CAPABILITY_VERSION_3 == h->version)
91 len = 2;
92 else
93 len = 1;
94
Dmitry V. Levinc70da7c2015-07-20 17:50:56 +000095 if (umoven_or_printaddr(tcp, addr, len * sizeof(data[0]), data))
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000096 return;
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +000097
98 tprints("{");
99 print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0);
100 tprints(", ");
101 print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0);
102 tprints(", ");
103 print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0);
104 tprints("}");
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000105}
106
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000107SYS_FUNC(capget)
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000108{
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +0000109 cap_user_header_t h;
110
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000111 if (entering(tcp)) {
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +0000112 h = get_cap_header(tcp, tcp->u_arg[0]);
113 print_cap_header(tcp, tcp->u_arg[0], h);
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000114 tprints(", ");
115 } else {
Dmitry V. Levin4b9c68b2014-12-05 00:21:23 +0000116 h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]);
117 print_cap_data(tcp, tcp->u_arg[1], h);
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000118 }
119 return 0;
120}
121
Dmitry V. Levina0bd3742015-04-07 01:36:50 +0000122SYS_FUNC(capset)
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000123{
Dmitry V. Levinff33aac2015-07-20 17:54:02 +0000124 cap_user_header_t h = get_cap_header(tcp, tcp->u_arg[0]);
125 print_cap_header(tcp, tcp->u_arg[0], h);
126 tprints(", ");
127 print_cap_data(tcp, tcp->u_arg[1], h);
128
129 return RVAL_DECODED;
Dmitry V. Levin5e7987b2014-12-03 20:30:15 +0000130}