blob: 74e97c253f2cdf1044be48c73d4a219b65d34291 [file] [log] [blame]
Mike Frysinger50e31fa2018-01-19 18:59:49 -05001/* Copyright 2017 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -04004 */
5
6#include "system.h"
7
8#include <errno.h>
9#include <fcntl.h>
Luis Hector Chavez71323552017-09-05 09:17:22 -070010#include <grp.h>
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040011#include <net/if.h>
Luis Hector Chavez71323552017-09-05 09:17:22 -070012#include <pwd.h>
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040013#include <stdbool.h>
14#include <stdio.h>
15#include <string.h>
16#include <sys/ioctl.h>
17#include <sys/prctl.h>
18#include <sys/socket.h>
19#include <sys/stat.h>
20#include <unistd.h>
21
22#include "util.h"
23
24#ifdef HAVE_SECUREBITS_H
25#include <linux/securebits.h>
26#else
27#define SECURE_ALL_BITS 0x55
28#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
29#endif
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040030
31#define SECURE_BITS_NO_AMBIENT 0x15
32#define SECURE_LOCKS_NO_AMBIENT (SECURE_BITS_NO_AMBIENT << 1)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040033
34/*
35 * Assert the value of SECURE_ALL_BITS at compile-time.
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040036 * Android devices are currently compiled against 4.4 kernel headers. Kernel 4.3
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040037 * added a new securebit.
38 * When a new securebit is added, the new SECURE_ALL_BITS mask will return EPERM
39 * when used on older kernels. The compile-time assert will catch this situation
40 * at compile time.
41 */
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040042#if defined(__ANDROID__)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040043_Static_assert(SECURE_ALL_BITS == 0x55, "SECURE_ALL_BITS == 0x55.");
44#endif
45
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070046int lock_securebits(uint64_t skip_mask)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040047{
48 /*
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040049 * Ambient capabilities can only be raised if they're already present
50 * in the permitted *and* inheritable set. Therefore, we don't really
51 * need to lock the NO_CAP_AMBIENT_RAISE securebit, since we are already
52 * configuring the permitted and inheritable set.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040053 */
Dylan Reida7f4fc92017-07-13 18:45:23 -070054 unsigned long securebits =
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070055 (SECURE_BITS_NO_AMBIENT | SECURE_LOCKS_NO_AMBIENT) & ~skip_mask;
56 if (!securebits) {
57 return 0;
58 }
59 int securebits_ret = prctl(PR_SET_SECUREBITS, securebits);
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040060 if (securebits_ret < 0) {
61 pwarn("prctl(PR_SET_SECUREBITS) failed");
62 return -1;
63 }
64
65 return 0;
66}
67
68int write_proc_file(pid_t pid, const char *content, const char *basename)
69{
70 int fd, ret;
71 size_t sz, len;
72 ssize_t written;
73 char filename[32];
74
75 sz = sizeof(filename);
76 ret = snprintf(filename, sz, "/proc/%d/%s", pid, basename);
77 if (ret < 0 || (size_t)ret >= sz) {
78 warn("failed to generate %s filename", basename);
79 return -1;
80 }
81
82 fd = open(filename, O_WRONLY | O_CLOEXEC);
83 if (fd < 0) {
84 pwarn("failed to open '%s'", filename);
85 return -errno;
86 }
87
88 len = strlen(content);
89 written = write(fd, content, len);
90 if (written < 0) {
91 pwarn("failed to write '%s'", filename);
92 return -1;
93 }
94
95 if ((size_t)written < len) {
96 warn("failed to write %zu bytes to '%s'", len, filename);
97 return -1;
98 }
99 close(fd);
100 return 0;
101}
102
103/*
104 * We specifically do not use cap_valid() as that only tells us the last
105 * valid cap we were *compiled* against (i.e. what the version of kernel
106 * headers says). If we run on a different kernel version, then it's not
107 * uncommon for that to be less (if an older kernel) or more (if a newer
108 * kernel).
109 * Normally, we suck up the answer via /proc. On Android, not all processes are
110 * guaranteed to be able to access '/proc/sys/kernel/cap_last_cap' so we
111 * programmatically find the value by calling prctl(PR_CAPBSET_READ).
112 */
113unsigned int get_last_valid_cap(void)
114{
115 unsigned int last_valid_cap = 0;
116 if (is_android()) {
117 for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0;
118 ++last_valid_cap)
119 ;
120
121 /* |last_valid_cap| will be the first failing value. */
122 if (last_valid_cap > 0) {
123 last_valid_cap--;
124 }
125 } else {
126 const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
127 FILE *fp = fopen(cap_file, "re");
128 if (fscanf(fp, "%u", &last_valid_cap) != 1)
129 pdie("fscanf(%s)", cap_file);
130 fclose(fp);
131 }
132 return last_valid_cap;
133}
134
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -0400135int cap_ambient_supported(void)
136{
137 return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >=
138 0;
139}
140
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400141int config_net_loopback(void)
142{
143 const char ifname[] = "lo";
144 int sock;
145 struct ifreq ifr;
146
147 /* Make sure people don't try to add really long names. */
148 _Static_assert(sizeof(ifname) <= IFNAMSIZ, "interface name too long");
149
150 sock = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
151 if (sock < 0) {
152 pwarn("socket(AF_LOCAL) failed");
153 return -1;
154 }
155
156 /*
157 * Do the equiv of `ip link set up lo`. The kernel will assign
158 * IPv4 (127.0.0.1) & IPv6 (::1) addresses automatically!
159 */
160 strcpy(ifr.ifr_name, ifname);
161 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
162 pwarn("ioctl(SIOCGIFFLAGS) failed");
163 return -1;
164 }
165
166 /* The kernel preserves ifr.ifr_name for use. */
167 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
168 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
169 pwarn("ioctl(SIOCSIFFLAGS) failed");
170 return -1;
171 }
172
173 close(sock);
174 return 0;
175}
176
177int setup_pipe_end(int fds[2], size_t index)
178{
179 if (index > 1)
180 return -1;
181
182 close(fds[1 - index]);
183 return fds[index];
184}
185
186int setup_and_dupe_pipe_end(int fds[2], size_t index, int fd)
187{
188 if (index > 1)
189 return -1;
190
191 close(fds[1 - index]);
192 /* dup2(2) the corresponding end of the pipe into |fd|. */
193 return dup2(fds[index], fd);
194}
195
196int write_pid_to_path(pid_t pid, const char *path)
197{
Mike Frysinger0b5cffa2017-08-15 18:06:18 -0400198 FILE *fp = fopen(path, "we");
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400199
200 if (!fp) {
201 pwarn("failed to open '%s'", path);
202 return -errno;
203 }
204 if (fprintf(fp, "%d\n", (int)pid) < 0) {
205 /* fprintf(3) does not set errno on failure. */
206 warn("fprintf(%s) failed", path);
207 return -1;
208 }
209 if (fclose(fp)) {
210 pwarn("fclose(%s) failed", path);
211 return -errno;
212 }
213
214 return 0;
215}
216
217/*
218 * setup_mount_destination: Ensures the mount target exists.
219 * Creates it if needed and possible.
220 */
221int setup_mount_destination(const char *source, const char *dest, uid_t uid,
Mike Frysingereaab4202017-08-14 14:57:21 -0400222 uid_t gid, bool bind)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400223{
224 int rc;
225 struct stat st_buf;
Mike Frysingereaab4202017-08-14 14:57:21 -0400226 bool domkdir;
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400227
228 rc = stat(dest, &st_buf);
229 if (rc == 0) /* destination exists */
230 return 0;
231
232 /*
233 * Try to create the destination.
234 * Either make a directory or touch a file depending on the source type.
Mike Frysingereaab4202017-08-14 14:57:21 -0400235 *
236 * If the source isn't an absolute path, assume it is a filesystem type
237 * such as "tmpfs" and create a directory to mount it on. The dest will
238 * be something like "none" or "proc" which we shouldn't be checking.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400239 */
Mike Frysingereaab4202017-08-14 14:57:21 -0400240 if (source[0] == '/') {
241 /* The source is an absolute path -- it better exist! */
242 rc = stat(source, &st_buf);
243 if (rc)
244 return -errno;
245
246 /*
247 * If bind mounting, we only create a directory if the source
248 * is a directory, else we always bind mount it as a file to
249 * support device nodes, sockets, etc...
250 *
251 * For all other mounts, we assume a block/char source is
252 * going to want a directory to mount to. If the source is
253 * something else (e.g. a fifo or socket), this probably will
254 * not do the right thing, but we'll fail later on when we try
255 * to mount(), so shouldn't be a big deal.
256 */
257 domkdir = S_ISDIR(st_buf.st_mode) ||
258 (!bind && (S_ISBLK(st_buf.st_mode) ||
259 S_ISCHR(st_buf.st_mode)));
260 } else {
261 /* The source is a relative path -- assume it's a pseudo fs. */
262
263 /* Disallow relative bind mounts. */
264 if (bind)
265 return -EINVAL;
266
267 domkdir = true;
268 }
269
270 /* Now that we know what we want to do, do it! */
271 if (domkdir) {
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400272 if (mkdir(dest, 0700))
273 return -errno;
274 } else {
Mike Frysingereaab4202017-08-14 14:57:21 -0400275 int fd = open(dest, O_RDWR | O_CREAT | O_CLOEXEC, 0700);
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400276 if (fd < 0)
277 return -errno;
278 close(fd);
279 }
280 return chown(dest, uid, gid);
281}
Luis Hector Chavez71323552017-09-05 09:17:22 -0700282
283/*
284 * lookup_user: Gets the uid/gid for the given username.
285 */
286int lookup_user(const char *user, uid_t *uid, gid_t *gid)
287{
288 char *buf = NULL;
289 struct passwd pw;
290 struct passwd *ppw = NULL;
291 ssize_t sz = sysconf(_SC_GETPW_R_SIZE_MAX);
292 if (sz == -1)
293 sz = 65536; /* your guess is as good as mine... */
294
295 /*
296 * sysconf(_SC_GETPW_R_SIZE_MAX), under glibc, is documented to return
297 * the maximum needed size of the buffer, so we don't have to search.
298 */
299 buf = malloc(sz);
300 if (!buf)
301 return -ENOMEM;
302 getpwnam_r(user, &pw, buf, sz, &ppw);
303 /*
304 * We're safe to free the buffer here. The strings inside |pw| point
305 * inside |buf|, but we don't use any of them; this leaves the pointers
306 * dangling but it's safe. |ppw| points at |pw| if getpwnam_r(3)
307 * succeeded.
308 */
309 free(buf);
310 /* getpwnam_r(3) does *not* set errno when |ppw| is NULL. */
311 if (!ppw)
312 return -1;
313
314 *uid = ppw->pw_uid;
315 *gid = ppw->pw_gid;
316 return 0;
317}
318
319/*
320 * lookup_group: Gets the gid for the given group name.
321 */
322int lookup_group(const char *group, gid_t *gid)
323{
324 char *buf = NULL;
325 struct group gr;
326 struct group *pgr = NULL;
327 ssize_t sz = sysconf(_SC_GETGR_R_SIZE_MAX);
328 if (sz == -1)
329 sz = 65536; /* and mine is as good as yours, really */
330
331 /*
332 * sysconf(_SC_GETGR_R_SIZE_MAX), under glibc, is documented to return
333 * the maximum needed size of the buffer, so we don't have to search.
334 */
335 buf = malloc(sz);
336 if (!buf)
337 return -ENOMEM;
338 getgrnam_r(group, &gr, buf, sz, &pgr);
339 /*
340 * We're safe to free the buffer here. The strings inside gr point
341 * inside buf, but we don't use any of them; this leaves the pointers
342 * dangling but it's safe. pgr points at gr if getgrnam_r succeeded.
343 */
344 free(buf);
345 /* getgrnam_r(3) does *not* set errno when |pgr| is NULL. */
346 if (!pgr)
347 return -1;
348
349 *gid = pgr->gr_gid;
350 return 0;
351}