Line data Source code
1 : /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 : /* gkd-capability.c - the security-critical initial phase of the daemon
3 : *
4 : * Copyright (C) 2011,2020 Steve Grubb
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * This program is distributed in the hope that it will be useful, but
12 : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see
18 : * <http://www.gnu.org/licenses/>.
19 : *
20 : * Author: Steve Grubb <sgrubb@redhat.com>
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include "gkd-capability.h"
26 :
27 : #ifdef HAVE_LIBCAPNG
28 : #include <cap-ng.h>
29 : #endif
30 :
31 : #include <stdio.h>
32 : #include <stdlib.h>
33 :
34 : #ifdef HAVE_LIBCAPNG
35 :
36 : /* No logging, no gettext */
37 : static void
38 : early_error (const char *err_string, int rc)
39 : {
40 : fprintf (stderr, "gnome-keyring-daemon: %s - %d, aborting\n",
41 : err_string, rc);
42 : exit (1);
43 : }
44 :
45 : static void
46 : early_warning (const char *warn_string)
47 : {
48 : if (!getenv ("GNOME_KEYRING_TEST_SERVICE"))
49 : fprintf (stderr, "gnome-keyring-daemon: %s\n", warn_string);
50 : }
51 :
52 : #endif /* HAVE_LIPCAPNG */
53 :
54 : /*
55 : * This program needs the CAP_IPC_LOCK posix capability.
56 : * We want to allow either setuid root or file system based capabilies
57 : * to work. If file system based capabilities, this is a no-op unless
58 : * the root user is running the program. In that case we just drop
59 : * capabilities down to IPC_LOCK. If we are setuid root, then change to the
60 : * invoking user retaining just the IPC_LOCK capability. The application
61 : * is aborted if for any reason we are unable to drop privileges.
62 : * Note: even gettext is unavailable!
63 : */
64 : void
65 27 : gkd_capability_obtain_capability_and_drop_privileges (void)
66 : {
67 : #ifdef HAVE_LIBCAPNG
68 : int rc;
69 :
70 : capng_get_caps_process ();
71 : switch (capng_have_capabilities (CAPNG_SELECT_CAPS))
72 : {
73 : case CAPNG_FULL:
74 : /* We are either setuid root or the root user */
75 : capng_clear (CAPNG_SELECT_CAPS);
76 : capng_update (CAPNG_ADD,
77 : CAPNG_EFFECTIVE|CAPNG_PERMITTED,
78 : CAP_IPC_LOCK);
79 : if ((rc = capng_change_id (getuid (), getgid (),
80 : CAPNG_DROP_SUPP_GRP|
81 : CAPNG_CLEAR_BOUNDING))) {
82 : early_error ("failed dropping capabilities",
83 : rc);
84 : }
85 : break;
86 : case CAPNG_FAIL:
87 : early_error ("error getting process capabilities", 0);
88 : break;
89 : case CAPNG_NONE:
90 : early_warning ("no process capabilities, insecure memory might get used");
91 : break;
92 : case CAPNG_PARTIAL: { /* File system based capabilities */
93 : capng_select_t set = CAPNG_SELECT_CAPS;
94 : if (!capng_have_capability (CAPNG_EFFECTIVE,
95 : CAP_IPC_LOCK)) {
96 : early_warning ("insufficient process capabilities, insecure memory might get used");
97 : }
98 :
99 : /* If we don't have CAP_SETPCAP, we can't update the
100 : * bounding set */
101 : if (capng_have_capability (CAPNG_EFFECTIVE,
102 : CAP_SETPCAP)) {
103 : set = CAPNG_SELECT_BOTH;
104 : }
105 :
106 : /* Drop all capabilities except ipc_lock */
107 : capng_clear (CAPNG_SELECT_BOTH);
108 : if ((rc = capng_update (CAPNG_ADD,
109 : CAPNG_EFFECTIVE|CAPNG_PERMITTED,
110 : CAP_IPC_LOCK)) != 0) {
111 : early_error ("error updating process capabilities", rc);
112 : }
113 : if ((rc = capng_apply (set)) != 0) {
114 : early_error ("error dropping process capabilities", rc);
115 : }} /* Extra brace for local variable declaration */
116 : break;
117 : }
118 : #endif /* HAVE_LIBCAPNG */
119 27 : }
|