blob: 5dbcf54f738be7ff3016d685e808eb27ec1c69c4 [file] [log] [blame]
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -04001/* Copyright (C) 2017 The Android Open Source Project
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "system.h"
17
18#include <errno.h>
19#include <fcntl.h>
20#include <net/if.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <string.h>
24#include <sys/ioctl.h>
25#include <sys/prctl.h>
26#include <sys/socket.h>
27#include <sys/stat.h>
28#include <unistd.h>
29
30#include "util.h"
31
32#ifdef HAVE_SECUREBITS_H
33#include <linux/securebits.h>
34#else
35#define SECURE_ALL_BITS 0x55
36#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
37#endif
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040038
39#define SECURE_BITS_NO_AMBIENT 0x15
40#define SECURE_LOCKS_NO_AMBIENT (SECURE_BITS_NO_AMBIENT << 1)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040041
42/*
43 * Assert the value of SECURE_ALL_BITS at compile-time.
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040044 * Android devices are currently compiled against 4.4 kernel headers. Kernel 4.3
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040045 * added a new securebit.
46 * When a new securebit is added, the new SECURE_ALL_BITS mask will return EPERM
47 * when used on older kernels. The compile-time assert will catch this situation
48 * at compile time.
49 */
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040050#if defined(__ANDROID__)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040051_Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55.");
52#endif
53
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070054int lock_securebits(uint64_t skip_mask)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040055{
56 /*
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040057 * Ambient capabilities can only be raised if they're already present
58 * in the permitted *and* inheritable set. Therefore, we don't really
59 * need to lock the NO_CAP_AMBIENT_RAISE securebit, since we are already
60 * configuring the permitted and inheritable set.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040061 */
Dylan Reida7f4fc92017-07-13 18:45:23 -070062 unsigned long securebits =
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070063 (SECURE_BITS_NO_AMBIENT | SECURE_LOCKS_NO_AMBIENT) & ~skip_mask;
64 if (!securebits) {
65 return 0;
66 }
67 int securebits_ret = prctl(PR_SET_SECUREBITS, securebits);
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040068 if (securebits_ret < 0) {
69 pwarn("prctl(PR_SET_SECUREBITS) failed");
70 return -1;
71 }
72
73 return 0;
74}
75
76int write_proc_file(pid_t pid, const char *content, const char *basename)
77{
78 int fd, ret;
79 size_t sz, len;
80 ssize_t written;
81 char filename[32];
82
83 sz = sizeof(filename);
84 ret = snprintf(filename, sz, "/proc/%d/%s", pid, basename);
85 if (ret < 0 || (size_t)ret >= sz) {
86 warn("failed to generate %s filename", basename);
87 return -1;
88 }
89
90 fd = open(filename, O_WRONLY | O_CLOEXEC);
91 if (fd < 0) {
92 pwarn("failed to open '%s'", filename);
93 return -errno;
94 }
95
96 len = strlen(content);
97 written = write(fd, content, len);
98 if (written < 0) {
99 pwarn("failed to write '%s'", filename);
100 return -1;
101 }
102
103 if ((size_t)written < len) {
104 warn("failed to write %zu bytes to '%s'", len, filename);
105 return -1;
106 }
107 close(fd);
108 return 0;
109}
110
111/*
112 * We specifically do not use cap_valid() as that only tells us the last
113 * valid cap we were *compiled* against (i.e. what the version of kernel
114 * headers says). If we run on a different kernel version, then it's not
115 * uncommon for that to be less (if an older kernel) or more (if a newer
116 * kernel).
117 * Normally, we suck up the answer via /proc. On Android, not all processes are
118 * guaranteed to be able to access '/proc/sys/kernel/cap_last_cap' so we
119 * programmatically find the value by calling prctl(PR_CAPBSET_READ).
120 */
121unsigned int get_last_valid_cap(void)
122{
123 unsigned int last_valid_cap = 0;
124 if (is_android()) {
125 for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0;
126 ++last_valid_cap)
127 ;
128
129 /* |last_valid_cap| will be the first failing value. */
130 if (last_valid_cap > 0) {
131 last_valid_cap--;
132 }
133 } else {
134 const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
135 FILE *fp = fopen(cap_file, "re");
136 if (fscanf(fp, "%u", &last_valid_cap) != 1)
137 pdie("fscanf(%s)", cap_file);
138 fclose(fp);
139 }
140 return last_valid_cap;
141}
142
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -0400143int cap_ambient_supported(void)
144{
145 return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >=
146 0;
147}
148
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400149int config_net_loopback(void)
150{
151 const char ifname[] = "lo";
152 int sock;
153 struct ifreq ifr;
154
155 /* Make sure people don't try to add really long names. */
156 _Static_assert(sizeof(ifname) <= IFNAMSIZ, "interface name too long");
157
158 sock = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
159 if (sock < 0) {
160 pwarn("socket(AF_LOCAL) failed");
161 return -1;
162 }
163
164 /*
165 * Do the equiv of `ip link set up lo`. The kernel will assign
166 * IPv4 (127.0.0.1) & IPv6 (::1) addresses automatically!
167 */
168 strcpy(ifr.ifr_name, ifname);
169 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
170 pwarn("ioctl(SIOCGIFFLAGS) failed");
171 return -1;
172 }
173
174 /* The kernel preserves ifr.ifr_name for use. */
175 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
176 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
177 pwarn("ioctl(SIOCSIFFLAGS) failed");
178 return -1;
179 }
180
181 close(sock);
182 return 0;
183}
184
185int setup_pipe_end(int fds[2], size_t index)
186{
187 if (index > 1)
188 return -1;
189
190 close(fds[1 - index]);
191 return fds[index];
192}
193
194int setup_and_dupe_pipe_end(int fds[2], size_t index, int fd)
195{
196 if (index > 1)
197 return -1;
198
199 close(fds[1 - index]);
200 /* dup2(2) the corresponding end of the pipe into |fd|. */
201 return dup2(fds[index], fd);
202}
203
204int write_pid_to_path(pid_t pid, const char *path)
205{
206 FILE *fp = fopen(path, "w");
207
208 if (!fp) {
209 pwarn("failed to open '%s'", path);
210 return -errno;
211 }
212 if (fprintf(fp, "%d\n", (int)pid) < 0) {
213 /* fprintf(3) does not set errno on failure. */
214 warn("fprintf(%s) failed", path);
215 return -1;
216 }
217 if (fclose(fp)) {
218 pwarn("fclose(%s) failed", path);
219 return -errno;
220 }
221
222 return 0;
223}
224
225/*
226 * setup_mount_destination: Ensures the mount target exists.
227 * Creates it if needed and possible.
228 */
229int setup_mount_destination(const char *source, const char *dest, uid_t uid,
230 uid_t gid)
231{
232 int rc;
233 struct stat st_buf;
234
235 rc = stat(dest, &st_buf);
236 if (rc == 0) /* destination exists */
237 return 0;
238
239 /*
240 * Try to create the destination.
241 * Either make a directory or touch a file depending on the source type.
242 * If the source doesn't exist, assume it is a filesystem type such as
243 * "tmpfs" and create a directory to mount it on.
244 */
245 rc = stat(source, &st_buf);
246 if (rc || S_ISDIR(st_buf.st_mode) || S_ISBLK(st_buf.st_mode)) {
247 if (mkdir(dest, 0700))
248 return -errno;
249 } else {
250 int fd = open(dest, O_RDWR | O_CREAT, 0700);
251 if (fd < 0)
252 return -errno;
253 close(fd);
254 }
255 return chown(dest, uid, gid);
256}