1 /*
2  * Copyright (C) 2017 by  <assafgordon@gmail.com>
3  *
4  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
5  */
6 //kbuild:lib-$(CONFIG_FEATURE_SETPRIV_CAPABILITIES) += capability.o
7 //kbuild:lib-$(CONFIG_RUN_INIT) += capability.o
8 
9 #include <linux/capability.h>
10 // #include <sys/capability.h>
11 // This header is in libcap, but the functions are in libc.
12 // Comment in the header says this above capset/capget:
13 /* system calls - look to libc for function to system call mapping */
14 extern int capset(cap_user_header_t header, cap_user_data_t data);
15 extern int capget(cap_user_header_t header, const cap_user_data_t data);
16 // so for bbox, let's just repeat the declarations.
17 // This way, libcap needs not be installed in build environment.
18 #include "libbb.h"
19 
20 static const char *const capabilities[] ALIGN_PTR = {
21 	"chown",
22 	"dac_override",
23 	"dac_read_search",
24 	"fowner",
25 	"fsetid",
26 	"kill",
27 	"setgid",
28 	"setuid",
29 	"setpcap",
30 	"linux_immutable",
31 	"net_bind_service",
32 	"net_broadcast",
33 	"net_admin",
34 	"net_raw",
35 	"ipc_lock",
36 	"ipc_owner",
37 	"sys_module",
38 	"sys_rawio",
39 	"sys_chroot",
40 	"sys_ptrace",
41 	"sys_pacct",
42 	"sys_admin",
43 	"sys_boot",
44 	"sys_nice",
45 	"sys_resource",
46 	"sys_time",
47 	"sys_tty_config",
48 	"mknod",
49 	"lease",
50 	"audit_write",
51 	"audit_control",
52 	"setfcap",
53 	"mac_override",
54 	"mac_admin",
55 	"syslog",
56 	"wake_alarm",
57 	"block_suspend",
58 	"audit_read",
59 };
60 
cap_name_to_number(const char * cap)61 unsigned FAST_FUNC cap_name_to_number(const char *cap)
62 {
63 	unsigned i, n;
64 
65 	if ((sscanf(cap, "cap_%u", &n)) == 1) {
66 		i = n;
67 		goto found;
68 	}
69 	for (i = 0; i < ARRAY_SIZE(capabilities); i++) {
70 		if (strcasecmp(capabilities[i], cap) == 0)
71 			goto found;
72 	}
73 	bb_error_msg_and_die("unknown capability '%s'", cap);
74 
75  found:
76 	if (!cap_valid(i))
77 		bb_error_msg_and_die("unknown capability '%s'", cap);
78 	return i;
79 }
80 
printf_cap(const char * pfx,unsigned cap_no)81 void FAST_FUNC printf_cap(const char *pfx, unsigned cap_no)
82 {
83 	if (cap_no < ARRAY_SIZE(capabilities)) {
84 		printf("%s%s", pfx, capabilities[cap_no]);
85 		return;
86 	}
87 	printf("%scap_%u", pfx, cap_no);
88 }
89 
90 DEFINE_STRUCT_CAPS;
91 
getcaps(void * arg)92 void FAST_FUNC getcaps(void *arg)
93 {
94 	static const uint8_t versions[] = {
95 		_LINUX_CAPABILITY_U32S_3, /* = 2 (fits into byte) */
96 		_LINUX_CAPABILITY_U32S_2, /* = 2 */
97 		_LINUX_CAPABILITY_U32S_1, /* = 1 */
98 	};
99 	int i;
100 	struct caps *caps = arg;
101 
102 	caps->header.pid = 0;
103 	for (i = 0; i < ARRAY_SIZE(versions); i++) {
104 		caps->header.version = versions[i];
105 		if (capget(&caps->header, NULL) == 0)
106 			goto got_it;
107 	}
108 	bb_simple_perror_msg_and_die("capget");
109  got_it:
110 
111 	switch (caps->header.version) {
112 		case _LINUX_CAPABILITY_VERSION_1:
113 			caps->u32s = _LINUX_CAPABILITY_U32S_1;
114 			break;
115 		case _LINUX_CAPABILITY_VERSION_2:
116 			caps->u32s = _LINUX_CAPABILITY_U32S_2;
117 			break;
118 		case _LINUX_CAPABILITY_VERSION_3:
119 			caps->u32s = _LINUX_CAPABILITY_U32S_3;
120 			break;
121 		default:
122 			bb_simple_error_msg_and_die("unsupported capability version");
123 	}
124 
125 	if (capget(&caps->header, caps->data) != 0)
126 		bb_simple_perror_msg_and_die("capget");
127 }
128