blob: 5e2a6f687a848286c946fec76fc8a30055511f7a [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
Jorge Lucangeli Obes54234212018-04-26 11:52:15 -040046int secure_noroot_set_and_locked(uint64_t mask)
47{
48 return (mask & (SECBIT_NOROOT | SECBIT_NOROOT_LOCKED)) ==
49 (SECBIT_NOROOT | SECBIT_NOROOT_LOCKED);
50}
51
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070052int lock_securebits(uint64_t skip_mask)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040053{
54 /*
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -040055 * Ambient capabilities can only be raised if they're already present
56 * in the permitted *and* inheritable set. Therefore, we don't really
57 * need to lock the NO_CAP_AMBIENT_RAISE securebit, since we are already
58 * configuring the permitted and inheritable set.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040059 */
Dylan Reida7f4fc92017-07-13 18:45:23 -070060 unsigned long securebits =
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070061 (SECURE_BITS_NO_AMBIENT | SECURE_LOCKS_NO_AMBIENT) & ~skip_mask;
62 if (!securebits) {
Jorge Lucangeli Obes54234212018-04-26 11:52:15 -040063 warn("not locking any securebits");
Luis Hector Chavezec0a2c12017-06-29 20:29:57 -070064 return 0;
65 }
66 int securebits_ret = prctl(PR_SET_SECUREBITS, securebits);
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -040067 if (securebits_ret < 0) {
68 pwarn("prctl(PR_SET_SECUREBITS) failed");
69 return -1;
70 }
71
72 return 0;
73}
74
75int write_proc_file(pid_t pid, const char *content, const char *basename)
76{
77 int fd, ret;
78 size_t sz, len;
79 ssize_t written;
80 char filename[32];
81
82 sz = sizeof(filename);
83 ret = snprintf(filename, sz, "/proc/%d/%s", pid, basename);
84 if (ret < 0 || (size_t)ret >= sz) {
85 warn("failed to generate %s filename", basename);
86 return -1;
87 }
88
89 fd = open(filename, O_WRONLY | O_CLOEXEC);
90 if (fd < 0) {
91 pwarn("failed to open '%s'", filename);
92 return -errno;
93 }
94
95 len = strlen(content);
96 written = write(fd, content, len);
97 if (written < 0) {
98 pwarn("failed to write '%s'", filename);
99 return -1;
100 }
101
102 if ((size_t)written < len) {
103 warn("failed to write %zu bytes to '%s'", len, filename);
104 return -1;
105 }
106 close(fd);
107 return 0;
108}
109
110/*
111 * We specifically do not use cap_valid() as that only tells us the last
112 * valid cap we were *compiled* against (i.e. what the version of kernel
113 * headers says). If we run on a different kernel version, then it's not
114 * uncommon for that to be less (if an older kernel) or more (if a newer
115 * kernel).
116 * Normally, we suck up the answer via /proc. On Android, not all processes are
117 * guaranteed to be able to access '/proc/sys/kernel/cap_last_cap' so we
118 * programmatically find the value by calling prctl(PR_CAPBSET_READ).
119 */
120unsigned int get_last_valid_cap(void)
121{
122 unsigned int last_valid_cap = 0;
123 if (is_android()) {
124 for (; prctl(PR_CAPBSET_READ, last_valid_cap, 0, 0, 0) >= 0;
125 ++last_valid_cap)
126 ;
127
128 /* |last_valid_cap| will be the first failing value. */
129 if (last_valid_cap > 0) {
130 last_valid_cap--;
131 }
132 } else {
133 const char cap_file[] = "/proc/sys/kernel/cap_last_cap";
134 FILE *fp = fopen(cap_file, "re");
135 if (fscanf(fp, "%u", &last_valid_cap) != 1)
136 pdie("fscanf(%s)", cap_file);
137 fclose(fp);
138 }
139 return last_valid_cap;
140}
141
Jorge Lucangeli Obesa6eb21a2017-04-20 10:44:00 -0400142int cap_ambient_supported(void)
143{
144 return prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_CHOWN, 0, 0) >=
145 0;
146}
147
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400148int config_net_loopback(void)
149{
150 const char ifname[] = "lo";
151 int sock;
152 struct ifreq ifr;
153
154 /* Make sure people don't try to add really long names. */
155 _Static_assert(sizeof(ifname) <= IFNAMSIZ, "interface name too long");
156
157 sock = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
158 if (sock < 0) {
159 pwarn("socket(AF_LOCAL) failed");
160 return -1;
161 }
162
163 /*
164 * Do the equiv of `ip link set up lo`. The kernel will assign
165 * IPv4 (127.0.0.1) & IPv6 (::1) addresses automatically!
166 */
167 strcpy(ifr.ifr_name, ifname);
168 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
169 pwarn("ioctl(SIOCGIFFLAGS) failed");
170 return -1;
171 }
172
173 /* The kernel preserves ifr.ifr_name for use. */
174 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
175 if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
176 pwarn("ioctl(SIOCSIFFLAGS) failed");
177 return -1;
178 }
179
180 close(sock);
181 return 0;
182}
183
184int setup_pipe_end(int fds[2], size_t index)
185{
186 if (index > 1)
187 return -1;
188
189 close(fds[1 - index]);
190 return fds[index];
191}
192
193int setup_and_dupe_pipe_end(int fds[2], size_t index, int fd)
194{
195 if (index > 1)
196 return -1;
197
198 close(fds[1 - index]);
199 /* dup2(2) the corresponding end of the pipe into |fd|. */
200 return dup2(fds[index], fd);
201}
202
203int write_pid_to_path(pid_t pid, const char *path)
204{
Mike Frysinger0b5cffa2017-08-15 18:06:18 -0400205 FILE *fp = fopen(path, "we");
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400206
207 if (!fp) {
208 pwarn("failed to open '%s'", path);
209 return -errno;
210 }
211 if (fprintf(fp, "%d\n", (int)pid) < 0) {
212 /* fprintf(3) does not set errno on failure. */
213 warn("fprintf(%s) failed", path);
214 return -1;
215 }
216 if (fclose(fp)) {
217 pwarn("fclose(%s) failed", path);
218 return -errno;
219 }
220
221 return 0;
222}
223
224/*
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500225 * Create the |path| directory and its parents (if need be) with |mode|.
226 * If not |isdir|, then |path| is actually a file, so the last component
227 * will not be created.
228 */
229int mkdir_p(const char *path, mode_t mode, bool isdir)
230{
yusukes059e0bd2018-03-05 10:22:16 -0800231 int rc;
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500232 char *dir = strdup(path);
yusukes059e0bd2018-03-05 10:22:16 -0800233 if (!dir) {
234 rc = errno;
235 pwarn("strdup(%s) failed", path);
236 return -rc;
237 }
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500238
239 /* Starting from the root, work our way out to the end. */
240 char *p = strchr(dir + 1, '/');
241 while (p) {
242 *p = '\0';
243 if (mkdir(dir, mode) && errno != EEXIST) {
yusukes059e0bd2018-03-05 10:22:16 -0800244 rc = errno;
245 pwarn("mkdir(%s, 0%o) failed", dir, mode);
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500246 free(dir);
yusukes059e0bd2018-03-05 10:22:16 -0800247 return -rc;
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500248 }
249 *p = '/';
250 p = strchr(p + 1, '/');
251 }
252
253 /*
254 * Create the last directory. We still check EEXIST here in case
255 * of trailing slashes.
256 */
257 free(dir);
yusukes059e0bd2018-03-05 10:22:16 -0800258 if (isdir && mkdir(path, mode) && errno != EEXIST) {
259 rc = errno;
260 pwarn("mkdir(%s, 0%o) failed", path, mode);
261 return -rc;
262 }
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500263 return 0;
264}
265
266/*
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400267 * setup_mount_destination: Ensures the mount target exists.
268 * Creates it if needed and possible.
269 */
270int setup_mount_destination(const char *source, const char *dest, uid_t uid,
Mike Frysingereaab4202017-08-14 14:57:21 -0400271 uid_t gid, bool bind)
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400272{
273 int rc;
274 struct stat st_buf;
Mike Frysingereaab4202017-08-14 14:57:21 -0400275 bool domkdir;
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400276
277 rc = stat(dest, &st_buf);
278 if (rc == 0) /* destination exists */
279 return 0;
280
281 /*
282 * Try to create the destination.
283 * Either make a directory or touch a file depending on the source type.
Mike Frysingereaab4202017-08-14 14:57:21 -0400284 *
285 * If the source isn't an absolute path, assume it is a filesystem type
286 * such as "tmpfs" and create a directory to mount it on. The dest will
287 * be something like "none" or "proc" which we shouldn't be checking.
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400288 */
Mike Frysingereaab4202017-08-14 14:57:21 -0400289 if (source[0] == '/') {
290 /* The source is an absolute path -- it better exist! */
291 rc = stat(source, &st_buf);
yusukes059e0bd2018-03-05 10:22:16 -0800292 if (rc) {
293 rc = errno;
294 pwarn("stat(%s) failed", source);
295 return -rc;
296 }
Mike Frysingereaab4202017-08-14 14:57:21 -0400297
298 /*
299 * If bind mounting, we only create a directory if the source
300 * is a directory, else we always bind mount it as a file to
301 * support device nodes, sockets, etc...
302 *
303 * For all other mounts, we assume a block/char source is
304 * going to want a directory to mount to. If the source is
305 * something else (e.g. a fifo or socket), this probably will
306 * not do the right thing, but we'll fail later on when we try
307 * to mount(), so shouldn't be a big deal.
308 */
309 domkdir = S_ISDIR(st_buf.st_mode) ||
310 (!bind && (S_ISBLK(st_buf.st_mode) ||
311 S_ISCHR(st_buf.st_mode)));
312 } else {
313 /* The source is a relative path -- assume it's a pseudo fs. */
314
315 /* Disallow relative bind mounts. */
yusukes059e0bd2018-03-05 10:22:16 -0800316 if (bind) {
317 warn("relative bind-mounts are not allowed: source=%s",
318 source);
Mike Frysingereaab4202017-08-14 14:57:21 -0400319 return -EINVAL;
yusukes059e0bd2018-03-05 10:22:16 -0800320 }
Mike Frysingereaab4202017-08-14 14:57:21 -0400321
322 domkdir = true;
323 }
324
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500325 /*
326 * Now that we know what we want to do, do it!
327 * We always create the intermediate dirs and the final path with 0755
328 * perms and root/root ownership. This shouldn't be a problem because
329 * the actual mount will set those perms/ownership on the mount point
330 * which is all people should need to access it.
331 */
yusukes059e0bd2018-03-05 10:22:16 -0800332 rc = mkdir_p(dest, 0755, domkdir);
333 if (rc)
334 return rc;
Mike Frysinger5fdba4e2018-01-17 15:39:48 -0500335 if (!domkdir) {
Mike Frysingereaab4202017-08-14 14:57:21 -0400336 int fd = open(dest, O_RDWR | O_CREAT | O_CLOEXEC, 0700);
yusukes059e0bd2018-03-05 10:22:16 -0800337 if (fd < 0) {
338 rc = errno;
339 pwarn("open(%s) failed", dest);
340 return -rc;
341 }
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400342 close(fd);
343 }
yusukes059e0bd2018-03-05 10:22:16 -0800344 if (chown(dest, uid, gid)) {
345 rc = errno;
346 pwarn("chown(%s, %u, %u) failed", dest, uid, gid);
347 return -rc;
348 }
yusukes76a9d742018-03-05 10:20:22 -0800349 return 0;
Jorge Lucangeli Obes0b208772017-04-19 14:15:46 -0400350}
Luis Hector Chavez71323552017-09-05 09:17:22 -0700351
352/*
353 * lookup_user: Gets the uid/gid for the given username.
354 */
355int lookup_user(const char *user, uid_t *uid, gid_t *gid)
356{
357 char *buf = NULL;
358 struct passwd pw;
359 struct passwd *ppw = NULL;
360 ssize_t sz = sysconf(_SC_GETPW_R_SIZE_MAX);
361 if (sz == -1)
362 sz = 65536; /* your guess is as good as mine... */
363
364 /*
365 * sysconf(_SC_GETPW_R_SIZE_MAX), under glibc, is documented to return
366 * the maximum needed size of the buffer, so we don't have to search.
367 */
368 buf = malloc(sz);
369 if (!buf)
370 return -ENOMEM;
371 getpwnam_r(user, &pw, buf, sz, &ppw);
372 /*
373 * We're safe to free the buffer here. The strings inside |pw| point
374 * inside |buf|, but we don't use any of them; this leaves the pointers
375 * dangling but it's safe. |ppw| points at |pw| if getpwnam_r(3)
376 * succeeded.
377 */
378 free(buf);
379 /* getpwnam_r(3) does *not* set errno when |ppw| is NULL. */
380 if (!ppw)
381 return -1;
382
383 *uid = ppw->pw_uid;
384 *gid = ppw->pw_gid;
385 return 0;
386}
387
388/*
389 * lookup_group: Gets the gid for the given group name.
390 */
391int lookup_group(const char *group, gid_t *gid)
392{
393 char *buf = NULL;
394 struct group gr;
395 struct group *pgr = NULL;
396 ssize_t sz = sysconf(_SC_GETGR_R_SIZE_MAX);
397 if (sz == -1)
398 sz = 65536; /* and mine is as good as yours, really */
399
400 /*
401 * sysconf(_SC_GETGR_R_SIZE_MAX), under glibc, is documented to return
402 * the maximum needed size of the buffer, so we don't have to search.
403 */
404 buf = malloc(sz);
405 if (!buf)
406 return -ENOMEM;
407 getgrnam_r(group, &gr, buf, sz, &pgr);
408 /*
409 * We're safe to free the buffer here. The strings inside gr point
410 * inside buf, but we don't use any of them; this leaves the pointers
411 * dangling but it's safe. pgr points at gr if getgrnam_r succeeded.
412 */
413 free(buf);
414 /* getgrnam_r(3) does *not* set errno when |pgr| is NULL. */
415 if (!pgr)
416 return -1;
417
418 *gid = pgr->gr_gid;
419 return 0;
420}