Branch data Line data Source code
1 : : /*
2 : : * dpkg - main program for package management
3 : : * selinux.c - SELinux support
4 : : *
5 : : * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
6 : : *
7 : : * This is free software; you can redistribute it and/or modify
8 : : * it under the terms of the GNU General Public License as published by
9 : : * the Free Software Foundation; either version 2 of the License, or
10 : : * (at your option) any later version.
11 : : *
12 : : * This is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : * GNU General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU General Public License
18 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <config.h>
22 : : #include <compat.h>
23 : :
24 : : #include <sys/types.h>
25 : : #include <sys/stat.h>
26 : :
27 : : #include <errno.h>
28 : : #include <unistd.h>
29 : :
30 : : #include <dpkg/i18n.h>
31 : : #include <dpkg/dpkg.h>
32 : : #include <dpkg/dpkg-db.h>
33 : :
34 : : #ifdef WITH_LIBSELINUX
35 : : #include <selinux/selinux.h>
36 : : #include <selinux/avc.h>
37 : : #include <selinux/label.h>
38 : : #endif
39 : :
40 : : #include "force.h"
41 : : #include "security-mac.h"
42 : :
43 : : #ifdef WITH_LIBSELINUX
44 : : static struct selabel_handle *sehandle;
45 : : #endif
46 : :
47 : : #ifdef WITH_LIBSELINUX
48 : : static int DPKG_ATTR_PRINTF(2)
49 : 0 : log_callback(int type, const char *fmt, ...)
50 : : {
51 : : va_list ap;
52 : : char *msg;
53 : :
54 [ # # ]: 0 : switch (type) {
55 : 0 : case SELINUX_ERROR:
56 : : case SELINUX_WARNING:
57 : : case SELINUX_AVC:
58 : 0 : break;
59 : 0 : default:
60 : 0 : return 0;
61 : : }
62 : :
63 : 0 : va_start(ap, fmt);
64 : 0 : m_vasprintf(&msg, fmt, ap);
65 : 0 : va_end(ap);
66 : :
67 : 0 : warning("selinux: %s", msg);
68 : 0 : free(msg);
69 : :
70 : 0 : return 0;
71 : : }
72 : : #endif
73 : :
74 : : void
75 : 0 : dpkg_selabel_load(void)
76 : : {
77 : : #ifdef WITH_LIBSELINUX
78 : : static int selinux_enabled = -1;
79 : :
80 [ # # ]: 0 : if (selinux_enabled < 0) {
81 : : int rc;
82 : :
83 : : /* Set selinux_enabled if it is not already set (singleton). */
84 [ # # # # ]: 0 : selinux_enabled = (in_force(FORCE_SECURITY_MAC) &&
85 : 0 : is_selinux_enabled() > 0);
86 [ # # ]: 0 : if (!selinux_enabled)
87 : 0 : return;
88 : :
89 : : /* Open the SELinux status notification channel, with fallback
90 : : * enabled for older kernels. */
91 : 0 : rc = selinux_status_open(1);
92 [ # # ]: 0 : if (rc < 0)
93 : 0 : ohshit(_("cannot open security status notification channel"));
94 : :
95 : 0 : selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) {
96 : : .func_log = log_callback,
97 : : });
98 [ # # # # ]: 0 : } else if (selinux_enabled && selinux_status_updated()) {
99 : : /* The SELinux policy got updated in the kernel, usually after
100 : : * upgrading the package shipping it, we need to reload. */
101 : 0 : selabel_close(sehandle);
102 : : } else {
103 : : /* SELinux is either disabled or it does not need a reload. */
104 : 0 : return;
105 : : }
106 : :
107 : 0 : sehandle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
108 [ # # # # ]: 0 : if (sehandle == NULL && security_getenforce() == 1)
109 : 0 : ohshite(_("cannot get security labeling handle"));
110 : : #endif
111 : : }
112 : :
113 : : void
114 : 0 : dpkg_selabel_set_context(const char *matchpath, const char *path, mode_t mode)
115 : : {
116 : : #ifdef WITH_LIBSELINUX
117 : 0 : char *scontext = NULL;
118 : : int ret;
119 : :
120 : : /* If SELinux is not enabled just do nothing. */
121 [ # # ]: 0 : if (sehandle == NULL)
122 : 0 : return;
123 : :
124 : : /*
125 : : * We use the _raw function variants here so that no translation
126 : : * happens from computer to human readable forms, to avoid issues
127 : : * when mcstransd has disappeared during the unpack process.
128 : : */
129 : :
130 : : /* Do nothing if we can't figure out what the context is, or if it has
131 : : * no context; in which case the default context shall be applied. */
132 : 0 : ret = selabel_lookup_raw(sehandle, &scontext, matchpath, mode & S_IFMT);
133 [ # # # # : 0 : if (ret < 0 || (ret == 0 && scontext == NULL))
# # ]
134 : 0 : return;
135 : :
136 : 0 : ret = lsetfilecon_raw(path, scontext);
137 [ # # # # ]: 0 : if (ret < 0 && errno != ENOTSUP)
138 : 0 : ohshite(_("cannot set security context for file object '%s'"),
139 : : path);
140 : :
141 : 0 : freecon(scontext);
142 : : #endif /* WITH_LIBSELINUX */
143 : : }
144 : :
145 : : void
146 : 0 : dpkg_selabel_close(void)
147 : : {
148 : : #ifdef WITH_LIBSELINUX
149 [ # # ]: 0 : if (sehandle == NULL)
150 : 0 : return;
151 : :
152 : 0 : selinux_status_close();
153 : 0 : selabel_close(sehandle);
154 : 0 : sehandle = NULL;
155 : : #endif
156 : : }
|